import paho.mqtt.client as mqtt
from SKFClient.core.utils.log import log


class MQTTStatusConsumer:
    def on_connect(self, client):
        pass

    def on_disconnect(self, client):
        pass


class MQTTClient:

    def __init__(self, cfg):
        self.config = cfg
        self.subscriptions = []
        self.client = mqtt.Client(client_id=self.config.client_id, clean_session=False)
        self.client.connected_flag = False
        self.client.on_connect = self._on_connect
        self.client.on_disconnect = self._on_disconnect
        #self.client.on_message = self._on_message
        self.client.on_publish = self._on_publish
        self.client.on_subscribe = self._on_subscribe
        self.client.on_log = self._on_log
        self.status_consumer = None

    def is_connected(self):
        return self.client.connected_flag

    def _on_connect(self, client, obj, flags, rc):
        self.client.connected_flag = True
        log.info("Connected")
        for topic in self.subscriptions:
            log.info("Subscribe to topic: " + str(topic[0]))
            self.client.subscribe(topic[0], topic[1])
        if self.status_consumer:
            self.status_consumer.on_connect(self)



    def _on_disconnect(self, client, obj, rc):
        self.client.connected_flag = False
        log.error("Connect failed")
        if self.status_consumer:
            self.status_consumer.on_disconnect(self)

    def _on_message(self, client, obj, msg):
        log.debug(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))

    def _on_publish(self, client, obj, mid):
        log.debug("mid: " + str(mid))

    def _on_subscribe(self, client, obj, mid, granted_qos):
        log.debug("Subscribed: " + str(mid) + " " + str(granted_qos))

    def _on_log(self, client, obj, level, string):
        log.debug(string)

    def subscribe(self, topic, qos, callback):
        topic_str = str(topic)
        matches = [el for el in self.subscriptions if topic_str == el[0]]
        if len(matches) == 0:
            self.subscriptions.append((topic_str, qos))
            self.client.message_callback_add(topic_str, callback)
        if self.client.connected_flag:
            self.client.subscribe(topic_str, qos)

    def publish(self, topic, payload=None, qos=0, retain=False):
        self.client.publish(topic, payload, qos, retain)

    def registry_status_consumer(self, status_consumer):
        self.status_consumer = status_consumer


    def run(self):
        try:
            self.client.connect(self.config.host, self.config.port, self.config.keep_alive_time)
        except Exception as ex:
            log.error(ex, exc_info=True)
        self.client.loop_start()

    def stop(self):
        self.client.loop_stop()
