#!python
# -*- coding: utf-8 -*-
"""
mjcast
"""

__license__ = """
    Copyright (C) 2018  doowan

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
__version__ = '0.1.3'

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

from optparse import OptionParser
import logging
import grp
import os
import pwd

from mjcast.modules import * # XXX
from mjcast.plugins import * # XXX
from dwho.modules import * # XXX
from dwho import config
from httpdis import httpdis
from sonicprobe.libs import daemonize


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

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

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

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

MJCAST_PIDFILE = os.environ.get('MJCAST_PIDFILE') or DEFAULT_PIDFILE
MJCAST_LOGFILE = os.environ.get('MJCAST_LOGFILE') or DEFAULT_LOGFILE


def argv_parse_check():
    """
    Parse (and check a little) command line parameters
    """
    parser              = OptionParser(usage="usage: %prog [options]")

    parser.add_option("-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_option("-d",
                      action    = 'store_true',
                      dest      = 'dontlauchmain',
                      default   = False,
                      help      = "Don't call the main function, for installation test purposes")
    parser.add_option("-f",
                      action    = 'store_true',
                      dest      = 'foreground',
                      default   = False,
                      help      = "Foreground, don't daemonize")
    parser.add_option("-c",
                      dest      = 'conffile',
                      default   = '/etc/mjcast/mjcast.yml',
                      help      = "Use configuration file <conffile> instead of %default")
    parser.add_option("-p",
                      dest      = 'pidfile',
                      default   = MJCAST_PIDFILE,
                      help      = "Use PID file <pidfile> instead of %default")
    parser.add_option("-u",
                      dest      = 'username',
                      type      = 'string',
                      default   = MJCAST_USER,
                      help      = "Use username for the process instead of %default")
    parser.add_option("-g",
                      dest      = 'groupname',
                      type      = 'string',
                      default   = MJCAST_GROUP,
                      help      = "Use groupname for the process instead of %default")
    parser.add_option("--logfile",
                      dest      = 'logfile',
                      type      = 'string',
                      default   = MJCAST_LOGFILE,
                      help      = "Use log file <logfile> instead of %default")
    parser.add_option("--listen-addr",
                      dest      = 'listen_addr',
                      help      = "Listen on address <listen_addr>")
    parser.add_option("--listen-port",
                      dest      = 'listen_port',
                      type      = 'int',
                      help      = "Listen on port <listen_port>")

    options, args       = parser.parse_args()

    if args:
        parser.error("no argument is allowed - use option --help to get an help screen")

    options.loglevel    = getattr(logging, options.loglevel.upper(), logging.INFO)

    return options


def main(options):
    """
    Main function; start the server
    """
    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     = config.load_conf(options.conffile, options)

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

    httpdis.init(options, False)
    config.DWHO_THREADS.append(httpdis.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(022)

        config.start_plugins()
        config.start_inotify()
        httpdis.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()
