#!/opt/alt/python35/bin/python3
import argparse
import asyncio
import os
import sys
from contextlib import suppress

from defence360agent.cli import EXITCODE_GENERAL_ERROR, CliResponse
from defence360agent.contracts import config
from defence360agent.contracts.plugins import AddCliSubparser
from defence360agent.internals import logger as logging
from defence360agent.internals.plugin_manager import PluginManager
from defence360agent.internals.geo import Country
from defence360agent.simple_rpc import RpcClient, SocketError
from defence360agent.utils.validate import is_valid_ipv4_addr

logger = logging.getLogger(__name__)


class PMConfig(config.PluginManager):
    PLUGIN_DIR = 'cli'
    NAMESPACE = 'defence360agent.cli'
    DISABLED_MODULE_LIST = []


def main():
    gparser = argparse.ArgumentParser(
        description='CLI for %s.' % config.Core.NAME)

    gparser.add_argument(
        '--remote-addr',
        type=lambda ip: ip if is_valid_ipv4_addr(ip) else None,
        help="Client's IP address for adding it to the whitelist"
    )

    gparser.add_argument('--console-log-level',
                         choices=['ERROR', 'WARNING', 'INFO', 'DEBUG'],
                         help="Level of logging input to the console")

    subparsers = gparser.add_subparsers(
        help='Available commands')

    plugin_manager = PluginManager(config=PMConfig)
    for cli_plugin in plugin_manager.filter_plugins(AddCliSubparser):
        cli_plugin.add_to(subparsers)

    args = gparser.parse_args()

    # get ready to start: set conservative umask
    os.umask(config.Core.FILE_UMASK)

    if args.remote_addr:
        with suppress(SocketError):
            RpcClient().whitelist_current_user(
                ip=args.remote_addr,
                country=Country().get_id(args.remote_addr))
    if args.console_log_level:
        logging.setConsoleLogLevel(args.console_log_level)
    if hasattr(args, "call"):
        try:
            args.call(args)
        except SocketError:
            error = "Server is not started"
            CliResponse(error=error).print(*[getattr(args, flag, None)
                                             for flag in ("json", "verbose")])
    else:
        gparser.print_help()


if __name__ == '__main__':
    try:
        main()
        # ensure loop is closed to prevent asyncio warning
        # (https://bugs.python.org/issue23548)
        asyncio.get_event_loop().close()
    except Exception as e:
        logger.info('Unknown error happened. See logs for more information')
        logger.exception(e)
        sys.exit(EXITCODE_GENERAL_ERROR)
