import os, sys, pkg_resources

def elisa_main(splash, options):
    """ Parse command-line options and start a new Application in the
    Twisted's reactor.
    """
    from elisa.core.application import Application
    from twisted.internet import reactor
    from twisted.python import usage
    
    try:
        app = Application(options['config_file'],
                          show_tracebacks=options['tracebacks'],
                          splash=splash)
    except Exception, exc:
        print 'Error', exc
        if options['tracebacks']:
            raise
    else:
        def initialize_done(result):
            return app.start()

        def initialize_failure(failure):
            from elisa.core.utils.benchmark import ReportViewer
            from elisa.core.component import ComponentError
            from elisa.core.plugin_registry import PluginNotFound
            
            print 'Elisa failed to initialize', failure
            error_message = failure.getErrorMessage()
            extra_msg = ""
            if isinstance(failure.value, (ComponentError, PluginNotFound)):
                extra_msg = "You need to install at least elisa-plugins-good and elisa-plugins-bad bundles"

            if extra_msg:
                msg = "%s. %s" % (error_message, extra_msg)
            ReportViewer(msg=msg)

        # if initialize() succeeds go ahead and call start(),
        # otherwise stop the reactor
        dfr = app.initialize()
        dfr.addCallbacks(initialize_done, initialize_failure)

        # this could lead to an ugly "'NoneType' object is
        # unsubscriptable" in twisted, when the reactor gets killed from
        # the outside. Bug is reported and fixed in twisted-svn/trunk:
        # http://twistedmatrix.com/trac/ticket/2265
        reactor.addSystemEventTrigger('before', 'shutdown', app.stop)

def start_elisa_with_splash(options):
    from elisa.core.utils.splash_screen import SplashScreen

    # set up the screen
    splash = None
    if SplashScreen is not None:
        splash = SplashScreen()

    # set the main-method as something to get called, when the reactor
    # gets called the first time. Don't use callWhenRunning, because
    # it does get called before the splashscreen is created. Delay it
    # for a few time
    from twisted.internet import reactor
    reactor.callLater(0.01, elisa_main, splash, options)

def start_elisa_with_benchmark(options):
    from elisa.core.utils.process_observer import ProcessObserver
    from twisted.internet import reactor

    def got_result(result):
        if result == 1:
            reactor.stop()
        else:
            start_elisa_with_splash(options)
    
    # our simple procotol
    protocol = ProcessObserver()
    protocol.deferred.addCallback(got_result)

    path = os.path.split(sys.modules['elisa'].__path__[0])[0]
    env = dict(os.environ)
    env['PYTHONPATH'] = \
                os.pathsep.join(sys.path + [path])

    # FIXME: assuming that sys.argv[0] is the filename
    args = [sys.executable,  sys.argv[0], '--benchmark']

    # start the process
    process = reactor.spawnProcess(protocol,
                sys.executable, args, env=env)

def run():

    # install gst-python and the reactor
    from elisa.core import common
    common.boot()

    # import the option parsing and parse the options
    from twisted.python import usage
    from elisa.core.options import Options
    options = Options()

    args = sys.argv

    try:
        options.parseOptions(args[1:])
    except usage.UsageError, errortext:
        print '%s: %s' % (args[0], errortext)
        print '%s: Try --help for usage details.' % (args[0])
        sys.exit(1)

    if options['import']:
        # what to do?
        pass

    from twisted.internet import reactor

    if options['benchmark']:
        from elisa.core.utils.benchmark import run_benchmark
        reactor.callLater(0.01, run_benchmark, sys.exit)
        reactor.run()


    if not options['skip-benchmark']: 
        if options['config_file']:
            do_benchmark =  not os.path.exists(options['config_file'])
        else:
            do_benchmark = not os.path.exists(os.path.join( \
                                    os.path.expanduser('~'),
                                    '.elisa', 'elisa.conf') )

    if do_benchmark:
        start_elisa_with_benchmark(options)
    else:
        start_elisa_with_splash(options)

    reactor.run()
