#!/usr/bin/env python

# Copyright (C) 2014:
#    Gabes Jean, naparuba@gmail.com

# We do not want the warnings print to stderr to pop out in the CLI or the agent
# NOTe: the warnings.filterwarnings('ignore') is not working with some warnings
# like in debian9 SSL, so use another way
import warnings


def _disable_warns(*args, **kwargs):
    pass


warnings.showwarning = _disable_warns

import optparse
import sys
import os

CLI = None



CONFIG = {}


def print_full_help():
    if is_tty():
        cprint(BANNER)
    else:
        cprint(TXT_BANNER, color='blue')
    # Also print some quotes
    quote, from_film = get_quote()
    cprint('  >> %s  (%s)\n' % (quote, from_film), color='grey')
    
    parser.print_help()
    CLI.print_list()


if __name__ == '__main__':
    parser = optparse.OptionParser('', version="%prog ", add_help_option=False)
    parser.add_option('--debug', action='store_true', dest="do_debug", help=("Enable the debug mode"))
    # parser.add_option('--proxy', dest="proxy", help="""Proxy URI. Like http://user:password@proxy-server:3128""")
    parser.add_option('-l', '--list', action='store_true', dest="do_list", help=("List available commands"))
    
    parser.add_option('-c', '--config', dest="ymlconfig", default='', help=("Path to your local.yml file."))
    parser.add_option('-v', action='store_true', dest="do_verbose", help=("Be more verbose"))
    parser.add_option('-h', '--help', action='store_true', dest="do_help", help=("Print help"))
    
    # First parsing, for purely internal parameters, but disable
    # errors, because we only want to see the -D -v things
    old_error = parser.error
    parser.error = lambda x: 1
    opts, args = parser.parse_args()
    # reenable the errors for later use
    parser.error = old_error
    
    # We need to import our libs, but can be an install or directly in the tarball (if executed directly from the install tar ball)
    install_less = False
    # In windows exe, __file__ is not set
    if not hasattr(sys, 'frozen'):
	    my_file = os.path.abspath(os.path.dirname(__file__))
    else:
	    my_file = os.path.dirname(os.path.abspath(sys.argv[0]))
    my_root_dir = os.path.dirname(my_file)
    # Both files must be present
    tar_ball_detection_files = (os.path.join(my_root_dir, 'README.md'), os.path.join(my_root_dir, 'setup.py'))
    if os.path.exists(tar_ball_detection_files[0]) and os.path.exists(tar_ball_detection_files[1]):
        install_less = True
        # Be sure that the opsbro lib is the install root one
        sys.path.insert(0, my_root_dir)
        from opsbro.defaultpaths import remap_from_install_dir
        
        # If we are install less, we must ask for a full file path remaping
        remap_from_install_dir()
    
    from opsbro.log import cprint, logger, is_tty
    from opsbro.cli import CLICommander, save_current_binary
    from opsbro.info import BANNER, TXT_BANNER
    from opsbro.misc.bro_quotes import get_quote
    from opsbro.yamlmgr import yamler

    # We should save our current opsbro binary, for debug purpose or sub spawn of some cli calls
    save_current_binary(sys.argv[0])
    
    logger.setLevel('WARNING')
    
    # Is args are setting them, they must be force to the rest of the execution without looking at the configuration
    if opts.do_verbose:
        logger.setLevel('INFO', force=True)
    
    if opts.do_debug:
        logger.setLevel('DEBUG', force=True)
    
    do_help = opts.do_help
    do_list = opts.do_list
    
    cfg = None
    if not os.path.exists(opts.ymlconfig):
        logger.debug('Missing configuration file!')
    else:
        try:
            with open(opts.ymlconfig, 'r') as f:
                buf = f.read()
                CONFIG = yamler.loads(buf)
            logger.debug("Loaded configuration file %s : %s" % (opts.ymlconfig, CONFIG))
        except Exception, exp:
            logger.error('Cannot load configuration file %s: %s' % (opts.ymlconfig, exp))
            sys.exit(2)
    
    CLI = CLICommander(CONFIG, opts)
    
    bash_completion_mode = ('EXEC_COMPLETION' in os.environ)
    
    # We will remove specific commands from the sys.argv list and keep
    # them for parsing them after
    # NOTE: in bash completion we do not want
    if not bash_completion_mode:
        command_args = CLI.hack_sys_argv()
    
    # Global command parsing, with the error enabled this time
    opts, args = parser.parse_args()
    
    logger.debug('CLI ARGS: %s' % args)
    
    if bash_completion_mode:
        CLI.print_completion(args)
        sys.exit(0)
    
    if do_help:
        if len(command_args) == 0:
            print_full_help()
            sys.exit(0)
        if len(command_args) == 1:
            sub_cmd = 'global'
        else:
            sub_cmd = command_args.pop(0)
        a = command_args.pop(0)
        if a not in CLI.keywords[sub_cmd]:
            logger.error("Cannot find any help for %s" % a)
            sys.exit(1)
        cprint('%s' % a, 'green')
        for arg in CLI.keywords[sub_cmd][a].args:
            n = arg.get('name', '')
            desc = arg.get('description', '')
            cprint('\t%s' % n.ljust(10), 'green', end='')
            cprint(': %s' % desc)
        
        sys.exit(0)
    
    # Maybe he/she just want to list our commands?
    if do_list:
        CLI.print_list(' '.join(command_args))
        sys.exit(0)
    
    # if no matching commands, can e=be just void (print help) or a unknown command (error)
    if len(command_args) == 0:
        print_full_help()
        # not matching command? error
        if len(sys.argv) != 0:
            logger.error('Unknown arguments: %s' % (' '.join(sys.argv)))
            sys.exit(2)
        sys.exit(0)
    
    # If it's just a one call shot, do it!
    CLI.one_loop(command_args)
