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

__version__ = 101

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

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


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


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


def main():
    k.boot()
    tbl.scan("evrm")
    tbl.add(cmd)
    tbl.add(ver)
    if RunCfg.verbose:
        k.log("EVRM %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("evrm.%s" % mn)
        clt.start()
        k.wait()


wrap(main)
