#!python
# This file is placed in the Public Domain.

__version__ = 52

import importlib
import os
import pkgutil
import readline
import sys
import termios
import time

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


from koning.obj import RunCfg, Object, fmt, keys, save
from koning.run import Client, Runtime, Table, elapsed, find, fntime, get_exception
from koning.run import listfiles, spl


RunCfg.wd = os.path.expanduser("~/.koning")


class Console(Client):

    def handle(self, clt, e):
        k.put(e)
        e.wait()

    def poll(self):
        return input("> ")

    def raw(self, txt):
        print(txt)
        sys.stdout.flush()


class Kernel(Runtime):

    def error(self, txt):
        print(txt)
        sys.stdout.flush()

    def log(self, txt):
        if "PONG" in txt or "PING" in txt:
            return
        if RunCfg.verbose:
            print(txt.rstrip())
            sys.stdout.flush()


class Table(Table):

    def addmod(self, mn):
        spc = importlib.util.find_spec(mn)
        if not spc:
            return
        mod = importlib.import_module(mn)
        self.introspect(mod)

    def scan(self, pn):
        spc = importlib.util.find_spec(pn)
        if not spc:
            return
        pkg = importlib.import_module(pn)
        for mn in pkgutil.walk_packages(pkg.__path__, pn + "."):
            mod = importlib.import_module(mn.name)
            if mod:
                self.introspect(mod)


def daemon():
    pid = os.fork()
    if pid != 0:
        termreset()
        os._exit(0)
    os.setsid()
    os.umask(0)
    si = open("/dev/null", 'r')
    so = open("/dev/null", 'a+')
    se = open("/dev/null", 'a+')
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())


def wrap(func):
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    try:
        func()
    except KeyboardInterrupt:
        print("")
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)


clt = Console()
k = Kernel()
tbl = Table()


def cmd(event):
    event.reply(",".join(tbl.modnames))

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

def main():
    k.boot()
    tbl.scan("koning")
    tbl.add(cmd)
    tbl.add(ver)
    if RunCfg.verbose:
        k.log("KONING %s" % __version__)
        k.log(fmt(RunCfg, ["bork","console","daemon","debug","verbose","wd"]))
    if RunCfg.verbose:
        k.log(",".join(tbl.modnames))
    if k.cfg.txt:
        return k.cmd(k.cfg.otxt)
    if RunCfg.daemon:
        daemon()
    if RunCfg.console or k.cfg.mod:
        k.start()
        for mn in spl(k.cfg.mod):
            k.init("koning.%s" % mn)
        clt.start()
        k.wait()


wrap(main)
