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

__version__ = 100

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


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


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


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


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("KAMER %s" % __version__)
    

def main():
    k.boot()
    tbl.add(cmd)
    tbl.add(ver)
    if RunCfg.verbose:
        k.log("PRESIDENT %s" % __version__)
        k.log(fmt(RunCfg, ["bork","console","daemon","debug","verbose","wd"]))
    tbl.scan("president")
    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("president.%s" % mn)
        clt.start()
        k.wait()


wrap(main)
