#!/usr/bin/env python
"""
TODO: only use for debugging
"""
import os
import sys
import yaml
import logging
import contextlib
import argparse
import importlib

# Simple magic for using scripts within a source tree
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if os.path.isdir(os.path.join(BASEDIR, 'depend_test_framework')):
    os.environ['PATH'] += ":" + os.path.join(BASEDIR, 'scripts')
    sys.path.insert(0, BASEDIR)

from depend_test_framework.engine import Demo
from depend_test_framework.base_class import Params
from depend_test_framework.client import load_template, load_modules, load_objs, ParamDoc


def parse_cmd():
    parser = argparse.ArgumentParser(description='Depend Test Framework debug command')
    parser.add_argument('--engine', dest='engine', action='store',
                        default="Demo",
                        help='Which engine')
    parser.add_argument('--params', dest='params', action='store',
                        default="",
                        help='params will pass to test')
    parser.add_argument('--params-config', dest='params_conf', action='store',
                        help='config file of params will pass to test')
    parser.add_argument('--template', dest='template', action='store',
                        help='config file of the template')
    parser.add_argument('--test-objs', dest='test_objs', action='store',
                        default="",
                        help='test objs')
    parser.add_argument('--modules', dest='modules', action='store',
                        default="",
                        help='modules will be used')
    parser.add_argument('--hook-module', dest='hook_module', action='store',
                        default="",
                        help='Hook module will be used')
    parser.add_argument('--doc-modules', dest='doc_modules', action='store',
                        default="",
                        help='doc modules will be used to gen test case')
    parser.add_argument('--work-path', dest='work_path', action='store',
                        help='work path will be used')
    parser.add_argument('--mock', dest='mock', action='store_true',
                        help='Need mock all test steps')
    parser.add_argument('--debug', dest='debug', action='store_true',
                        help='Enable debug log')
    parser.add_argument('--ai-test', dest='ai_test', action='store_true',
                        help='Do a simple AI test base on generated cases')
    parser.add_argument('--print-doc', dest='print_doc', action='store_true',
                        help='Display parameters document')
    args = parser.parse_args()
    return args


def load_module(module_name):
    cmd_folder = os.path.realpath('.')
    sys.path.insert(0, cmd_folder)
    return importlib.import_module(module_name)


def load_params(params_str, params_conf=None):
    params = Params()
    if params_conf:
        with open(params_conf) as fp:
            data = yaml.load(fp)
            for key, val in data.items():
                if isinstance(val, dict):
                    setattr(params, key, Params(val))
                else:
                    setattr(params, key, val)
    if params_str:
        for param_str in params_str.split(';'):
            key, value = param_str.split('=')
            setattr(params, key, value)
    return params


@contextlib.contextmanager
def change_work_path(params):
    old_path = os.path.realpath(os.curdir)
    if params.work_path:
        path = os.path.realpath(params.work_path)
    elif params.template:
        path = os.path.dirname(os.path.realpath(params.template))
        params.template = os.path.realpath(params.template)
    else:
        path = None
    if path:
        os.chdir(path)
    yield
    if path:
        os.chdir(old_path)


def main():
    args = parse_cmd()
    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)

    if args.print_doc:
        print(ParamDoc.gen_document())
        return

    with change_work_path(args):
        hook_module = load_module(args.hook_module) if args.hook_module else None
        if args.template:
            for i, data in enumerate(load_template(args.template)):
                params, modules, doc_modules, test_objs = data
                d = Demo(params, modules, test_funcs=test_objs,
                         doc_modules=doc_modules, hook_module=hook_module)
                d.run('case%d.file' % i)
        else:
            modules_gen = load_modules(args.modules.split(','))
            doc_modules = load_modules(args.doc_modules.split(','))
            test_objs_gen = load_objs(args.test_objs.split(','))
            params = load_params(args.params, args.params_conf)

            if args.mock:
                params.mock = True

            # TODO: support specify test engine
            d = Demo(params, list(modules_gen), test_funcs=list(test_objs_gen),
                     doc_modules=list(doc_modules), hook_module=hook_module)
            d.run()


if __name__ == '__main__':
    main()
