#!/usr/bin/python3

# Copyright (c) 2019-2021 AT&T Intellectual Property.
# All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only


import pydbus
import logging
import logging.handlers
from gi.repository import GLib
import vyatta.vrrp_vci.keepalived.util as util
import vyatta.vrrp_vci.keepalived.config_file as config_file
import vyatta.vrrp_vci.keepalived.dbus.process_control as process_control


class NotifyDaemon:

    def __init__(self, log):
        self.log = log
        self.keepalived = None
        self.keepalived_dbus = None
        self.keepalived_proxy = None
        self.old_instances = {}
        self._loop = GLib.MainLoop()
        self.log.info("Notify daemon object created")

    @property
    def loop(self):
        return self._loop

    def setup_instance_variables(self):
        if self.keepalived is None:
            self.keepalived = config_file.KeepalivedConfig()
        if self.keepalived_dbus is None:
            self.keepalived_dbus = process_control.ProcessControl()
            self.keepalived_dbus.keepalived_process = \
                self.keepalived_dbus.sysbus.get(
                    util.KEEPALIVED_DBUS_INTF_NAME,
                    util.VRRP_PROCESS_DBUS_INTF_PATH
                )
            self.keepalived_proxy = self.keepalived_dbus.keepalived_process
        if self.keepalived.vrrp_connections != {}:
            self.old_instances = self.keepalived.vrrp_connections

    def refresh_state(self):
        self.log.debug("Reading config")
        file_config = self.keepalived.read_config()
        conf = util.sanitize_vrrp_config(
            self.keepalived.convert_to_vci_format_dict(file_config)
        )
        self.keepalived.update(
            conf
        )
        self.log.debug("Registering vrrp instance signal")
        for instance, connection in self.keepalived.vrrp_connections.items():
            if instance not in self.old_instances:
                try:
                    connection.subscribe_instance_signals()
                except KeyError:
                    self.log.debug(f"{instance} is not yet active")
        for instance, connection in self.old_instances.items():
            if instance not in self.keepalived.vrrp_connections:
                connection.state_change(util.VrrpState[util.STATE_INVALID].value)
        self.old_instances.clear()

    def shutdown_system(self):
        self.log.info("Keepalived VrrpStopped signal caught")
        for connection in self.keepalived.vrrp_connections.values():
            connection.state_change(util.VrrpState.INVALID.value)
        self.loop.quit()
        self.log.debug("GLib loop shutdown")


def bus_activates(name):
    # This really isn't the best thing to do abusing the scope of variables
    # need to figure out a better way for this to work
    daemon.setup_instance_variables()
    log.info("Bus name %s has become active, registering signals", name)
    log.debug("Registering Keepalived Reloaded signal")
    daemon.keepalived_proxy.VrrpReloaded.connect(daemon.refresh_state)
    log.debug("Registering keepalived shutdown signal")
    daemon.keepalived_proxy.VrrpStopped.connect(daemon.shutdown_system)
    log.debug("Registering other keepalived signals")
    daemon.keepalived_dbus.subscribe_process_signals()
    daemon.refresh_state()


if __name__ == "__main__":
    logging.basicConfig(
        level=logging.DEBUG,
        format="%(message)s"
    )
    #handler = logging.handlers.SysLogHandler(address="/dev/log")
    log = logging.getLogger("vyatta-vrrp-notify")
    #log.addHandler(handler)
    log.info("Starting vrrp notify daemon")
    daemon = NotifyDaemon(log)
    loop = daemon.loop
    sysbus = pydbus.SystemBus()
    sysbus.watch_name(
        util.KEEPALIVED_DBUS_INTF_NAME,
        name_appeared=bus_activates
    )
    log.debug("Running GLib loop")
    loop.run()
    log.info("Shutting down vrrp notify daemon")
