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


import logging
import os
import sys
import threading
import time


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


from objz.command import Commands, command
from objz.clients import Client
from objz.configs import Config
from objz.kernels import Kernel, scanner
from objz.message import Message
from objz.package import modules
from objz.statics import SYSTEMD
from objz.threads import threadhook
from objz.utility import daemon, forever, pidfile, privileges, wrap
from objz.utility import check, spl, wrapped
from objz.workdir import pidname


Config.ignore = "udp"
Config.name = "objz" 
Config.version = 110


class CLI(Client):

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

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


class Console(CLI):

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

    def poll(self):
        evt = Message()
        evt.text = input("> ")
        evt.kind = "command"
        return evt


"in the beginning"


def banner():
    tme = time.ctime(time.time()).replace("  ", " ")
    logger = logging.getLogger()
    print("%s %s since %s (%s)" % (
                                   Config.name.upper(),
                                   Config.version,
                                   tme,
                                   logging.getLevelName(logger.getEffectiveLevel())
                                  ))
    sys.stdout.flush()


"scripts"


def background():
    daemon(check("v"))
    privileges()
    scanner(modules(), True)
    Commands.add(cmd, ver)
    pidfile(pidname(Config.name))
    forever()


def console():
    import readline # noqa: F401
    if "v" in Config.opts:
        banner()
    mods = []
    if "a" in Config.opts:
        mods = modules()
    else:
        mods = spl(Config.sets.get("init", ""))
    Commands.add(cmd, ver)
    csl = Console()
    for _mod, thr in scanner(mods, True):
        thr.join(30.0)
    csl.start()
    forever()


def control():
    if len(sys.argv) == 1:
        return
    scanner(modules(), False)
    Commands.add(cmd, srv, ver)
    csl = CLI()
    csl.silent = False
    evt = Message()
    evt.orig = repr(csl)
    evt.text = " ".join(sys.argv[1:])
    evt.type = "command"
    command(evt)
    evt.wait()


def service():
    privileges()
    banner(Config.name, Config.version)
    scanner(modules(), True)
    Commands.add(cmd, ver)
    pidfile(pidname(Config.name))
    forever()


"commands"


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


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


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


"runtime"


def main():
    Kernel.configure()
    if check("b"):
        threading.excepthook = threadhook
    if check('z'):
        Config.debug = True
    if check("c"):
        wrap(console)
    elif check("d"):
        background()
    elif check("s"):
        wrapped(service)
    else:
        wrapped(control)


if __name__ == "__main__":
    main()
