import time

def init(monitor):
    """ Plugin interface method """
    return PluginWarning(monitor)

class PluginWarning:
    """
    Generate all kind of warnings whenever needed and observe the sensor
    if they see a problematic situation in the container
    """
    def __init__(self, monitor):
        self.monitor = monitor

        self.revmapping = {
            sensor.name : sensor
            for sensor in self.monitor.sensors.values()
        }

        self.warning_conf = self.monitor.config['warning']

        conftest = [
            self.warning_conf['floor_sensors'],
            self.warning_conf['ceiling_sensors'],
            self.warning_conf['floor_ceiling_diff'],
            self.warning_conf['ceiling_warning_level'],
        ]
        del conftest

    def get_sensor(self, sensorname):
        """
        Resovle the reverse mapping and get back the sensor
        """
        return self.revmapping[sensorname]

    def get_stats(self, sensorlist):
        """
        Calculate mininmum, maximum average and variance over the sensor names given
        """
        sensors = [self.get_sensor(sensor) for sensor in sensorlist]
        sensors = [sensor for sensor in sensors if sensor.valid]

        if not sensors:
            return [], 0, 0, 0, 0

        avg = sum(sensor.temperature for sensor in sensors) / len(sensors)
        var = sum((sensor.temperature - avg)**2 for sensor in sensors) / len(sensors)

        sensormin = +9999
        sensormax = -9999
        for sensor in sensors:
            if sensor.temperature < sensormin:
                sensormin = sensor.temperature
            if sensor.temperature > sensormax:
                sensormax = sensor.temperature

        return sensors, sensormin, sensormax, avg, var


    async def sensor_update(self):
        """
        First generate stats and relay them to the collectd module, then use these stats
        to decide wether it is currently critical in the container, and if so, send
        warnings
        """
        # Do nothing yet
        floor_sensors, floor_min, floor_max, floor_avg, floor_var = self.get_stats(
            self.warning_conf['floor_sensors'].split(','))

        ceil_sensors, ceil_min, ceil_max, ceil_avg, ceil_var = self.get_stats(
            self.warning_conf['ceiling_sensors'].split(','))

        now = time.time()
        if floor_sensors:
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-floormin", stattime=now, statval=floor_min)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-floormax", stattime=now, statval=floor_max)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-flooravg", stattime=now, statval=floor_avg)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-floorvar", stattime=now, statval=floor_var)

        if ceil_sensors:
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-ceilmin", stattime=now, statval=ceil_min)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-ceilmax", stattime=now, statval=ceil_max)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-ceilavg", stattime=now, statval=ceil_avg)
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-ceilvar", stattime=now, statval=ceil_var)

        if floor_sensors and ceil_sensors:
            # Else we already have sent warning messages for broken sensors

            tempdiff = ceil_avg - floor_avg
            await self.monitor.call_plugin(
                "send_stats_graph", graph="stats",
                stattype="temperature-floor_ceil_diff", stattime=now, statval=tempdiff)

            print("floor: min {:05.2f} max {:05.2f} avg {:05.2f} var {:05.2f}".format(
                floor_min, floor_max, floor_avg, floor_var))
            print("ceil:  min {:05.2f} max {:05.2f} avg {:05.2f} var {:05.2f}".format(
                ceil_min, ceil_max, ceil_avg, ceil_var))

            # Here comes the warning magic
            if ceil_max > int(self.warning_conf['min_ceiling_warning']):
                if  tempdiff > int(self.warning_conf['floor_ceiling_diff']):
                    await self.monitor.call_plugin("temperature_warning",
                                                   source="tempdiff",
                                                   name1="floor",
                                                   name2="ceiling",
                                                   temp1=floor_avg,
                                                   temp2=ceil_avg,
                                                   tempdiff=tempdiff)

            if ceil_avg > int(self.warning_conf['ceiling_warning_level']):
                await self.monitor.call_plugin("temperature_warning",
                                               source="singlehot",
                                               name="ceiling",
                                               temp=ceil_avg)