#!/usr/bin/env python3
# This file is placed in the Public Domain.
# pylint: disable=R,C,W,C0302,E0611


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


__version__ = "85"


## import


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


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


from genocide.hdl import Callback, Command, Event, Handler, parse
from genocide.obj import Class, Object, Wd, keys, last, printable, update
from genocide.obj import find, fntime, items, save, update
from genocide.hdl import command, scan, scandir
from genocide.thr import name
from genocide.utl import elapsed
from genocide.run import Cfg


from genocide import cmds, irc, mdl, rss


## define

scan(cmds)
scan(irc)
scan(mdl)
scan(rss)


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


starttime = time.time()


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


## class


class CLI(Handler):

    @staticmethod
    def announce(txt):
        CLI.raw(txt)

    @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.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


## utility


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))


## runtime


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()
        mdl.init()
        csl = Console()
        csl.start()
        csl.wait()


wrap(main)
 