#!/usr/bin/env python
"""
phenny - An IRC Bot
Copyright 2008, Sean B. Palmer, inamidst.com
Licensed under the Eiffel Forum License 2.

http://inamidst.com/phenny/

Note: DO NOT EDIT THIS FILE.
Run ./phenny, then edit ~/.phenny/default.py
Then run ./phenny again
"""

import sys, os, imp, optparse, logging
from textwrap import dedent as trim

log = logging.getLogger(__name__)
handler = logging.StreamHandler(sys.stdout)
f = logging.Formatter("[%(levelname)s] phenny: %(message)s", None)
handler.setFormatter(f)
log.addHandler(handler)
log.level = logging.DEBUG

def check_python_version(): 
   if sys.version_info < (2, 4): 
      error = 'Error: Requires Python 2.4 or later, from www.python.org'
      log.error(error)
      sys.exit(1)

def create_default_config(fn): 
   f = open(fn, 'w')
   print >> f, trim("""\
   nick = 'phenny'
   host = 'irc.example.net'
   channels = ['#example', '#test']
   owner = 'yournickname'

   # password is the NickServ password, serverpass is the server password
   # password = 'example'
   # serverpass = 'serverpass'

   # These are people who will be able to use admin.py's functions...
   admins = [owner, 'someoneyoutrust']
   # But admin.py is disabled by default, as follows:
   exclude = ['admin']

   # If you want to enumerate a list of modules rather than disabling
   # some, use "enable = ['example']", which takes precedent over exclude
   # 
   # enable = []

   # Directories to load user modules from
   # e.g. /path/to/my/modules
   extra = []

   # Services to load: maps channel names to white or black lists
   external = { 
      '#liberal': ['!'], # allow all
      '#conservative': [], # allow none
      '*': ['!'] # default whitelist, allow all
   }

   homedir = '%s'

   # EOF
   """ % (os.path.dirname(os.path.abspath(fn)), )
   )
   f.close()

def check_config(config):
   if len(config) == 0:
      log.info('No config file found. Creating `config.py`')

      # TODO: confirm with user before create file
      create_default_config('config.py')

      log.info('Generated default config in `config.py`')
      log.info('Edit this file and rerun the command')
      return False
   return True

def config_names(config): 
   config = config or 'config'

   def files(d): 
      names = os.listdir(d)
      return list(os.path.join(d, fn) for fn in names if fn.endswith('.py'))

   here = os.path.join('.', config)
   if os.path.isfile(here): 
      return [here]
   if os.path.isfile(here + '.py'): 
      return [here + '.py']
   if os.path.isdir(here): 
      return files(here)

   return []

def main(argv=None): 
   # Step One: Parse The Command Line

   parser = optparse.OptionParser('%prog [options]')
   parser.add_option('-c', '--config', metavar='fn', 
      help='use this configuration file or directory')
   opts, args = parser.parse_args(argv)
   if args: log.error('Warning: ignoring spurious arguments')

   config = config_names(opts.config)
   
   # Step Two: Check Dependencies

   check_python_version() # require python2.4 or later
   check_config(config) # require a config file, if none are found, create one and exit

   # Step Three: Load The Configurations

   config_modules = []
   for config_name in config:
      basename = os.path.basename(config_name).split('.')[0]
      if basename == 'config': basename = 'default'
      
      name = basename + '_config'
      module = imp.load_source(name, config_name)
      module.filename = config_name

      if not hasattr(module, 'prefix'): 
         module.prefix = r'\.'

      if not hasattr(module, 'name'): 
         module.name = 'Phenny Palmersbot, http://inamidst.com/phenny/'

      if not hasattr(module, 'port'): 
         module.port = 6667

      if not hasattr(module, 'password'): 
         module.password = None

      if module.host == 'irc.example.net': 
         error = ('you must edit the config file first!\n' + 
                  "You're currently using %s" % module.filename)
         log.error(error)
         sys.exit(1)

      if not os.path.isdir(getattr(module, 'homedir', False)):
         module.homedir = os.path.dirname(os.path.abspath(config_name))
      
      vardir = os.path.join(module.homedir, 'var')
      if not os.path.isdir(vardir):
         log.info('No `var` directory found, creating one to store module data')
         os.mkdir(vardir)

      module.vardir = vardir

      config_modules.append(module)

   # Step Four: Load Phenny

   try: from __init__ import run
   except ImportError: 
      try: from phenny import run
      except ImportError: 
         log.error("Error: Couldn't find phenny to import")
         sys.exit(1)

   # Step Five: Initialise And Run The Phennies

   # @@ ignore SIGHUP
   for config_module in config_modules: 
      run(config_module) # @@ thread this

if __name__ == '__main__': 
   main()
