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


"objects"


import getpass
import os
import readline
import sys
import termios
import time


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


from objx.default import Default
from objx.workdir import Workdir, skel


from botl.excepts import Error, debug, enable
from botl.handler import Client, Command, cmnd, parse_cmd, scan
from botl.handler import forever


Cfg         = Default()
Cfg.mod     = "cmd,ena,mod"
Cfg.version = 103
Cfg.wd      = os.path.expanduser(f"~/.{Cfg.name}")
Cfg.pidfile = os.path.join(Cfg.wd, f"{Cfg.name}.pid")
Workdir.wd = Cfg.wd


names    = __file__.split(os.sep)


if names[-2] == "bin":
    Cfg.name = names[-1]
else:
    Cfg.name = names[-2]


if os.path.exists("zbot"):
    import zbot as mods
else:
    print("zbot not found")
    os._exit(0)


class Console(Client):

    def announce(self, txt):
        pass

    def callback(self, evt):
        Client.callback(self, evt)
        evt.wait()

    def poll(self):
        evt = Message()
        evt.orig = object.__repr__(self)
        evt.txt = input("> ")
        evt.type = "command"
        return evt

    def say(self, channel, txt):
        txt = txt.encode('utf-8', 'replace').decode()
        print(txt)


def daemon(pidfile, verbose=False):
    pid = os.fork()
    if pid != 0:
        os._exit(0)
    os.setsid()
    pid2 = os.fork()
    if pid2 != 0:
        os._exit(0)
    if not verbose:
        with open('/dev/null', 'r', encoding="utf-8") as sis:
            os.dup2(sis.fileno(), sys.stdin.fileno())
        with open('/dev/null', 'a+', encoding="utf-8") as sos:
            os.dup2(sos.fileno(), sys.stdout.fileno())
        with open('/dev/null', 'a+', encoding="utf-8") as ses:
            os.dup2(ses.fileno(), sys.stderr.fileno())
    os.umask(0)
    os.chdir("/")
    if os.path.exists(pidfile):
        os.unlink(pidfile)
    cdir(os.path.dirname(pidfile))
    with open(pidfile, "w", encoding="utf-8") as fds:
        fds.write(str(os.getpid()))


def wrap(func):
    old2 = None
    try:
        old2 = termios.tcgetattr(sys.stdin.fileno())
    except termios.error:
        pass
    try:
        func()
    except (KeyboardInterrupt, EOFError):
        print("")
    finally:
        if old2:
            termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, old2)


"runtime"


def cmd(event):
    event.reply(",".join(sorted(list(Command.cmds))))


def ver(event):
    event.reply(f"{fg.name} {Cfg.version}")
    

def main():
    Command.add(cmd)
    Command.add(ver)
    enable(print)
    skel()
    parse_cmd(Cfg, " ".join(sys.argv[1:]))
    readline.redisplay()
    if 'a' in Cfg.opts:
        Cfg.mod = ",".join(mods.__dir__())
    if "v" in Cfg.opts:
        dte = time.ctime(time.time()).replace("  ", " ")
        debug(f"{Cfg.name.upper()} {Cfg.opts.upper()} started {dte}")
    if "h" in Cfg.opts:
        from . import __doc__ as txt
        print(txt)
        return
    if "d" in Cfg.opts:
        Cfg.mod = ",".join(mods.__dir__())
        Cfg.user = getpass.getuser()
        daemon(Cfg.pidfile, "v" in Cfg.opts)
        privileges(Cfg.user)
        scan(mods, Cfg.mod, True, Cfg.dis, True)
        forever()
        return
    if "c" in Cfg.opts:
        scan(mods, Cfg.mod, True, Cfg.sets.dis, True)
        csl = Console()
        if 'z' in Cfg.opts:
            csl.threaded = False
        csl.start()
        forever()
        return
    if Cfg.otxt:
        Cfg.mod = ",".join(mods.__dir__())
        scan(mods, Cfg.mod, False, Cfg.sets.dis, False)
        return cmnd(Cfg.otxt, print)

def wrapped():
    wrap(main)
    Error.show()


if __name__ == "__main__":
    wrapped()
