#!/usr/bin/env python
"""Tron Control

Part of the command line interface to the tron daemon. Provides the interface
to controlling jobs and runs.
"""

import datetime
import logging
import optparse
import os.path
import sys
import urllib2
import urlparse

try:
    import simplejson
except ImportError:
    import json as simplejson

import yaml

import tron
from tron import cmd


COMMAND_HELP = (
    ('start', 'Start the selected job, job run, action, or service'),
    ('cancel', 'Cancel the selected job run'),
    ('disable', 'Disable selected job and cancel any outstanding runs'),
    ('enable', 'Enable the selected job and schedule the next run'),
    ('disableall', 'Disable all jobs'),
    ('enableall', 'Enable all jobs'),
    ('fail', 'Mark an UNKNOWN job as having failed'),
    ('succeed', 'Mark an UNKNOWN job as having succeeded'),
    ('stop', 'Stop the selected service'),
    ('zap', "Reset a service or service instance's status to DOWN without taking any other action"),
)


log = logging.getLogger('tronctl')


class TronCtlOptionParser(optparse.OptionParser):
    def format_epilog(self, formatter):
        # We want to include some extra helpful info
        result = []
        result.append(formatter.format_heading("Commands"))
        formatter.indent()
        for cmd, desc in COMMAND_HELP:
            result.append(formatter._format_text(''.join((cmd.ljust(20), desc.ljust(40)))))
            result.append('\n')

        result.append('\n')
        return ''.join(result)


def parse_date(option, opt_str, value, parser):
    parser.values.run_date = datetime.datetime.strptime(value, "%Y-%m-%d")


def parse_options():
    parser = TronCtlOptionParser(
        "usage: %prog [options] <command> [<job | job run | action>]",
        version="%%prog %s" % tron.__version__)

    parser.add_option("--server", action="store", dest="server", default=None,
                      help="Server URL to connect to")
    parser.add_option("--verbose", "-v", action="count", dest="verbose",
                      default=0, help="Verbose logging")
    parser.add_option("--run-date", action="callback", callback=parse_date,
                      type="string", dest="run_date",
                      help="For job starts, what should run date be set to")

    options, args = parser.parse_args(sys.argv)

    if len(args) < 2:
        parser.error("Missing command")

    return options, args[1:]


def edit(options, command, uri):
    data = {'command': command}
    if command == "start" and options.run_date:
        data['run_time'] = str(options.run_date)

    status, content = cmd.request(options.server, uri, data=data)

    if status == cmd.OK:
        log.info(content['result'])
        print content['result']
        return True
    else:
        return False


def main():
    """run tronctl"""
    options, args = parse_options()

    cmd.setup_logging(options)

    cmd.load_config(options)
    status, content = cmd.request(options.server, "/")
    if status != cmd.OK or not content:
        log.error("Error connecting to tron server at %s", options.server)
        sys.exit(1)

    command = args.pop(0)

    if not args:
        # our only non-object commands are for enabling and disabling jobs, so just
        # direct those commands here
        ret = edit(options, command, '/jobs')
    else:
        job_to_uri = cmd.make_job_to_uri(content)
        service_to_uri = cmd.make_service_to_uri(content)

        for obj_spec in args:
            try:
                full_uri = cmd.obj_spec_to_uri(obj_spec, job_to_uri, service_to_uri)
            except Exception:
                log.error('Unknown identifier: %s' % obj_spec)
                sys.exit(1)

            ret = edit(options, command, full_uri)

    cmd.save_config(options)
    if ret:
        sys.exit(0)
    else:
        sys.exit(1)

if __name__ == '__main__':
    main()
