# F.. Falcon Arg Parser
from typing import Optional, Dict, Any

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
    GRAY = '\033[90m'

class CommandBase:
    def __init__(self, name: str) -> None:
        self.name: str = name
        self.desc: Optional[str] = None
        self.usage: Optional[str] = None
        self.core: Optional['FAP'] = None

    def run(self, args: Dict[str, Any]) -> int:
        pass


class Help(CommandBase):
    def __init__(self, core):
        super().__init__('help')
        self.desc = "print information about commands"
        self.usage = f"{core.app_binname} help"

    def run(self, args):
        i = 1
        print(f"{self.core.app_displayname} Commands:")

        for c in self.core.registered_commands.values():
            usage = ''
            if isinstance(c.usage, list):
                for x in c.usage:
                    usage = usage + "\n      $ " + x
            else:
                usage = "$ " + c.usage

            print(f'{i}) {bcolors.BOLD}{bcolors.OKCYAN}{c.name}{bcolors.ENDC}{bcolors.BOLD} - {c.desc};{bcolors.ENDC}\n   Usage:  {usage}')
            i = i + 1


class FAP:
    """Falcon Argument Parser - простой парсер командной строки."""
    NO_VALUE = '__NO_VALUE'
    def __init__(self, app_id, app_displayname, app_binname):
        self.app_id = app_id
        self.app_binname = app_binname
        self.app_displayname = app_displayname


        self.registered_commands = {}
        self.cmds = []
        self.arg_l1 = []
        self.arg_l2 = []

        self.reg(Help(self))
        self.no_command_action = None

    def command_by_name(self, name):
        return self.registered_commands.get(name)

    def now(self, args):

        # base parse 
        for a in args:
            a = a.strip()

            if (a[:1]) == '-':
                if a[:2] == '--':
                    self.arg_l2.append(a[2:])
                else:
                    self.arg_l1.append(a[1:])
            else:
                self.cmds.append(a)

        l2 = self.arg_l2
        self.arg_l2 = self.proc_kv(l2)


        if len(self.cmds) < 2:
            if self.no_command_action is None:
                print(f'No command specified!')
                self.print_help()
                return 2
            else:
                a_c = {
                    "args_l0": self.cmds,
                    "args_l1": self.arg_l1,
                    "args_l2": self.arg_l2,
                }
                self.no_command_action.run(a_c)
        else:
            a_c = {
                "args_l0": self.cmds[2:],
                "args_l1": self.arg_l1,
                "args_l2": self.arg_l2,
            }
            command = self.command_by_name(self.cmds[1])
            if command is None:
                print(f'command {self.cmds[1]} not found!')
                return 2

            return command.run(a_c)

    # {'name': 'install', 'value': 'string', 'desc': 'install package', 'usage': 'install <package>'}
    def reg(self, command : CommandBase):
        if self.registered_commands.get(command.name) is None:
            command.core = self
            self.registered_commands[command.name] = command

    def print_help(self):
        self.command_by_name('help').run(None)

    def proc_kv(self, kv_list):
        r = {}
        for kv in kv_list:
            l = kv.split("=")
            if len(l) > 1:
                k = l[0]
                v = ''.join(l[1:])
            if len(l) == 1:
                k = l[0]
                v = self.NO_VALUE
            r[k] = v

        return r


class execTask:
    def __init__(self, command, args):
        self.command = command

        if args is None:
            args = []
        self.args = args
