#!python
# -*- coding: utf-8 -*-
# Copyright (C) 2018-2022 fjord-technologies
# SPDX-License-Identifier: GPL-3.0-or-later
"""nsaproxy"""

__version__ = '0.1.52'

# TODO: load Python logging configuration (using standard logging.config)

import argparse
import logging
import grp
import os
import pwd

from six import ensure_text

from dwho.modules import * # XXX
from dwho import config
from httpdis.ext import httpdis_json
from sonicprobe.libs import daemonize

from nsaproxy.classes.config import load_conf
from nsaproxy.modules import * # XXX
from nsaproxy.plugins import * # XXX


SYSLOG_NAME     = "nsaproxy"
LOG             = logging.getLogger(SYSLOG_NAME)

DEFAULT_PIDFILE = "/run/nsaproxy/nsaproxy.pid"
DEFAULT_LOGFILE = "/var/log/nsaproxy/daemon.log"

try:
    NSAPROXY_USER  = pwd.getpwnam(os.environ.get('NSAPROXY_USER') or 'nsaproxy').pw_name
except KeyError:
    NSAPROXY_USER  = pwd.getpwuid(os.geteuid())[0]

try:
    NSAPROXY_GROUP = grp.getgrnam(os.environ.get('NSAPROXY_GROUP') or 'nsaproxy').gr_name
except KeyError:
    NSAPROXY_GROUP = grp.getgrgid(os.getegid())[0]

NSAPROXY_PIDFILE = os.environ.get('NSAPROXY_PIDFILE') or DEFAULT_PIDFILE
NSAPROXY_LOGFILE = os.environ.get('NSAPROXY_LOGFILE') or DEFAULT_LOGFILE


def argv_parse_check():
    """
    Parse (and check a little) command line parameters
    """
    parser        = argparse.ArgumentParser()

    parser.add_argument("-l",
                        dest      = 'loglevel',
                        default   = 'info',   # warning: see affectation under
                        choices   = ('critical', 'error', 'warning', 'info', 'debug'),
                        help      = ("Emit traces with LOGLEVEL details, must be one of:\t"
                                     "critical, error, warning, info, debug"))
    parser.add_argument("-d",
                        action    = 'store_true',
                        dest      = 'dontlauchmain',
                        default   = False,
                        help      = "Don't call the main function, for installation test purposes")
    parser.add_argument("-f",
                        action    = 'store_true',
                        dest      = 'foreground',
                        default   = False,
                        help      = "Foreground, don't daemonize")
    parser.add_argument("-c",
                        dest      = 'conffile',
                        type      = ensure_text,
                        default   = '/etc/nsaproxy/nsaproxy.yml',
                        help      = "Use configuration file <conffile> instead of %(default)s")
    parser.add_argument("-p",
                        dest      = 'pidfile',
                        type      = ensure_text,
                        default   = NSAPROXY_PIDFILE,
                        help      = "Use PID file <pidfile> instead of %(default)s")
    parser.add_argument("-u",
                        dest      = 'username',
                        type      = ensure_text,
                        default   = NSAPROXY_USER,
                        help      = "Use username for the process instead of %(default)s")
    parser.add_argument("-g",
                        dest      = 'groupname',
                        type      = ensure_text,
                        default   = NSAPROXY_GROUP,
                        help      = "Use groupname for the process instead of %(default)s")
    parser.add_argument("--logfile",
                        dest      = 'logfile',
                        type      = ensure_text,
                        default   = NSAPROXY_LOGFILE,
                        help      = "Use log file <logfile> instead of %(default)s")
    parser.add_argument("--listen-addr",
                        dest      = 'listen_addr',
                        type      = ensure_text,
                        help      = "Listen on address <listen_addr>")
    parser.add_argument("--listen-port",
                        dest      = 'listen_port',
                        type      = int,
                        help      = "Listen on port <listen_port>")

    args          = parser.parse_args()
    args.loglevel = getattr(logging, args.loglevel.upper(), logging.INFO)

    return args


def main(options):
    """
    Main function; start the server
    """
    config.set_softname(SYSLOG_NAME)
    config.set_softver(__version__)

    uid = pwd.getpwnam(options.username)[2]
    gid = grp.getgrnam(options.groupname)[2]

    config.make_piddir(options.pidfile, uid, gid)
    config.make_logdir(options.logfile, uid, gid)

    root_logger = config.init_logger(options.logfile, SYSLOG_NAME)
    options     = load_conf(options.conffile, options)

    setattr(options, 'server_version', "%s/%s" % (SYSLOG_NAME, __version__))
    setattr(options, 'sys_version', '')

    httpdis_json.init(options, False)
    config.DWHO_THREADS.append(httpdis_json.stop)

    if not options.foreground:
        LOG.info("Transforming into a daemon from hell")
        daemonize.daemonize()

    LOG.info("locking PID")
    daemonize.lock_pidfile_or_die(options.pidfile)

    try:
        LOG.info("pidfile ok")
        root_logger.setLevel(options.loglevel)
        os.chown(options.pidfile, uid, gid)
        os.setgid(gid)
        os.setuid(uid)
        os.umask(0o22)

        config.start_plugins()
        httpdis_json.run(options)
    except (KeyboardInterrupt, SystemExit):
        raise
    except Exception:
        LOG.exception("bad things happen")
    finally:
        daemonize.unlock_pidfile(options.pidfile)

if __name__ == '__main__':
    def _start():
        "entry point"
        options = argv_parse_check()
        if not options.dontlauchmain:
            main(options)
    _start()
