#!python
# 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 genocide.command import Commands, command
from genocide.clients import Client
from genocide.configs import Config
from genocide.kernels import Kernel, scanner
from genocide.message import Message
from genocide.package import modules
from genocide.statics import SYSTEMD
from genocide.threads import threadhook
from genocide.utility import daemon, forever, pidfile, privileges, wrap
from genocide.utility import check, spl, wrapped
from genocide.workdir import pidname


Config.ignore = ""
Config.name = "genocide" 
Config.version = 201


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()
    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(" ".join(sys.argv[1:]))
    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()
