#!/usr/bin/env python3

# Copyright (c) 2021 AT&T Intellectual Property. All Rights Reserved.
#
# SPDX-License-Identifier: GPL-2.0-only
#
# This is run if there has been a change under "interfaces" vlan-modify policy
# or if vlan-modify policy is changed where it looks for vlan-modify policies
# attached  to interfaces
#

import argparse
import logging
import sys

from vplaned import Controller
from vyatta import configd
from vyatta.proto import SFPMonitor_pb2

CONFIG_CANDIDATE = configd.Client.CANDIDATE
CONFIG_RUNNING = configd.Client.RUNNING
client = None
dbg = logging.debug
err = logging.error


def sfp_permit_mismatch():
    global client

    try:
        client = configd.Client()
    except Exception as exc:
        err("Cannot establish client session: '{}'".format(str(exc).strip()))
        return 1

    key = "sfp permit mismatch-"
    node = "system sfp permit mismatch-action"
    enforce_state = node + " enforcement state"
    logging_state = node + " logging"

    cfg = SFPMonitor_pb2.SfpPermitConfig()

    if client.node_exists(client.AUTO, node):
        tree = client.tree_get_dict(node)
        entries = tree['mismatch-action']

        status = client.node_get_status(client.AUTO, logging_state)

        if status in (client.CHANGED, client.ADDED):
            logging_msg(key, cfg, "SET", entries['logging'] == "enabled")
        elif status == client.DELETED:
            logging_msg(key, cfg, "DELETE")

        status = client.node_get_status(client.AUTO, enforce_state)

        if status in (client.CHANGED, client.ADDED):
            enforcement_msg(key, cfg, "SET",
                            entries['enforcement']['state'] == "enabled")
        elif status == client.DELETED:
            enforcement_msg(key, cfg, "DELETE")
    else:
        dbg("Delete sfp permit list mismatch config")
        enforcement_msg(key, cfg, "DELETE")
        logging_msg(key, cfg, "DELETE")

    return 0


def enforcement_msg(key, cfg, action, enabled=False):
    if action == "DELETE":
        cfg.mismatch.action = SFPMonitor_pb2.SfpPermitConfig.DELETE
    else:
        cfg.mismatch.action = SFPMonitor_pb2.SfpPermitConfig.SET

    if enabled:
        cfg.mismatch.mode = SFPMonitor_pb2.SfpPermitConfig.ENFORCE
        cfg.mismatch.effective_enforcement_time = get_effective_enforcement()
    else:
        cfg.mismatch.mode = SFPMonitor_pb2.SfpPermitConfig.MONITOR
        cfg.mismatch.effective_enforcement_time = 0

    controller.store(key + "enforcement", cfg, "ALL", action,
                     cmd_name="vyatta:sfppermitlist")


def logging_msg(key, cfg, action, enabled=False):
    if action == "DELETE":
        cfg.mismatch.action = SFPMonitor_pb2.SfpPermitConfig.DELETE
    else:
        cfg.mismatch.action = SFPMonitor_pb2.SfpPermitConfig.SET

    if enabled:
        cfg.mismatch.logging = SFPMonitor_pb2.SfpPermitConfig.ENABLE
    else:
        cfg.mismatch.logging = SFPMonitor_pb2.SfpPermitConfig.DISABLE

    controller.store(key + "logging", cfg, "ALL", action,
                     cmd_name="vyatta:sfppermitlist")


def get_effective_enforcement():
    with open('/proc/uptime', 'r') as f:
        uptime = float(f.readline().split()[0])
        return int(uptime)


def sfp_permit_list(policy):
    global client

    try:
        client = configd.Client()
    except Exception as exc:
        err("Cannot establish client session: '{}'".format(str(exc).strip()))
        return 1
    key = "sfp permit list {}".format(policy)
    node = "system sfp permit list " + policy

    cfg = SFPMonitor_pb2.SfpPermitConfig()

    if client.node_exists(client.AUTO, node):
        dbg("sfp permit {} changed ".format(policy))
        tree = client.tree_get_dict(node)
        dbg("sfp permit list {} {} ".format(policy, tree))
        cfg.list.action = SFPMonitor_pb2.SfpPermitConfig.SET
        cfg.list.name = policy

        if 'index' in tree:
            index_list = tree['index']
            for index in index_list:
                sfp_cfg = cfg.list.SFPs.add()
                if 'index' in index:
                    sfp_cfg.index = index['index']
                if 'part' in index:
                    sfp_cfg.part = index['part']
                if 'vendor' in index:
                    sfp_cfg.vendor = index['vendor']
                if 'oui' in index:
                    sfp_cfg.oui = index['oui']
                if 'revision' in index:
                    sfp_cfg.rev = index['revision']
                dbg(index)

        controller.store(key, cfg, "ALL", "SET",
                         cmd_name="vyatta:sfppermitlist")

    else:
        cfg.list.action = SFPMonitor_pb2.SfpPermitConfig.DELETE
        cfg.list.name = policy
        dbg("Delete list {}".format(policy))
        controller.store(key, cfg, "ALL", "DELETE",
                         cmd_name="vyatta:sfppermitlist")

    return 0


if __name__ == "__main__":

    logging.basicConfig(level=logging.INFO,
                        format='sfp permit list: %(message)s')
    parser = argparse.ArgumentParser(
        description='Vyatta sfp permit list command')
    parser.add_argument('-l', '--list', help='sfp-permit-list permit list')
    parser.add_argument('-m', '--mismatch',
                        help='sfp-permit-list permit mismatch')
    parser.add_argument('-d', '--debug', action='store_true',
                        help='Enable debug output')

    with Controller() as controller:

        args = parser.parse_args()

        log = logging.getLogger()
        if args.debug:
            log.setLevel(logging.DEBUG)
        if args.list:
            ret = sfp_permit_list(args.list)
        elif args.mismatch:
            ret = sfp_permit_mismatch()
        else:
            parser.print_help()
            ret = 1

    sys.exit(ret)
