#!/usr/bin/env python
# PYTHON_ARGCOMPLETE_OK
#
# Copyright 2017 QuantRocket - All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# to make argcomplete perky, limit imports to the minimum here and in
# subcommand modules
import sys
import six
import argparse
import pkgutil
from . import subcommands

def import_func(path):
    '''
    Imports and returns a function or class from a dot separated path.
    '''
    parts = path.split('.')
    module_path = parts[:-1]
    func_name = parts[-1]

    module = __import__('.'.join(module_path), fromlist=module_path[:-1])
    func = getattr(module, func_name)
    return func

def add_subcommands(subparsers):
    """
    Adds subparsers for each of the service modules in the subcommands package.
    """
    for _, service, _ in pkgutil.iter_modules(subcommands.__path__):
        func = import_func("quantrocket.cli.subcommands.{0}.add_subparser".format(service))
        func(subparsers)

def handle_error(msg):
    import logging
    import subprocess
    import os.path
    from ..flightlog import FlightlogHandler
    servicename_path = "/opt/conda/bin/servicename"
    if os.path.exists(servicename_path):
        servicename = subprocess.check_output([servicename_path], universal_newlines=True).strip()
    else:
        servicename = "cli"
    logger = logging.getLogger("quantrocket.{0}".format(servicename))
    handler = FlightlogHandler(background=False)
    logger.addHandler(handler)
    logger.error("Error running {0}".format(" ".join(sys.argv)))
    if not isinstance(msg, six.string_types):
        msg = repr(msg)
    for l in msg.splitlines():
        logger.error(l)

class ArgumentParser(argparse.ArgumentParser):
    """
    ArgumentParser that logs parsing errors to flightlog if not a tty.
    """
    def error(self, message):
        if not sys.stdin.isatty():
            handle_error(message)
        return super(ArgumentParser, self).error(message)

def get_parser():
    parser = ArgumentParser(description="QuantRocket command line interface")
    subparsers = parser.add_subparsers(title="commands", dest="command", help="for specific help type: quantrocket <subcommand> -h")
    subparsers.required = True
    add_subcommands(subparsers)
    return parser

def main():
    parser = get_parser()
    if sys.stdin.isatty():
        try:
            import argcomplete
        except ImportError:
            pass
        else:
            argcomplete.autocomplete(parser)
    args = parser.parse_args()
    args = vars(args)
    args.pop("command")
    args.pop("subcommand", None)
    func_name = args.pop("func")
    func = import_func(func_name)
    try:
        result, exit_code = func(**args)
    except:
        if not sys.stdin.isatty():
            import traceback
            msg = traceback.format_exc()
            handle_error(msg)
        raise
    else:
        if result:
            # nonzero exit codes for non-interactive commands should be
            # logged
            if exit_code > 0 and not sys.stdin.isatty() and not sys.stdout.isatty():
                handle_error(result)
                print(result)
            # otherwise print
            else:
                print(result)

        return exit_code

if __name__ == '__main__':
    sys.exit(main())
