#!/usr/bin/env python3
# This file is placed in the Public Domain.
#
# pylint: disable=C0115,C0116,C0209,C0413,W0201,R0903,W0212


"command line interface"


import inspect
import os
import sys


sys.path.insert(0, os.getcwd())


from obj.object import Default, Object, keys
from obj.disk   import Storage
from obj.find   import find
from obj.method import fmt, parse


Storage.wd = os.path.expanduser("~/.obj")


Cfg = Default()


class CLI:

    cmds = Object()

    @staticmethod
    def add(func) -> None:
        setattr(CLI.cmds, func.__name__, func)

    @staticmethod
    def dispatch(evt) -> None:
        func = getattr(CLI.cmds, evt.cmd, None)
        if not func:
            return
        func(evt)
        evt.show()

    @staticmethod
    def scan(mod) -> None:
        for key, cmd in inspect.getmembers(mod, inspect.isfunction):
            if key.startswith("cb"):
                continue
            if 'event' in cmd.__code__.co_varnames:
                CLI.add(cmd)


class Event(Default):

    def __init__(self):
        Default.__init__(self)
        self.result  = []
        self.txt     = ""

    def reply(self, txt) -> None:
        self.result.append(txt)

    def show(self) -> None:
        for txt in self.result:
            print(txt.encode('utf-8', 'replace').decode())
            sys.stdout.flush()

def cmd(event):
    event.reply(",".join(sorted(CLI.cmds)))


CLI.add(cmd)


def fnd(event):
    if not event.rest:
        res = sorted([x.split('.')[-1].lower() for x in Storage.files()])
        if res:
            event.reply(",".join(res))
        else:
            event.reply("no objects in store")
        return
    otype = event.args[0]
    args = []
    if event.gets:
        args.extend(keys(event.gets))
    if event.rest:
        args.extend(event.args[1:])
    clz = Storage.long(otype)
    if "." not in clz:
        for fnm in Storage.files():
            claz = fnm.split(".")[-1]
            if otype == claz.lower():
                clz = fnm
    nmr = 0
    for fnm, obj in find(clz, event.gets):
        event.reply(f"{nmr} {fmt(obj, args, plain=True)}")
        nmr += 1
    if not nmr:
        event.reply("no result")


CLI.add(fnd)


def main():
    parse(Cfg, " ".join(sys.argv[1:]))
    if "wd" in Cfg.sets:
        Storage.wd = Cfg.wd
    evn = Event()
    evn.txt = Cfg.otxt
    parse(evn)
    CLI.dispatch(evn)


if __name__ == "__main__":
    main()
