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


import json
import logging
import os
import os.path
import sys
import time


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


from tob.clients import Client
from tob.command import Commands, command, scanner, table
from tob.methods import parse
from tob.handler import Event
from tob.objects import update
from tob.package import NAME, Mods
from tob.package import getmod, inits, md5sum, modules, setdirs, sums
from tob.utility import check, daemon, forever, privileges, level, spl
from tob.workdir import Workdir, moddir, pidfile, pidname, setwd


CHECKSUM = ""


class Config:

    debug = False
    default = ""
    gets = {}
    index = None
    init  = ""
    level = "warn"
    mod = ""
    opts = ""
    otxt = ""
    sets = {}
    verbose = False
    version = 131
    wdr = ""


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


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


def background():
    daemon("-v" in sys.argv)
    privileges()
    boot(False)
    pidfile(pidname(NAME))
    inits(spl(Config.init or Config.default))
    forever()


def boot(doparse=True):
    if doparse:
        parse(Config, " ".join(sys.argv[1:]))
        update(Config, Config.sets, empty=False)
        Workdir.wdr = Config.wdr
    level(Config.level)
    setwd(NAME)
    Mods.dir("mods", "mods")
    setdirs("n" in Config.opts, "m" in Config.opts)
    if "v" in Config.opts:
        banner()
    if "a" in Config.opts:
        Config.init = ",".join(modules())
    Commands.add(ver)
    sums(CHECKSUM)
    table(CHECKSUM)
    logging.info("workdir is %s", Workdir.wdr)


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


def control():
    if len(sys.argv) == 1:
        return
    boot()
    csl = CLI()
    evt = Event()
    evt.orig = repr(csl)
    evt.type = "command"
    evt.txt = Config.otxt
    command(evt)
    evt.wait()


def service():
    privileges()
    boot(False)
    pidfile(pidname(NAME))
    banner()
    inits(spl(Config.init or Config.default))
    forever()


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


def wrapped(func):
    try:
        func()
    except (KeyboardInterrupt, EOFError):
        print("")


def wrap(func):
    import termios
    old = None
    try:
        old = termios.tcgetattr(sys.stdin.fileno())
    except termios.error:
        pass
    try:
        wrapped(func)
    finally:
        if old:
            termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, old)


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


if __name__ == "__main__":
    main()
