"""
@package   mqtt-software-definition-service
@file      mqtt_software_definition_service.py
@brief     Publishes software definitions via MQTT

@author    andy wright
@date      11/06/2024
@copyright Copyright 2024 Hanover Displays Limited.
@license   This program is the confidential and proprietary product of
           Hanover Displays Limited. Any unauthorised use, reproduction or
           transfer of this program is strictly prohibited. (Subject to
           limited distribution and restricted disclosure only.) All
           rights reserved.
"""

import time
import datetime
import argparse
import mqtt_service as mqtt
import logging
import signal
logger = logging.getLogger(__name__)

class softwareDefinitionService(object):
    def __init__(self, broker            = "127.0.0.1",
                       port              = 1883,
                       user_name         = "",
                       password          = "",
                       deviceID          = "",
                       customerID        = "",
                       VIN               = "",
                ):

        def inc_level(sig, frame):
            level = logger.getEffectiveLevel()
            if level == logging.CRITICAL:
                logger.setLevel(logging.ERROR)
            elif level == logging.ERROR:
                logger.setLevel(logging.WARNING)
            elif level == logging.WARNING:
                logger.setLevel(logging.INFO)
            elif level == logging.INFO:
                logger.setLevel(logging.DEBUG)
            print(f"Set logging to {logging.getLevelName(logger.getEffectiveLevel())}")

        def dec_level(sig, frame):
            level = logger.getEffectiveLevel()
            if level == logging.NOTSET:
                logger.setLevel(logging.DEBUG)
            elif level == logging.DEBUG:
                logger.setLevel(logging.INFO)
            elif level == logging.INFO:
                logger.setLevel(logging.WARNING)
            elif level == logging.WARNING:
                logger.setLevel(logging.ERROR)
            elif level == logging.ERROR:
                logger.setLevel(logging.CRITICAL)
            print(f"Set logging to {logging.getLevelName(logger.getEffectiveLevel())}")

        signal.signal(signal.SIGUSR2, inc_level)
        signal.signal(signal.SIGUSR1, dec_level)

        self.app_versions_array = []

        self.software_definitions_dictionary = {
            "atDateTime":       "",
            "baseFWversion":    "",
            "OSversion":        "",
            "appVersions":      self.app_versions_array
        }

        if deviceID == "":
            self.topic = "info/sw"
        else:
            self.topic = customerID + "/" + VIN + "/hanover/inventory/equipment/" + deviceID + "/info/sw"

        self.mqttService = mqtt.mqttService("mqtt-software-definition-service",
                                            broker    = broker,
                                            port      = port,
                                            user_name = user_name,
                                            password  = password)

    def setPayload(self, baseFWversion = None,
                         OSversion     = None):
        if baseFWversion != None:
            self.software_definitions_dictionary["baseFWversion"] = baseFWversion
        if OSversion != None:
            self.software_definitions_dictionary["OSversion"] = OSversion

    def setBaseFWversion(self, baseFWversion):
            self.software_definitions_dictionary["baseFWversion"] = baseFWversion

    def setOSversion(self, OSversion):
            self.software_definitions_dictionary["OSversion"] = OSversion

    def setAppVerion(self, appName, version, provider):
        found = 0
        for app in self.app_versions_array:
            if app["appName"] == appName:
                app["version"] = version
                app["provider"] = provider
                found = 1
                break
        if found == 0:
            eth_dict = {"appName": appName, 
                        "version": version,
                        "provider": provider}
            self.app_versions_array.append(eth_dict)

    def delAppVerion(self, appName):
        for app in self.app_versions_array:
            if app["appName"] == appName:
                self.app_versions_array.remove(app)
                break

    def publish(self):
        self.software_definitions_dictionary["atDateTime"] = datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
        logger.debug(f"publish - {self.topic}\n{self.software_definitions_dictionary}\n")
        self.mqttService.publish(self.topic, self.software_definitions_dictionary)

if __name__ == "__main__":
    # Instantiate the parser
    parser = argparse.ArgumentParser(description='Publishes software definitions via MQTT')

    # Parse arguments
    parser.add_argument('--period', type=int, default=5, help='MQTT message publish period in seconds (default 5 seconds)')
    parser.add_argument('--baseFWversion', type=str, help='Software version to publish')
    parser.add_argument('--OSversion', type=str, help='OS version to publish')
    args = parser.parse_args()

    #use local broker to forward topics
    swDefService = softwareDefinitionService()

    #send topics direct to cloud
    #swDefService = softwareDefinitionService(broker            = "mqtt.ver.hanover.cloud",
    #                                         port              = 2023,
    #                                         user_name         = "1031_300",
    #                                         password          = "z3Qs38jn",
    #                                         deviceID          = "EG4",
    #                                         customerID        = "1031",
    #                                         VIN               = "0")

    if args.baseFWversion != None:
        swDefService.setBaseFWversion(args.baseFWversion)
    if args.OSversion != None:
        swDefService.setOSversion(args.OSversion)

    while 1:
        swDefService.publish()
        time.sleep(args.period)
