import sys
import os
import pyccsm.ccsmprocutils as ccsmproc


##################################################################
# Public "Command" or "Action" Methods 
#        
# These are callable by the user by typing their name, and sending
# a list of space seperated arguements. The help text for each
# method is generated by its docstring.
###################################################################


def create_set(self, set=None, flags=None, *args):
    """Create a new CCSM set with attribute flags.
    
    usage: create_set <set-name> <flags>
    """
    if set is None:
        self.write("Error: No set name specified.\n")
        self.help("create_set")
        return
    if flags is None:
        self.write("Error: No flags specified.\n")
        self.help("create_set")
        return
    retval = self.ccsm_session.create_set(set,flags)
    if retval == 0:
        self.write("Created set %s\n" % set)
    else:
        self.write("Unable to create set %s (Error Code %i)\n" % (set, retval))

def destroy_set(self, set=None, *args):
    """Destroy a CCSM set.
    
    usage: destroy_set <set-name>
    """
    if set is None:
        self.write("Error: No set name specified.")
        self.help("destroy_set")
        return
    retval = self.ccsm_session.destroy_set(set)
    if retval == 0:
        self.write("Destroyed set %s\n" % set)
    else:
        self.write("Unable to destroy set %s (Error Code %i)\n" % (set, retval))


def add_member(self, set=None, member=None, *args):
    """Add a member CCSM Set to another CCSM Set.
    
    usage: add_member <set-name> <member-name>
    """
    if set is None:
        self.write("Error: No set name specified.\n")
        self.help("add_member")
        return
    if member is None:
        self.write("Error: No member name specified.\n")
        self.help("add_member")
        return
    retval = self.ccsm_session.add_member(set, member)
    if retval == 0:
        self.write("Added set %s to set %s\n" % (member,set))
    else:
        self.write("Unable to add set %s (Error Code %i)\n" % (member, retval))


def remove_member(self, set=None, member=None,*args):
    """Remove a member CCSM Set from a give CCSM Set.

    usage: remove_member <set-name> <member-name>
    """
    if set is None:
        self.write("Error: No set name specified.\n")
        self.help("add_member")
        return
    if member is None:
        self.write("Error: No member name specified.\n")
        self.help("add_member")
        return
    retval = self.ccsm_session.add_member(set, member)
    if retval == 0:
        self.write("Removed set %s from set %s\n" % (member,set))
    else:
        self.write("Unable to remove set %s (Error Code %i)\n" % (member, retval))

 

def create_component_self(self, component=None, *args):
    """Create a named Computation Component.

    usage: create_component_self <component-name> 
    """
    if component is None:
        self.write("Error: No component name specified.")
        self.help("create_component_self")
        return
    retval = self.ccsm_session.create_component_self(component)
    if retval == 0:
        self.write("Created component %s\n" % component)
    else:
        self.write("Unable to create component %s (Error Code %i)\n" % (component, retval))
    
    

def create_component_by_pid(self, component=None, pid=None, *args):
    """Create a named Component attached to a pid.
    
    usage: create_component_by_pid <component-name> <pid>
    """
    if component is None:
        self.write("Error: No component name specified.")
        self.help("create_component_by_pid")
        return
    if pid is None:
        self.write("Error: No component pid specified.")
        self.help("create_component_by_pid")
        return
    retval = self.ccsm_session.create_component_by_pid(component,pid)
    if retval == 0:
        self.write("Created component %s\n" % component)
    else:
        self.write("Unable to create component %s (Error Code %i)\n" % (component, retval))
    


def destroy_component_by_name(self, component=None,*args):
    """Destroy a named Computation Component.
    
    usage: destroy_component_by_name <component-name>
    """
    if component is None:
        self.write("Error: No component name specified.")
        self.help("destroy_component_by_name")
        return
    retval = self.ccsm_session.destroy_component_by_name(component)
    if retval == 0:
        self.write("Destroyed component %s\n" % component)
    else:
        self.write("Unable to destroy component %s (Error Code %i)\n" % (component, retval))
    

def destroy_component_by_pid(self, pid=None, *args):
    """Destroy a Computation Component by pid.

    usage: destroy_component_by_pid <pid>
    """
    if component is None:
        self.write("Error: No component name specified.")
        self.help("create_component_by_pid")
        return
    if pid is None:
        self.write("Error: No component pid specified.")
        self.help("create_component_by_pid")
        return
    retval = self.ccsm_session.destroy_component_by_pid(component,pid)
    if retval == 0:
        self.write("Destroy component %s\n" % component)
    else:
        self.write("Unable to destroy component %s (Error Code %i)\n" % (component, retval))
    


def print_sets(self, *args):
    """Prints all of sets on the system. 

    usage: print_sets
    """
    all_sets = ccsmproc.parse()
    for set in all_sets:
        set.pprint()
        

def quit(self, *args):
    """Immediately quit.
    """
    self.ccsm_session.close()
    sys.exit()

def help(self, *args):
    """Prints this help menu, or help about a specific command.
        
    usage: help [command-name]
    """
    show_extended_help = False

    # Filter function sent to the python filter() function that
    # specifies to filter item_strings that start with an
    # underscore or if they are a hidden action and not accessable
    # to the user anyway.
    filter_func = lambda item_string: \
        not item_string.startswith("_") and \
        not item_string in self.hidden_actions

    # Obtain the list of attributes for this class as specified by
    # filter_func
    menu_actions = filter(filter_func, dir(self))

    if len(args) > 0:
        # Specific help has been requested filter the specific
        # help topics by seeing if they exist in the help topics.
        temp_actions = filter( lambda item_string: item_string in args,
                                   menu_actions)
        if len(temp_actions) > 0:
            # The user inputted 1 or more valid help topics,
            # swtich the actions to be printed to the valid user
            # inputted help topics. Then switch the output mode to
            # extended.
            menu_actions = temp_actions
            show_extended_help = True

    for action_name in menu_actions:
        # For all actions that are valid attributes of this class,
        # first obtain that attribute object. We hope that it is a
        # callable method.
        method = getattr(self, action_name)
        if callable(method):
            # Great it is a callable method and has passed all of
            # the other filtering of attributes that should not be
            # accessable by the user.
                
            # Get the name of the method (name of the command)
            name = method.__name__
            # Get the docstring, which is used to generate the
            # help
            help_string = method.__doc__
                
            if not show_extended_help:
                # For the general help menu, just print out the
                # one line summary of the help. There is a little
                # string fomatting to make it easier to read.
                help_string = help_string.split('\n')
                if len(help_string) > 1:
                    help_string = help_string[0]
                    self.write(name.rjust(20)+" : ")
                    self.write(help_string.rjust(25)+"\n")
            else:
                # The user has specified a help topic about which
                # they want more information, so present all of
                # the help information about the topic. Obviously
                # formatted to be easier to read.
                self.write('\nHelp for command: %s\n\n' % name)
                for line in help_string.split('\n'):
                    line = line.strip()
                    self.write('    %s\n' % line)
