from homie.constants import BOOLEAN, FALSE, TRUE, FLOAT
from homie.property import HomieProperty
from update_homie_node import UpdateHomieNode
# from homie.device import await_ready_state
from machine import Pin, ADC
import uasyncio as asyncio


class PlantNode(UpdateHomieNode):

    def __init__(
            self,
            id,
            name,
            pin_watering,
            pin_moisture,
            pin_water_tank,
            waterlevel_sensor,
            interval=60*5,
            interval_watering=0.1):
        super().__init__(
            id=id, name=name, type="watering",
            interval=interval,
            interval_short=interval_watering)

        # Update Interval
        self.interval_normal = interval
        self.interval_watering = interval_watering

        # WaterLevelSensor
        self.waterlevel_sensor = waterlevel_sensor
        self.property_waterlevel = HomieProperty(
            id="waterlevel",
            name="Wassertankstand",
            datatype=FLOAT,
            unit="L",
        )
        self.add_property(self.property_waterlevel)
        self.property_waterlevel_percent = HomieProperty(
            id="waterlevel_percent",
            name="Wassertankstand [%]",
            datatype=FLOAT,
            format="0.00:100.00",
            unit="%",
        )
        self.add_property(self.property_waterlevel_percent)

        self.property_waterlevel_volume_liter = HomieProperty(
            id="waterlevel_volume_max",
            name="Wassertankgröße",
            settable=True,
            datatype=FLOAT,
            unit="L",
            on_message=self._set_waterlevel_volume
        )
        self.add_property(self.property_waterlevel_volume_liter)

        # Moisture
        self.adc = ADC(pin_moisture)
        self.adc.atten(ADC.ATTN_11DB)
        self.property_moisture = HomieProperty(
            id="moisture",
            name="Feuchte",
            datatype=FLOAT,
            format="0.00:100.00",
            unit="%",
        )
        self.add_property(self.property_moisture)

        # Watering Motor
        self.pin_watering_motor = pin_watering
        self.pin_watering_motor.init(mode=Pin.OUT, value=0)
        self.property_water_power = HomieProperty(
            id="power",
            name="Bewässerung",
            settable=True,
            datatype=BOOLEAN,
            default=FALSE,
            on_message=self.toggle_motor,
        )
        self.add_property(self.property_water_power)

        self.property_watering_max_duration = HomieProperty(
            id="watering_duration_max",
            name="Bewässerungszeit",
            settable=True,
            datatype=FLOAT,
            default=3,
            unit="s",
        )
        self.add_property(self.property_watering_max_duration)

    def update_data(self):
        self.property_moisture.value = "{:1.2f}".format(
            (4096 - self.adc.read()) / 40.96)

        self.property_waterlevel_percent.value = "{:1.0f}".format(
            self.waterlevel_sensor.level_percent)
        self.property_waterlevel.value = "{:1.2f}".format(
            self.waterlevel_sensor.level)
        self.property_waterlevel_volume_liter.value = "{:1.4f}".format(
            self.waterlevel_sensor.volume)

        if self.pin_watering_motor.value() == 1:
            self.interval_normal = self._interval
            self.set_interval(self.interval_watering)

    def toggle_motor(self, topic, payload, retained):
        ONOFF = {FALSE: 0, TRUE: 1}
        v = ONOFF[payload]
        self.pin_watering_motor(v)
        if v == 1:
            self.interval_normal = self._interval
            self.set_interval(self.interval_watering)
            asyncio.create_task(self.stop_motor())

    def stop_motor(self):
        await asyncio.sleep_ms(
            int(float(self.property_watering_max_duration.value) * 1000))
        self.pin_watering_motor.value(0)
        self.set_interval(self.interval_normal)
        self.property_water_power.value = FALSE

    def _set_waterlevel_min_value(self, topic, payload, retained):
        self.waterlevel_sensor.value_min = float(payload)

    def _set_waterlevel_max_value(self, topic, payload, retained):
        self.waterlevel_sensor.value_max = float(payload)

    def _set_waterlevel_volume(self, topic, payload, retained):
        self.waterlevel_sensor.volume = float(payload)
