#!/usr/bin/python3 -sP
import logging

from dnsconfd.input_modules import ResolveDbusInterface, DnsconfdDbusInterface
from dnsconfd.fsm import ContextEvent
from dnsconfd.fsm import DnsconfdContext
from dnsconfd.configuration import DnsconfdArgumentParser as ArgParser
from dnsconfd.exit_code import ExitCode

import sys
import signal
import dbus.mainloop.glib
from gi.repository import GLib

if __name__ == "__main__":
    parser = ArgParser(prog='dnsconfd',
                       description='local DNS cache configuration daemon')
    parser.add_arguments()
    parser.add_commands()
    try:
        args = parser.parse_args()
    except ValueError:
        sys.exit(ExitCode.BAD_ARGUMENTS.value)

    # This ensures that proper handler is called if command is provided, else
    # noop and execution returns here
    args.func()

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    config = vars(args)
    main_loop = GLib.MainLoop()
    ctx = DnsconfdContext(config, main_loop)
    # this has to happen before we expose the API
    GLib.idle_add(lambda: ctx.transition_function(ContextEvent("KICKOFF")))
    lgr = logging.getLogger("dnsconfd")
    try:
        if config["api_choice"] == "resolve1":
            input_module = ResolveDbusInterface(ctx, config)
        else:
            input_module = DnsconfdDbusInterface(ctx, config)
            ctx.set_signal_emitter(input_module.emit_serial_signal)
    except dbus.DBusException as e:
        lgr.critical("Failed to connect to DBUS, check your policy %s", e)
        sys.exit(ExitCode.DBUS_FAILURE.value)

    # using lambdas here allows us to not use exit in DnsconfdContext class
    signal.signal(signal.SIGTERM,
                  lambda signum, frame:
                  GLib.idle_add(lambda:
                                ctx.transition_function(ContextEvent("STOP"))))

    signal.signal(signal.SIGINT,
                  lambda signum, frame:
                  GLib.idle_add(lambda:
                                ctx.transition_function(ContextEvent("STOP"))))
    main_loop.run()
    sys.exit(ctx.get_exit_code())
