import paho.mqtt.client as mqtt
import time

import threading
import sys

import json

class Logger: 
    def __init__ (self):
        self.state = dict()

        self.hostname = open('/etc/hostname').read().strip()
        self.main_topic = '/rfc/' + self.hostname +'/'

        self.mqtt_client = mqtt.Client()

        logger_create_thread = threading.Thread(target=self.logger_connect)

        self.state_change_messages = {}

    def logger_connect(self):
        try:
            self.mqtt_client.connect("iot.eclipse.org", 1883)
            self.log("Connected to mqtt server.")
            self.connected = True
        except:
            self.connected = False
            self.log("Failed to connect to mqtt server.")
    

    def logger_thread(self):
        while True:
            time.sleep(5)
            self.publish_state()

    def publish_state(self):
        self.update_state('time', time.time(), suppress_publish = True)
        self.publish_message('state', json.dumps(self.state))

    def update_state(self, prop, value, suppress_publish = False):
        if prop in self.state.keys() and (prop, self.state[prop], value) in self.state_change_messages.keys():
            self.log(self.state_change_messages[(prop,self.state[prop],value)])

        if prop not in self.state.keys() or self.state[prop] != value:
            self.state[prop] = value
            if suppress_publish == False: self.publish_state()

    def publish_message(self, prop, payload):
        try:
            if self.mqtt_client.publish(self.main_topic + prop, payload).rc != mqtt.MQTT_ERR_SUCCESS:
                self.log('Failed to publish to mqtt server',True)
        except:
            self.log('Failed to publish to mqtt server',True)

    def publish_log(self, payload):
        self.publish_message('log', payload)

    def log(self, payload, suppress_publish = False):
        message = '[{0:.2f}] '.format(time.time()) + payload
        print(message)
        if suppress_publish == False: self.publish_log(message)

    def set_state_change_message(self, prop, from_state, to_state, message):
        self.state_change_messages[(prop, from_state, to_state)] = message
        
