#!/usr/bin/env python
import logging
import logging.handlers
import argparse
import systemd.journal
import daemon
import signal
import fcntl
import sys

import scitag
import scitag.settings
import scitag.service

log = logging.getLogger("scitag")


def args_parser():
    parser = argparse.ArgumentParser(description='flowd - flow and packet marking daemon')
    parser.add_argument('--version', action='version', version='%(prog)s ' + str(scitag.__version__))
    parser.add_argument('-c', '--config', default=scitag.settings.CONFIG_PATH,
                        help='Specify path of the configuration file (defaults to {})'.format(
                            scitag.settings.CONFIG_PATH))
    parser.add_argument('-d', '--debug', action='store_true', help='Debug mode (implies run in foreground)')
    parser.add_argument('-f', '--fg', action='store_true', help='Run in foreground')
    args = parser.parse_args()

    if args.debug:
        log.setLevel(logging.DEBUG)
        formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s %(module)s[%(process)d]: %(message)s',
                                      datefmt='%b %d %H:%M:%S')
        fh = logging.StreamHandler(stream=sys.stdout)
        fh.setFormatter(formatter)
        log.addHandler(fh)
    elif args.fg:
        log.setLevel(logging.INFO)
        formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s %(module)s[%(process)d]: %(message)s',
                                      datefmt='%b %d %H:%M:%S')
        fh = logging.StreamHandler(stream=sys.stdout)
        fh.setFormatter(formatter)
        log.addHandler(fh)
    else:
        log.setLevel(logging.INFO)
        formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s %(module)s[%(process)d]: %(message)s',
                                      datefmt='%b %d %H:%M:%S')
        fh = systemd.journal.JournalHandler()
        fh.setFormatter(formatter)
        log.addHandler(fh)

    if args.config:
        scitag.settings.CONFIG_PATH = args.config

    from scitag.config import config

    # todo: check config sanity
    # todo: check system files/dirs accessible/created

    return args


def lock_file(f):
    if f.writable():
        fcntl.lockf(f, fcntl.LOCK_EX)


if __name__ == "__main__":
    p_args = args_parser()
    pid_file = open(scitag.settings.PID_FILE, 'w')
    flow_service = scitag.service.FlowService(p_args, pid_file)
    context = daemon.DaemonContext(
        working_directory=scitag.settings.WORK_DIR,
        umask=0o002,
        pidfile=lock_file(pid_file),
    )

    # config_file = open(scitag.settings.CONFIG_PATH)
    # context.files_preserve = [config_file]

    context.signal_map = {
        signal.SIGTERM: flow_service.cleanup,
        signal.SIGHUP: 'terminate',
        signal.SIGUSR1: scitag.service.FlowService.reload_config(),
    }

    flow_service.init_plugins()

    if p_args.debug or p_args.fg:
        flow_service.main()
    else:
        with context:
            flow_service.main()
