#!/usr/bin/env python

# wrapper script that will get installed by setup.py into the execution path

import sys, logging
from optparse import OptionParser
import os
from os.path import join, dirname, exists, realpath, abspath

VERSION='0.22.2'

def handlebadplugin(plugin_error):
    logging.debug('Plugin error, %s.' % plugin_error)
    if plugin_error.reason == PLUGIN_ERRORS.unknown_plugin:
        logging.error('Cannot load plugin, %s.' % plugin_error.plugin_spec)
        return

    if plugin_error.reason == PLUGIN_ERRORS.missing_attribute:
        logging.error('Plugin, %s, doesn\'t have the needed plugin attribute, %s.' \
                % (plugin_error.plugin_spec, plugin_error.name))
        return

    if plugin_error.reason == PLUGIN_ERRORS.invalid_attribute:
        logging.error('Plugin, %s, has an invalid plugin attribute, %s.' \
                % (plugin_error.plugin_spec, plugin_error.name))
        return

    if plugin_error.reason == PLUGIN_ERRORS.missing_property:
        logging.error('Plugin, %s, requires the config option, %s, but it was missing.' \
                % (plugin_error.plugin_spec, plugin_error.name))
        return

# just provide the command line hook into the flashbake.commit module
if __name__ == "__main__":
    usage = "usage: %prog [options] <project_dir> [quiet_min]"

    parser = OptionParser(usage=usage, version='%s %s' % ('%prog', VERSION))
    parser.add_option('-c', '--context', dest='context_only',
            action='store_true', default=False,
            help='just generate and show the commit message, don\'t check for changes')
    parser.add_option('-v', '--verbose', dest='verbose',
            action='store_true', default=False,
            help='include debug information in the output')
    parser.add_option('-q', '--quiet', dest='quiet',
            action='store_true', default=False,
            help='disable all output excepts errors')
    parser.add_option('-d', '--dryrun', dest='dryrun',
            action='store_true', default=False,
            help='execute a dry run')
    parser.add_option('-p', '--plugins', dest='plugin_dir',
            action='store', type='string', metavar='PLUGIN_DIR',
            help='specify an additional location for plugins')

    (options, args) = parser.parse_args()

    if options.quiet and options.verbose:
        parser.error('Cannot specify both verbose and quiet')

    level = logging.INFO
    if options.verbose:
        level = logging.DEBUG

    if options.quiet:
        level = logging.ERROR

    logging.basicConfig(level=level,
            format='%(message)s')

    ######################################################################
    # Setup path (borrowed directly from gwibber)
    LAUNCH_DIR = abspath(sys.path[0])
    logging.debug("Launched from %s", LAUNCH_DIR)
    source_tree_flashbake = join(LAUNCH_DIR, "..", "flashbake")

    # If we were invoked from a flashbake source directory add that as the
    # preferred module path ...
    if exists(join(source_tree_flashbake, "commit.py")):
        logging.info("Running from source tree; adjusting path")
        sys.path.insert(0, realpath(dirname(source_tree_flashbake)))
        try:
            from flashbake.commit import commit, parsecontrol
            from flashbake.context import buildmessagefile
            from flashbake.plugins import PluginError, PLUGIN_ERRORS
        finally:
            del sys.path[0]
    else:
        logging.debug("Assuming path is correct")
        from flashbake.commit import commit, parsecontrol
        from flashbake.context import buildmessagefile
        from flashbake.plugins import PluginError, PLUGIN_ERRORS
    
    home_dir = os.path.expanduser('~')
    # look for plugin directory
    plugin_dir = join(home_dir, '.flashbake', 'plugins')
    if os.path.exists(plugin_dir):
        logging.debug('Plugin directory exists, adding.')
        sys.path.insert(0, realpath(plugin_dir))
    else:
        logging.debug('Plugin directory doesn\'t exist, skipping.')

    if options.plugin_dir != None:
        if os.path.exists(options.plugin_dir):
            logging.debug('Adding plugin directory, %s.' % options.plugin_dir)
            sys.path.insert(0, realpath(options.plugin_dir))
        else:
            logging.warn('Plugin directory, %s, doesn\'t exist.' % options.plugin_dir)

    if len(args) < 1:
        parser.error('Must specify project directory.')
        sys.exit(1)

    project_dir = args[0]

    # look for central config
    control_file = join(home_dir, '.flashbake', 'config')
    if os.path.exists(control_file):
        (hot_files, control_config) = parsecontrol(control_file)
    else:
        hot_files = None
        control_config = None

    control_file = join(project_dir, '.flashbake')

    # look for .control for backwards compatibility
    if not os.path.exists(control_file):
        control_file = join(project_dir, '.control')

    if not os.path.exists(control_file):
        parser.error('Could not find .flashbake or .control file in directory, "%s".' % project_dir)
        sys.exit(1)

    if options.context_only:
        try:
            (hot_files, control_config) = parsecontrol(control_file, control_config, hot_files)
            msg_filename = buildmessagefile(control_config)
            message_file = open(msg_filename, 'r')

            try:
                for line in message_file:
                    print line.strip()
            finally:
                message_file.close()
                os.remove(msg_filename)            
            sys.exit(0)
        except PluginError, error:
            handlebadplugin(error)
            sys.exit(1)

    quiet_period = 0
    if len(args) == 2:
        try:
            quiet_period = int(args[1])
        except:
            parser.error('Quiet minutes, "%s", must be a valid number.' % args[1])
            sys.exit(1)

    try:
        (hot_files, control_config) = parsecontrol(control_file, control_config, hot_files)
        commit(project_dir, control_config, hot_files, quiet_period, options.dryrun)
    except PluginError, error:
        handlebadplugin(error)
        sys.exit(1)
