#!/usr/bin/env python3
# This file is placed in the Public Domain.


import json
import os
import sys
import time


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


from tob.clients import Client
from tob.command import Commands, command, scanner
from tob.handler import Event
from tob.package import getmod, inits
from tob.persist import pidname
from tob.runtime import Config, boot, daemon, forever, pidfile, privileges
from tob.runtime import wrap, wrapped
from tob.utility import md5sum, spl


import examples as MODS


CHECKSUM = "74c8e52fc1ef4d1f5dc90eae4f2200c4"


Config.name = "tobot"
Config.version = 4


class CLI(Client):

    def __init__(self):
        Client.__init__(self)
        self.register("command", command)

    def raw(self, txt):
        print(txt.encode('utf-8', 'replace').decode("utf-8"))


class Console(CLI):

    def callback(self, event):
        if not event.txt:
            return
        super().callback(event)
        event.wait()

    def poll(self):
        evt = Event()
        evt.txt = input("> ")
        evt.type = "command"
        return evt


"scripts"


def background():
    daemon("-v" in sys.argv)
    privileges()
    boot(MODS, CHECKSUM, False)
    Commands.add(cmd, ver)
    pidfile(pidname(Config.name))
    inits(spl(Config.default))
    forever()


def console():
    import readline # noqa: F401
    boot(MODS, CHECKSUM)
    Commands.add(cmd, ver)
    for _mod, thr in inits(spl(Config.sets.init)):
        if "w" in Config.opts:
            thr.join(30.0)
    csl = Console()
    csl.start()
    forever()


def control():
    if len(sys.argv) == 1:
        return
    boot(MODS, CHECKSUM)
    Commands.add(cmd, md5, tbl, srv, ver)
    csl = CLI()
    evt = Event()
    evt.orig = repr(csl)
    evt.txt = " ".join(sys.argv[1:])
    evt.type = "command"
    command(evt)
    evt.wait()


def service():
    privileges()
    boot(MODS, CHECKSUM, False)
    Commands.add(cmd, ver)
    pidfile(pidname(Config.name))
    inits(spl(Config.default))
    forever()


"utility"


def banner():
    tme = time.ctime(time.time()).replace("  ", " ")
    print("%s %s since %s (%s)" % (Config.name.upper(), Config.version, tme, Config.level.upper()))


def check(txt):
    args = sys.argv[1:]
    for arg in args:
        if not arg.startswith("-"):
            continue
        for char in txt:
            if char in arg:
                return True
    return False


"commands"


def cmd(event):
    event.reply(",".join(sorted(Commands.names or Commands.cmds)))


def md5(event):
    tbl = getmod("tbl")
    if tbl:
        event.reply(md5sum(tbl.__file__))
    else:
        event.reply("table is not there.")


def srv(event):
    import getpass
    name = getpass.getuser()
    event.reply(TXT % (Config.name.upper(), name, name, name, Config.name))


def tbl(event):
    Commands.names = {}
    scanner()
    event.reply("# This file is placed in the Public Domain.")
    event.reply("")
    event.reply("")
    event.reply('"lookup tables"')
    event.reply("")
    event.reply("")
    event.reply(f"NAMES = {json.dumps(Commands.names, indent=4, sort_keys=True)}")
    event.reply("")
    event.reply("")
    event.reply("MD5 = {")
    for module in scanner():
        event.reply(f'    "{module.__name__.split(".")[-1]}": "{md5sum(module.__file__)}",')
    event.reply("}")


def ver(event):
    event.reply(f"{Config.name.upper()} {Config.version}")


"data"


TXT = """[Unit]
Description=%s
After=network-online.target

[Service]
Type=simple
User=%s
Group=%s
ExecStart=/home/%s/.local/bin/%s -s

[Install]
WantedBy=multi-user.target"""


"runtime"


def main():
    if check('v'):
        banner()
    if check("c"):
        wrap(console)
    elif check("d"):
        background()
    elif check("s"):
        wrapped(service)
    else:
        wrapped(control)


"trampoline"


if __name__ == "__main__":
    main()
