#!/usr/bin/env python
import os
import sys
import argparse
import logging

def extend_sys_path(module_path, folders):
    root_path = os.path.dirname(os.path.dirname(module_path))
    for folder in folders:
        # Prepend path to the modules effectively prioritizing them.
        sys.path.insert(0, os.path.join(root_path, folder))
extend_sys_path(os.path.abspath(__file__), ('lib','src'))


from daemon.runner import DaemonRunner
from plato import getBasicLogger
from plato.application import PlatoApp


USER_HOME_DIR = os.path.expanduser('~/')
SCHEDULER = 'LOCAL'
APP_NAME = 'plato'
CONF_NAME = APP_NAME + '.conf'
DEBUG = True
APP_BIN_DIR = os.path.dirname(os.path.abspath(__file__))

logger = getBasicLogger(APP_NAME, logging.DEBUG)
is_interactive = False


def get_plato_app():
    plato_app = PlatoApp(APP_NAME, CONF_NAME, SCHEDULER,
                         is_interactive=is_interactive, debug=DEBUG,
                         logger=logger)    
    plato_app.load_config(APP_BIN_DIR)
    plato_app.validate_config()
    return plato_app


def get_scheduler():
    return get_plato_app().scheduler


# Below go functions that do actual work based on command line arguments
def run_as_daemon(args):
    plato_app = get_plato_app()    
    if not is_interactive:        
        app_argv = [sys.argv[0], args.action]
        daemon_runner = DaemonRunner(plato_app, app_argv)
        daemon_runner.do_action()
    else:
        plato_app.run()


def run_steps(args):    
    for index in range(args.times):
        get_plato_app().step()


def list(args):
    '''List plato registered jobs (not runner's like LSF).'''
    logger.info('listing jobs')
    scheduler = get_scheduler()
    jobs = scheduler.runner.list_jobs('*')
    print jobs


def submit(args):
    logger.info('submit job')
    if not args.batch_name:
        batch_name = os.path.basename(args.command.split()[0])
    info = dict()
    info['command'] = args.command
    if info['command'] == '-':
        # Treat standard input as submission shell line
        lines = [line for line in sys.stdin]
        if len(lines) > 1:
            raise Exception('Multiline command submission is not supported (yet)!')
        info['command'] = lines[0].strip()
    info['queue'] = args.queue if not args.queue else 'default'
    scheduler = get_scheduler()
    job = scheduler.monitor.new_job(batch_name)
    job.info = info
    if not scheduler.submit_job(job):
        logger.error('Failed to submit job: %s' % job)



class ArgumentParser(argparse.ArgumentParser):
    
    def error(self, message):        
        self.print_help(sys.stderr)
        self.exit(2, '%s: error: %s\n' % (self.prog, message))


if __name__ == '__main__':
    parser = ArgumentParser(description='Command-line interface for plato '
                            + 'batch submission system.')
    parser.add_argument('-i','--interactive', action='store_true', default=False)
    subparsers = parser.add_subparsers()
    
    # daemon
    parser_daemon = subparsers.add_parser('daemon')
    parser_daemon.add_argument('action', help="{start, stop, restart}")
    parser_daemon.set_defaults(func=run_as_daemon)

    # run
    parser_run = subparsers.add_parser('run')
    parser_run.add_argument('times', nargs='?', type=int, default=1)
    parser_run.set_defaults(func=run_steps)

    # list 
    parser_list = subparsers.add_parser('list')
    parser_list.set_defaults(func=list)
    
    # submit
    parser_submit = subparsers.add_parser('submit')
    parser_submit.add_argument('--queue', default='default')
    parser_submit.add_argument('--name', dest="batch_name", 
                               help="Job title or batch name")
    parser_submit.add_argument('command')
    parser_submit.set_defaults(func=submit)

    # Parse arguments.
    args = parser.parse_args()
    # On error this will print help and cause exit with explanation message.

    is_interactive = args.interactive
    args.func(args)
