#!/usr/bin/env python
from __future__ import with_statement
import os
import tempfile
import optparse
import sys
import shutil

import tron
from tron import mcp, commands
from tron.commands.client import Client
from tron.config import config_parse


def parse_options():
    parser = optparse.OptionParser("usage: %prog [options] [-]",
                                   version="%%prog %s" % tron.__version__)

    parser.add_option("--print", "-p", action="store_true",
                      dest="print_config",
                      help="Print config to stdout, rather than uploading",
                      default=False)
    parser.add_option("--verbose", "-v", action="count", dest="verbose",
                      help="Verbose logging", default=0)
    parser.add_option("--server", action="store", dest="server",
                      help="Server URL to connect to", default=None)
    parser.add_option("--save", "-s", action="store_true", dest="save_config",
                      help="Save options used on this job for next time.",
                      default=False)
    (options, args) = parser.parse_args(sys.argv)

    options.from_stdin = False
    if args[-1] == "-":
        options.from_stdin = True

    return options


def upload_config(client, contents):
    client.config(contents)
    print "Configuration uploaded successfully"


def test_config(contents):
    tmpdir = tempfile.mkdtemp()

    # Can the MCP handle the configuration?
    try:
        config = config_parse.load_config(contents)
        master = mcp.MasterControlProgram(tmpdir, None)
        master.apply_config(config, skip_env_dependent=True)
        return True
    except Exception, e:
        print >>sys.stderr, "Error in configuration: %s" % str(e)

    finally:
        shutil.rmtree(tmpdir)


def edit_config(contents):
    fi = tempfile.NamedTemporaryFile(suffix='.yaml')
    fi.write(contents)
    fi.flush()

    editor = os.getenv('EDITOR') or os.getenv('VISUAL') or 'vim'
    while os.system("%s %s" % (editor, fi.name)):
        response = raw_input(
            "Editor returned an error. Continue editing? (y/n): ")
        if response[:1].lower() == 'n':
            return

    with open(fi.name) as upload_file:
        return upload_file.read()


if __name__ == '__main__':
    options = parse_options()
    commands.setup_logging(options)
    commands.load_config(options)
    client = Client(options)

    def finish(new_config):
        if options.print_config:
            print new_config
        else:
            upload_config(client, new_config)

        if options.save_config:
            # Save our command options (NOT THE CONFIG FILE)
            commands.save_config(options)
        sys.exit(0)

    if options.from_stdin:
        # We're taking config from stdin
        new_config = sys.stdin.read()
        if not test_config(new_config):
            sys.exit(1)
        finish(new_config)

    new_config = client.config()
    if not sys.stdout.isatty():
        # No editing possible, use the existing config
        finish(new_config)

    while True:
        new_config = edit_config(new_config)
        if not new_config:
            print >>sys.stderr, "Cancelling edit"
            sys.exit(1)

        if test_config(new_config):
            finish(new_config)

        response = raw_input(
            "There are errors in your configuration. Continue editing? (y/n): ")
        if response[:1].lower() == 'n':
            sys.exit(1)