#!/usr/bin/env python3
import time
import mqtt_service as mqtt
import datetime
import logging
import signal

logger = logging.getLogger(__name__)


class apcMonitoringService(object):
    def __init__(
        self,
        broker="127.0.0.1",
        port=1883,
        user_name="",
        password="",
        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)

        if customerID == "":
            self.topic = "apc/counts"
        else:
            self.topic = customerID + "/" + VIN + "/hanover/apc/counts"

        self.mqttService = mqtt.mqttService(
            "mqtt-monitoring-apc-service",
            broker=broker,
            port=port,
            user_name=user_name,
            password=password,
        )

        self.current_count_dictionary = {"atDateTime": "", "sensorRef": "", "count": 0}
        self.count_in_dictionary = {"atDateTime": "", "sensorRef": "", "count": 0}
        self.count_out_dictionary = {"atDateTime": "", "sensorRef": "", "count": 0}

        self.current_count = 0
        self.count_in = 0
        self.count_out = 0
        self.sensor_ref = ""
        self.occupancy_percent = 0.0

    def setCurrentCount(self, count: int) -> bool:
        if count != self.current_count:
            self.current_count = count
            self.current_count_dictionary["count"] = count
            self.current_count_dictionary["atDateTime"] = (
                datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
            )
            return True
        else:
            return False

    def setCountIn(self, count: int) -> bool:
        if count != self.count_in:
            self.count_in = count
            self.count_in_dictionary["count"] = count
            self.count_in_dictionary["atDateTime"] = (
                datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
            )
            return True
        else:
            return False

    def setCountOut(self, count: int) -> bool:
        if count != self.count_out:
            self.count_out = count
            self.count_out_dictionary["count"] = count
            self.count_out_dictionary["atDateTime"] = (
                datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
            )
            return True
        else:
            return False

    def setSensorRef(self, sensor_ref: str) -> bool:
        if sensor_ref != self.sensor_ref:
            self.sensor_ref = sensor_ref
            self.current_count_dictionary["sensorRef"] = sensor_ref
            self.count_in_dictionary["sensorRef"] = sensor_ref
            self.count_out_dictionary["sensorRef"] = sensor_ref

    def setOccupancyPercent(self, occupancy_percent: float) -> bool:
        if occupancy_percent != self.occupancy_percent:
            self.occupancy_percent = occupancy_percent
            return True
        else:
            return False

    def publish(self):
        apc_dictionary = {}
        apc_dictionary["atDateTime"] = (
            datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
        )
        apc_dictionary["currentCount"] = self.current_count_dictionary
        apc_dictionary["countIn"] = self.count_in_dictionary
        apc_dictionary["countOut"] = self.count_out_dictionary
        apc_dictionary["occupancyPercent"] = self.occupancy_percent
        logger.debug(f"publish - {self.topic}\n{apc_dictionary}\n")
        self.mqttService.publish(self.topic, apc_dictionary)


if __name__ == "__main__":
    logger.info("APC Monitoring Service running in foreground")

    # use local broker to forward topics
    apcMonService = apcMonitoringService()

    apcMonService.setCountIn(5)

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

    while 1:
        apcMonService.publish()
        time.sleep(5)
