#!python
# This file is placed in the Public Domain.
# pylint: disable=E0611,C0413,C0115,C0116


"Assembly. Court. Prosecutor. Reconsider OTP-CR-!17/19."


import atexit
import importlib
import os
import readline
import rlcompleter
import signal
import sys
import termios
import traceback
import time


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


from genocide.handler import Callback, Command, Event, Handler, parse
from genocide.object import Wd, keys, printable, update
from genocide.handler import command, scan
from genocide.thread import name
from genocide.run import Cfg


from genocide import cmds, irc, model, rss


__version__ = "86"


scan(cmds)
scan(irc)
scan(model)
scan(rss)


Wd.workdir = os.path.expanduser("~/.genocide")


starttime = time.time()


def cprint(txt):
    print(txt)
    sys.stdout.flush()


class CLI(Handler):

    @staticmethod
    def announce(txt):
        pass

    @staticmethod
    def raw(txt):
        cprint(txt)


    def say(self, channel, txt):
        self.raw(txt)

class Console(CLI):

    @staticmethod
    def handle(event):
        Command.handle(event)
        event.wait()

    def poll(self):
        event = Event()
        event.txt = input("> ")
        event.orig = repr(self)
        return event


class Completer(rlcompleter.Completer):

    def __init__(self, options):
        super().__init__()
        self.matches = []
        self.options = options

    def complete(self, text, state):
        if state == 0:
            if text:
                self.matches = [s for s in self.options if s and s.startswith(text)]
            else:
                self.matches = self.options[:]
        try:
            return self.matches[state]
        except IndexError:
            return None


def banner(cfg):
    cprint(
          "GENOCIDE started at %s %s" % (
                                     time.ctime(time.time()).replace("  ", " "),
                                     printable(cfg, "debug,verbose")
                                    )
         )


def boot():
    signal.signal(signal.SIGHUP, hup)
    setcompleter(keys(Command.cmd))
    txt = ' '.join(sys.argv[1:])
    cfg = parse(txt)
    update(Cfg, cfg)
    return cfg


def from_exception(exc, txt="", sep=" "):
    result = []
    for frm in traceback.extract_tb(exc.__traceback__):
        fnm = os.sep.join(frm.filename.split(os.sep)[-2:])
        result.append(f"{fnm}:{frm.lineno}")
    nme = name(exc)
    res = sep.join(result)

    return f"{txt} {res} {nme}: {exc}"


def hup(_sig, _frame):
    cprint("signal 15 called")
    sys.stdout.flush()


def importer(pname, mname):
    modname = "%s.%s" % (pname, mname)
    mod = importlib.import_module(modname, pname)
    scan(mod)


def init(pname, mname):
    modname = "%s.%s" % (pname, mname)
    mod = importlib.import_module(modname, pname)
    if "init" in dir(mod):
        mod.init()


def isopt(ostr):
    for opt in ostr:
        if opt in Cfg.opts:
            return True
    return False


def setcompleter(optionlist):
    completer = Completer(optionlist)
    readline.set_completer(completer.complete)
    readline.parse_and_bind("tab: complete")
    atexit.register(lambda: readline.set_completer(None))


def ver(event):
    event.reply("GENOCIDE %s" % __version__)


def wrap(func):
    fds = sys.stdin.fileno()
    gotterm = True
    try:
        old = termios.tcgetattr(fds)
    except termios.error:
        gotterm = False
    readline.redisplay()
    try:
        func()
    except (EOFError, KeyboardInterrupt):
        cprint("")
    finally:
        if gotterm:
            termios.tcsetattr(fds, termios.TCSADRAIN, old)
    for err in Callback.errors:
        cprint(from_exception(err))


def main():
    cfg = boot()
    Command.add(ver)
    if cfg.txt:
        cli = CLI()
        return command(cli, cfg.otxt)
    if Cfg.console:
        banner(cfg)
        bot = irc.init()
        print(printable(bot.cfg, "nick,channel,server,port,sasl"))
        rss.init()
        model.init()
        csl = Console()
        csl.start()
        csl.wait()
    return None


wrap(main)
 