#!/usr/bin/env python3
# This file is placed in the Public Domain.
# pylint: disable=C0413,W0212,W0718,E0401


"main"


import getpass
import os
import pathlib
import pwd
import sys
import time


from rssbot.cfg   import Config
from rssbot.cli   import CLI
from rssbot.defer import Errors, errors, later
from rssbot.disk  import Persist, skel
from rssbot.log   import Logging
from rssbot.main  import init


from rssbot import modules
from rssbot import user


Cfg         = Config()
Cfg.dis     = ""
Cfg.mod     = "cmd,err,mod,thr"
Cfg.opts    = ""
Cfg.name    = "rssbot"
Cfg.user    = getpass.getuser()
Cfg.wdr     = os.path.expanduser(f"~/.{Cfg.name}")
Cfg.pidfile = os.path.join(Cfg.wdr, f"{Cfg.name}.pid")


Persist.workdir = Cfg.wdr


def daemon(verbose=False):
    "switch to background."
    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("/")


def pidfile(pid):
    "write the pid to a file."
    if os.path.exists(pid):
        os.unlink(pid)
    path = pathlib.Path(pid)
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(pid, "w", encoding="utf-8") as fds:
        fds.write(str(os.getpid()))


def forever():
    "it never ends, until ctl-c."
    while True:
        time.sleep(1.0)


def modnames():
    "list all modules."
    return sorted({x for x in dir(modules) + dir(user) if not x.startswith("__")})


def privileges(username):
    "drop privileges."
    pwnam = pwd.getpwnam(username)
    os.setgid(pwnam.pw_gid)
    os.setuid(pwnam.pw_uid)


def wrap(func):
    "catch exceptions"
    try:
        func()
    except (KeyboardInterrupt, EOFError):
        print("")
    except Exception as ex:
        later(ex)
    errors()


def main():
    "main"
    daemon("-v" in sys.argv)
    skel()
    pidfile(Cfg.pidfile)
    privileges(Cfg.user)
    if "-v" not in sys.argv:
        CLI.out = Errors.out = Logging.out = None
    modstr = "," + ",".join(modnames())
    init(modules, modstr)
    init(user, modstr)
    forever()


if __name__ == "__main__":
    wrap(main)
