# synarere -- a trivial, highly modular IRC bot.
# Copyright (C) 2010 Michael Rodriguez.
# Rights to this code are documented in ../docs/LICENSE.

'''Module API.'''

# Import required Python module.
import imp

# Import required source modules.
import logger, var, instance

# This is the IRC command hash table.
# This determines which functions are called
# when certain IRC events happen.
# This is initialised in irc.py.
irc_cmd = {}

# This is the IRC channel command hash table.
# This determines which functions are called
# when someone says certain things on IRC.
chan_cmd = {}

# This is the IRC channel addressed hash table.
# This determines which functions are called
# when someone addresses us on IRC.
chanme_cmd = {}

# This is the private message command hash table.
# This determines which functions are called
# when someone sends a certian PRIVMSG to the bot.
priv_cmd = {}

# This is the CTCP command hash table.
# This determines which functions are called
# when someone sends a certain CTCP.
ctcp_cmd = {}

def dispatch(hash, command, *args):
    '''Dispatch commands.'''

    logger.debug('Dispatching %s of type %s' % (command, hash))

    if hash[command]['first']:
        hash[command]['first'](*args)

    for func in hash[command]['funcs']:
        func(*args)

    if hash[command]['last']:
        hash[command]['last'](*args)

def create(event, func, hash):
    """Add a function to an event's list of functions."""

    event = event.upper()

    try:
        test = hash[event]
    except KeyError:
        hash[event] = { 'first' : None,
                        'funcs' : [],
                        'last' : None }

    if func in hash[event]['funcs']:
        return True

    else:
        hash[event]['funcs'].append(func)
        return True

def create_first(event, func, hash):
    """Add a function as an event's first function."""

    event = event.upper()

    try:
        test = hash[event]
    except KeyError:
        hash[event] = { 'first' : None,
                        'funcs' : [],
                        'last' : None }

    if hash[event]['first']:
        return False

    else:
        hash[event]['first'] = func
        return True

def destroy(event, func, hash):
    """Remove a function from an event's list of functions."""

    event = event.upper()

    if func not in hash[event]['funcs']:
        return False

    hash[event]['funcs'].remove(func)
    return True

def destroy_first(event, func, hash):
    """Remove a function as an event's first function."""

    event = event.upper()

    hash[event]['first'] = None

def load(module):
    '''Load a module.'''

    mod = None

    try:
        mod = imp.load_source(module, module)
    except ImportError, e:
        logger.error('Unable to load module %s: %s' % (module, e))
        return

    # Call the module's initialisation function.
    if not hasattr(mod, 'module_init'):
        logger.error('Entry point not found for module %s.' % mod.__name__)
        return

    mod.module_init()

    if not hasattr(mod, 'module_fini'):
        logger.error('Exit point not found for module %s.' % mod.__name__)
        return

    # Add it to the loaded modules list.
    var.modules_loaded.append(mod)
    logger.info('Module %s loaded successfully!' % mod.__name__)

def unload(mod):
    '''Unload a module.'''

    mod.module_fini()

    try:
        var.modules_loaded.remove(mod)
    except ValueError:
        logger.critical('Loaded module %s is not in the loaded modules list!' % mod.__name__)
        return

    logger.info('Module %s unloaded successfully!' % mod.__name__)

def load_all_from_conf():
    '''Load all modules listed in the configuration.'''

    try:
        for i in instance.conf.get('mload'):
            name = i.get('name')

            if name != None:
                load(name)
    except:
        pass

def unload_all():
    '''Unload all modules.'''

    for i in var.modules_loaded:
        unload(i)
