###
#  GND    ADC     VCC
#   |      |       |
#   R1     |       |
#   |      |       |
#   |______|       |
#   |              |
#  R2_1            |
#   |              |
#  R2_2            |
#   |              |
#   ...          ...
#   |              |
# ~~~~~WATER~~~~~~~~~
#   | - current - -|
#  R2_n            |
#
#
# VCC gets toggeled by 'power_pin', so current doesn't flow continously.
#
# To have equal distances between the voltages following calculation can be used:
# r2 = [r1/(1-i/n) - r1/(1-(i-1)/n) for i in range(1,n)]
#
# example for
# n  = 4        # 4 r2 resistors
# r1 = 10000   # 10k Ohms Resistor to GND
# gives resistance values:
# -> r2_1 :=  3333.3 (~3300 Ohm)
# -> r2_2 :=  6666.7 (~6800 Ohm)
# -> r2_3 := 20000.0
#
###

from machine import Pin, ADC
# import uasyncio as asyncio
import time


class WaterLevelSensor:
    def __init__(
            self,
            power_pin=Pin(26),
            adc_pin=Pin(35),
            resistor_ground=10000,
            resistors_water=[3300, 6800, 20000],
            resistance_water_tolerance=[400, 550, 700, 850],
            volume_liter=11*9*8.5/1000):

        self.power_pin = power_pin
        self.power_pin.init(mode=Pin.OUT, value=0)

        self.adc_pin = adc_pin
        self.adc = ADC(self.adc_pin)
        self.adc.atten(ADC.ATTN_11DB)

        self._r1 = resistor_ground
        self._r2 = resistors_water
        self.resistance_water_tolerance = resistance_water_tolerance
        self._voltage_levels = \
            [4096 * self._r1 / (self._r1 + sum(self._r2[:i]))
             for i in range(len(self._r2), 0, -1)]
        print(self._voltage_levels)

        self.min_measure_time_ms = 500
        self._last_measurment_time_ms = time.ticks_diff(time.ticks_ms(), 500)
        self._last_level_rel = 0

        self.volume = volume_liter
        # asyncio.create_task(self._polling())
        # from waterlevel_sensor import WaterLevelSensor; wls = WaterLevelSensor()

    def _measure_value(self):
        self.power_pin.on()
        self._last_measure = self.adc.read()
        self.power_pin.off()
        return self._last_measure

    @property
    def _level_rel(self):
        now = time.ticks_ms()
        if time.ticks_diff(now, self._last_measurment_time_ms) \
                > self.min_measure_time_ms:
            self._last_measurment_time_ms = now
            adc_value = self._measure_value()
            for i, voltage in enumerate(self._voltage_levels):
                if adc_value >= voltage - self.resistance_water_tolerance[i]:
                    self._last_level_rel = (i / (len(self._voltage_levels)))
                else:
                    break
        return self._last_level_rel

    @property
    def level(self):
        return self._level_rel * self.volume

    @property
    def level_percent(self):
        return self._level_rel * 100
