from hydratk.core.masterhead import MasterHead
from hydratk.lib.console.commandlinetool import CommandlineTool
import hydratk.core.const as const
import yodalib.hydratk.core.commandopt as commandopt


class TestHead(MasterHead):

    cli_cmdopt_profile = 'htk'
    options = {}

    def __init__(self):

        self._instance = super(TestHead, self).__new__(MasterHead)
        self.reset()

        self._reg_self_fn_hooks()
        self._core_base_init()
        self.run_fn_hook('h_bootstrap')

    def reset(self):

        self._runlevel = const.RUNLEVEL_SHUTDOWN
        self._config = None
        self._language = const.DEFAULT_LANGUAGE
        self._config_file = const.CONFIG_FILE
        self._ext_confd = const.EXT_CONFIG_DIR
        self._use_extensions = True
        '''Extensions'''
        self._ext = {}
        self._default_command = 'short-help'
        self._help_title = '{h}' + const.APP_NAME + \
            ' v' + const.APP_VERSION + '{e}'
        self._cp_string = '{u}' + const.CP_STRING + '{e}'
        self._command = None
        self._opt_profile = 'htk'
        self._cmd_option_hooks = {}
        self._event_hooks = {}
        self._cmd_hooks = {}
        self._fn_hooks = {}
        self._msg_router_id = 'raptor01'
        self._msg_router = None
        self._app_status = None
        self._observer_status = None
        '''Core thread pool'''
        self._thr = []
        '''Translator instance'''
        self._trn = None
        self._pid_file = None
        self._option = {}
        self._option_param = {}

        '''Application services pool'''
        self._app_service = []
        self._run_mode = const.CORE_RUN_MODE_SINGLE_APP

        '''Function callbacks'''
        self._fn_callback = {}

        '''Parallel processing'''
        self._fn_cb = {}
        self._fn_cb_shared = {}
        self._async_fn_tickets = {}
        self._cbm = None  # Callback manager
        self._async_fn = {}
        self._async_fn_ex = {}

    def clear_cmd(self):

        self._cmd_hooks = {}
        commandopt.cmd = {}
        commandopt.long_opt = {}
        commandopt.short_opt = {}
        commandopt.opt = {}

    @staticmethod
    def get_input_option(opt):

        return TestHead.options[opt] if (opt in TestHead.options) else False

    def pre_replace(self):

        self._old = CommandlineTool.get_input_option
        CommandlineTool.get_input_option = staticmethod(
            TestHead.get_input_option)

    def post_replace(self):

        CommandlineTool.get_input_option = staticmethod(self._old)

    def match_cli_command(self, cmd, opt_group='htk'):

        if opt_group not in commandopt.cmd:
            commandopt.cmd[opt_group] = []

        if cmd != '':
            if cmd not in commandopt.cmd[opt_group]:
                commandopt.cmd[opt_group].append(cmd)

            else:
                raise ValueError(self._trn.msg('htk_cmd_registered', cmd))
        else:
            raise ValueError(self._trn.msg('htk_cmd_invalid', cmd))

    def match_long_option(self, opt, value_expected=False, d_opt=None, allow_multiple=False, opt_group='htk'):

        if type(opt_group).__name__ == 'list':
            for optg in opt_group:
                if optg not in commandopt.long_opt:
                    commandopt.long_opt[optg] = []
                if opt not in commandopt.long_opt[optg]:
                    commandopt.long_opt[optg].append(opt)
                    optl = "--{0}".format(opt)
                    if optg not in commandopt.opt:
                        commandopt.opt[optg] = {}
                    commandopt.opt[optg][optl] = {
                        'd_opt': d_opt,
                        'has_value': value_expected,
                        'allow_multiple': allow_multiple
                    }
        elif type(opt_group).__name__ == 'str':
            if opt_group not in commandopt.long_opt:
                commandopt.long_opt[opt_group] = []
            if opt not in commandopt.long_opt[opt_group]:
                commandopt.long_opt[opt_group].append(opt)
                optl = "--{0}".format(opt)
                if opt_group not in commandopt.opt:
                    commandopt.opt[opt_group] = {}
                commandopt.opt[opt_group][optl] = {
                    'd_opt': d_opt,
                    'has_value': value_expected,
                    'allow_multiple': allow_multiple
                }

        else:
            raise TypeError('opt_group can be only of type list or str, got {0}'.format(
                type(opt_group).__name__))

    def match_short_option(self, opt, value_expected=False, d_opt=None, allow_multiple=False, opt_group='htk'):

        if type(opt_group).__name__ == 'list':
            for optg in opt_group:
                if optg not in commandopt.short_opt:
                    commandopt.short_opt[optg] = ''
                if opt not in commandopt.short_opt[optg]:
                    commandopt.short_opt[optg] += opt
                    opts = "-{0}".format(opt)
                    if optg not in commandopt.opt:
                        commandopt.opt[optg] = {}
                    commandopt.opt[optg][opts] = {
                        'd_opt': d_opt,
                        'has_value': value_expected,
                        'allow_multiple': allow_multiple
                    }
        elif type(opt_group).__name__ == 'str':
            if opt_group not in commandopt.short_opt:
                commandopt.short_opt[opt_group] = ''
            if opt not in commandopt.short_opt[opt_group]:
                commandopt.short_opt[opt_group] += opt
                opts = "-{0}".format(opt)
                if opt_group not in commandopt.opt:
                    commandopt.opt[opt_group] = {}
                commandopt.opt[opt_group][opts] = {
                    'd_opt': d_opt,
                    'has_value': value_expected,
                    'allow_multiple': allow_multiple
                }

        else:
            raise TypeError('opt_group can be only of type list or str, got {0}'.format(
                type(opt_group).__name__))
