"""
Name: wdm_credential_service
Title: 
Author: Cooper
Date: 24/05/2024

Desc:  The purpose of this module is to deal with WDM credentials over MQTT,  this module will allow both the publishing
and subscription of WDM credentials.

"""
import os
import time
import _thread
import logging

from hanip.itxpt import mqtt_client
from hanip.itxpt import mqtt_payload_parser
from hanip.itxpt import DNS_SD

class WDM_Credential_Service(object):
    def __init__(self, config_dict, hw_dict):
        self.config_dict = config_dict
        self.hw_dict = hw_dict

        self.mqtt_username = "hanover_sign"
        self.mqtt_password = "letmein"
        self.broker_connected = False
        self.credential_topic = "hanover/cloud/credentials"

        self.jsh = mqtt_payload_parser.MQTTPayloadParser(self.config_dict)
        self.mqttc = mqtt_client.MQTT_Client()

    def connect_to_broker(self, broker_address):
        """

        """
        certificate_path = self.config_dict.get("MQTT_certificate", "/etc/ssl/certs/ca-root-cert.crt")

        self.mqttc.set_broker_address(broker_address)
        status = self.mqttc.connect_client(
            username="hanover_sign",
            password="letmein",
            port=8883,
            enable_tls=True,
            certificate_path=certificate_path
        )

        if status:
            logging.info("WCS: MQTT secure channel connected")
            self.broker_connected = True
            return True
        else:
            logging.warning("WCS: MQTT secure channel failed")
            return False

class WDM_Credential_Service_Console(WDM_Credential_Service):
    def __init__(self, config_dict, hw_dict):
        super().__init__(config_dict, hw_dict)

    def register_service(self, ip, hostname):
        """
        Registers the credential service on the network
        """
        self.dnssd = DNS_SD.HANOVER_DNSSD(ip, hostname)
        self.dnssd.hanover_wdm_credentials_service()

    def publish_wdm_creds(self, credentials):
        """
        Publishes the credentials to the broker with the retain flag so that the sign will get it the moment it connects
        to the broker
        """
        if self.broker_connected:
            self.mqttc.publish_data(topic=self.credential_topic,
                                    payload=self.jsh.convDictToJSON(credentials),
                                    qos=0,
                                    retain=True
                                    )


class WDM_Credential_Service_Sign(WDM_Credential_Service):
    def __init__(self, config_dict, hw_dict):
        super().__init__(config_dict, hw_dict)

        self.status = ""
        self.service_ip = ""

    def look_for_service(self):
        """
        Looks for a WDM credentials service, unlike the service for signs this can wait indefinitely without timeout,
        it will also block until a valid service is found
        """
        self.dnssd = DNS_SD.DNSSD_Discover("_mqtt._tcp.local.", "Han-cloud-service")
        self.dnssd.run()

        while 1:
            if self.dnssd.serviceIP == "":
                time.sleep(1)

            else:
                self.status = "Service Found"
                self.service_found = True
                self.service_ip = self.dnssd.serviceIP
                break

        self.dnssd.close()
        logging.info("WCS: Credential service found at %s" % self.service_ip)
        return self.service_ip

    def subscribe_to_service(self, thread=False):
        """
        Subscribes to the service
        """
        logging.info("WCS: Subscribing and running MQTT loop")
        self.mqttc.subscribe_to_topics((self.credential_topic, 0))

        if thread:
            _thread.start_new_thread(self.mqttc.run_client, ())
        else:
            self.mqttc.run_client()

    def find_connect_subscribe_to_service(self):
        """
        This call is intended for a calling class so that this module can do its own thing whilst the other module
        continues to do its thing.

        Intended to be run as a thread.
        """
        self.look_for_service()
        # Assuming a service is found else the call above would never return.
        if self.connect_to_broker(self.service_ip):
            # Only subscribe upon success of connection to broker.
            self.subscribe_to_service()

    def check_new_payload(self):
        if self.mqttc.newMsg:
            self.mqttc.newMsg = False

            return self.jsh.parseJSON(self.mqttc.payload)
        else:
            return None

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)

    config_dict = {}
    hw_dict = {}

    if "sign" in os.listdir(os.getcwd()):
        print("Running on sign")
        wcss = WDM_Credential_Service_Sign(config_dict, hw_dict)
        wcss.look_for_service()
        wcss.connect_to_broker(wcss.service_ip)
        wcss.subscribe_to_service(True)

        while 1:
            wcss.check_new_payload()
            time.sleep(1)

    else:
        dummy_payload = {
            "username": "username",
            "password": "password",
            "timestamp": ""
        }

        print("Running on console")
        wcss = WDM_Credential_Service_Console(config_dict, hw_dict)
        wcss.register_service("10.104.0.14", "Han-cloud-service")
        wcss.connect_to_broker("127.0.0.1")

        time.sleep(3)

        while 1:
            print("publishing")
            dummy_payload["timestamp"] = time.time()
            wcss.publish_wdm_creds(dummy_payload)
            time.sleep(5)
