#!/usr/bin/env python
""" Start the Tron server daemon."""
from __future__ import absolute_import
from __future__ import unicode_literals

import argparse
import logging
import os
import traceback

import IPython
import pkg_resources

import tron.mcp
from tron import trondaemon
from tron.commands import cmd_utils
from tron.config import manager

log = logging.getLogger(__name__)

DEFAULT_CONF = 'default_config.yaml'
DEFAULT_CONF_PATH = 'config/'
DEFAULT_WORKING_DIR = '/var/lib/tron/'
DEFAULT_LOCKFILE = 'tron-repl.lock'
DEFAULT_LOCKPATH = '/var/run/' + DEFAULT_LOCKFILE


def parse_cli():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        '--version',
        action='version',
        version="%s %s" % (parser.prog, tron.__version__),
    )

    parser.add_argument(
        "-w",
        "--working-dir",
        default=DEFAULT_WORKING_DIR,
        help="Working directory for the Tron daemon, default %(default)s",
    )

    parser.add_argument(
        "-c",
        "--config-path",
        default=DEFAULT_CONF_PATH,
        help="File path to the Tron configuration file",
    )

    parser.add_argument(
        "--nodaemon",
        action="store_true",
        default=False,
        help="[DEPRECATED] Disable daemonizing, default %(default)s",
    )

    parser.add_argument(  # for backwards compatibility
        "--pid-file",
        help="[DEPRECATED] File path to pid file. Use --lock-file instead."
    )

    parser.add_argument(
        "--lock-file",
        help="File path to lock file, defaults to %s if working directory "
        "is default. Otherwise defaults to <working dir>/%s" %
        (DEFAULT_LOCKPATH, DEFAULT_LOCKFILE),
    )

    logging_group = parser.add_argument_group('logging', '')
    logging_group.add_argument(
        "--log-conf",
        "-l",
        help="File path to a custom logging.conf",
    )

    logging_group.add_argument(
        "-v",
        "--verbose",
        action="count",
        default=0,
        help="Verbose logging. Repeat for more verbosity.",
    )

    logging_group.add_argument(
        "--debug",
        action="store_true",
        help="Debug mode, extra error reporting, no daemonizing",
    )

    api_group = parser.add_argument_group('Web Service API', '')
    api_group.add_argument(
        "--port",
        "-P",
        dest="listen_port",
        type=int,
        help="TCP port number to listen on, default %(default)s",
        default=cmd_utils.DEFAULT_PORT,
    )

    api_group.add_argument(
        "--host",
        "-H",
        dest="listen_host",
        help="Hostname to listen on, default %(default)s",
        default=cmd_utils.DEFAULT_HOST,
    )

    requirement = pkg_resources.Requirement.parse("tron")
    api_group.add_argument(
        "--web-path",
        default=pkg_resources.resource_filename(
            requirement,
            'tronweb',
        ),
        help="Path to static web resources, default %(default)s.",
    )

    args = parser.parse_args()
    args.working_dir = os.path.abspath(args.working_dir)

    if args.log_conf:
        args.log_conf = os.path.join(args.working_dir, args.log_conf)
        if not os.path.exists(args.log_conf):
            parser.error("Logging config file not found: %s" % args.log_conf, )

    if not args.lock_file:
        if args.pid_file:  # for backwards compatibility
            args.lock_file = args.pid_file
        elif args.working_dir == DEFAULT_WORKING_DIR:
            args.lock_file = DEFAULT_LOCKPATH
        else:
            args.lock_file = DEFAULT_LOCKFILE

    args.lock_file = os.path.join(args.working_dir, args.lock_file)
    args.config_path = os.path.join(
        args.working_dir,
        args.config_path,
    )

    return args


def create_default_config(config_path):
    """Create a default empty configuration for first time installs"""
    default = pkg_resources.resource_string(tron.__name__, DEFAULT_CONF)
    manager.create_new_config(config_path, default)


def setup_environment(args):
    """Setup the working directory and config environment."""
    if not os.path.exists(args.working_dir):
        os.makedirs(args.working_dir)

    if (
        not os.path.isdir(args.working_dir) or
        not os.access(args.working_dir, os.R_OK | os.W_OK | os.X_OK)
    ):
        msg = "Error, can't access working directory %s" % args.working_dir
        raise SystemExit(msg)

    # Attempt to create a default config if config is missing
    if not os.path.exists(args.config_path):
        try:
            create_default_config(args.config_path)
        except OSError as e:
            msg = "Error creating default configuration at %s: %s"
            log.debug(traceback.format_exc())
            raise SystemExit(msg % (args.config_path, e))

    if not os.access(args.config_path, os.R_OK | os.W_OK):
        msg = "Error opening configuration %s: Missing Permissions"
        raise SystemExit(msg % args.config_path)


def main():
    args = parse_cli()

    setup_environment(args)
    trond = trondaemon.TronDaemon(args)  # noqa: F841

    trond.mcp = tron.mcp.MasterControlProgram(
        trond.options.working_dir,
        trond.options.config_path,
    )
    trond.mcp._load_config()
    # trond.mcp.restore_state(trond.mcp.config.load().get_master().action_runner)

    # mcp = trond.mcp  # noqa: F841
    # store = mcp.state_watcher.state_manager._impl  # noqa: F841

    print("")
    print("+---------------------+")
    print("| Tron REPL           |")
    print("|   Available locals: |")
    print("|   - trond           |")
    print("+---------------------+")
    print("")
    IPython.embed()


if __name__ == '__main__':
    main()
