"""
Show date and time in ISO format on the LCD.
Use LEDs for binary date+time presentation.
Show also temperature, hydration and air pressure.

Author: lortas
"""
import utime
import display
import leds
import ledfx
import buttons
import color
import light_sensor
import os
import bme680

battery_color_good = [  0,230,0]
battery_color_ok   = [255,215,0]
battery_color_bad  = [255,  0,0]
weekdays = ["Mo","Tu","We","Th","Fr","Sa","Su"]

def get_bat_color():
    """
    Function determines the color of the battery indicator. Colors can be set in config.
    Voltage threshold's are currently estimates as voltage isn't that great of an indicator for
    battery charge.
    :return: false if old firmware, RGB color array otherwise
    """
    try:
        v = os.read_battery()
        if v > 3.8:
            return battery_color_good
        if v > 3.6:
            return battery_color_ok
        return battery_color_bad
    except AttributeError:
        return False


def render_battery(disp):
    """
    Adds the battery indicator to the display. Does not call update or clear so it can be used in addition to
    other display code.
    :param disp: open display
    """
    c = get_bat_color()
    if not c:
        return
    disp.rect(140, 2, 155, 9, filled=True, col=c)
    disp.rect(155, 4, 157, 7, filled=True, col=c)
    try:
        v = os.read_battery()
        if v < 4.0:
            disp.rect(151, 3, 154, 8, filled=True, col=[0,0,0])
        if v < 3.8:
            disp.rect(146, 3, 151, 8, filled=True, col=[0,0,0])
        if v < 3.6:
            disp.rect(141, 3, 146, 8, filled=True, col=[0,0,0])
    except AttributeError:
        return

class Clock:
    def __init__(self, console_out = False, run_once = False, update_interval = 1):
        self.console_out = console_out
        self.update_interval = update_interval
        self.run_once = run_once
        self.editpos=0
        bme680.init()
        light_sensor.start()

    def loop(self):
        with display.open() as disp:
            while True:
                self.updateClock(disp)
                if self.run_once:
                    break
                self.setClock(disp)
                utime.sleep(0.3 * self.update_interval)

    def updateClock(self, disp):
        sensor_data = bme680.get_data()
        light = light_sensor.get_reading()
        (year, month, day, hour, minute, second, weekday, yearday) = utime.localtime()
        disp.clear()
        disp.print("{0:04d}-{1:02d}-{2:02d}".format(year,month,day),     fg=color.WHITE, bg=color.BLACK, posx=0,  posy=0)
        disp.print("{0:02d}:{1:02d}:{2:02d} {3}".format(hour,minute,second,weekdays[weekday]), fg=color.WHITE, bg=color.BLACK, posx=0, posy=14)
        render_battery(disp)
        disp.print("{0:2.0f}C {1:3.0f}rh".format(sensor_data[0],sensor_data[1]), fg=color.WHITE, bg=color.BLACK, posy=28)
        disp.print("{0:4.0f}hPa".format(sensor_data[2]), fg=color.WHITE, bg=color.BLACK, posy=42)
        # Set LED brightness based on environment light
        gs = 15 + int( light * 0.6 )
        ledcolors = [ ((i>>1&1)*gs, (i>>2)*gs, (i&1)*gs) for i in range(0, 8) ]
        leds.set(0, ledcolors[second % len(ledcolors)])
        leds.set(1, ledcolors[(second//len(ledcolors)) % len(ledcolors)])
        leds.set(2, ledcolors[minute % len(ledcolors)])
        leds.set(3, ledcolors[(minute//len(ledcolors)) % len(ledcolors)])
        leds.set(4, ledcolors[hour % len(ledcolors)])
        leds.set(5, ledcolors[(hour//len(ledcolors)) % len(ledcolors)])
        leds.set(6, ledcolors[day % len(ledcolors)])
        leds.set(7, ledcolors[(day//len(ledcolors)) % len(ledcolors)])
        leds.set(8, ledcolors[month % len(ledcolors)])
        leds.set(9, ledcolors[(month//len(ledcolors)) % len(ledcolors)])
        disp.update()

    def setClock(self, disp):
        pressed = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT)
        if pressed != 0:
            if pressed & buttons.BOTTOM_LEFT != 0:
                if self.editpos < 11:
                    self.editpos += 1
                else:
                    self.editpos = 0
            if pressed & buttons.BOTTOM_RIGHT != 0:
                secs = utime.time()
                if self.editpos ==  1: secs +=     365 * 24 * 60 * 60
                if self.editpos ==  2: secs +=     305 * 24 * 60 * 60
                if self.editpos ==  3: secs +=      31 * 24 * 60 * 60
                if self.editpos ==  4: secs +=      10 * 24 * 60 * 60
                if self.editpos ==  5: secs +=           24 * 60 * 60
                if self.editpos ==  6: secs +=           10 * 60 * 60
                if self.editpos ==  7: secs +=                60 * 60
                if self.editpos ==  8: secs +=                10 * 60
                if self.editpos ==  9: secs +=                     60
                if self.editpos == 10: secs +=                     10
                if self.editpos == 11: secs +=                      1
                utime.set_time(secs)
            if pressed & buttons.TOP_RIGHT != 0:
                secs = utime.time()
                if self.editpos ==  1: secs -=     365 * 24 * 60 * 60
                if self.editpos ==  2: secs -=     305 * 24 * 60 * 60
                if self.editpos ==  3: secs -=      31 * 24 * 60 * 60
                if self.editpos ==  4: secs -=      10 * 24 * 60 * 60
                if self.editpos ==  5: secs -=           24 * 60 * 60
                if self.editpos ==  6: secs -=           10 * 60 * 60
                if self.editpos ==  7: secs -=                60 * 60
                if self.editpos ==  8: secs -=                10 * 60
                if self.editpos ==  9: secs -=                     60
                if self.editpos == 10: secs -=                     10
                if self.editpos == 11: secs -=                      1
                utime.set_time(secs)
        xpos=0
        ypos=0
        if self.editpos > 9:
            xpos=14*(self.editpos-4)
            ypos=14
        elif self.editpos > 7:
            xpos=14*(self.editpos-5)
            ypos=14
        elif self.editpos > 5:
            xpos=14*(self.editpos-6)
            ypos=14
        elif self.editpos > 3:
            xpos=14*(self.editpos+4)
            ypos=0
        elif self.editpos > 1:
            xpos=14*(self.editpos+3)
            ypos=0
        elif self.editpos > 0:
            xpos=14*(self.editpos+2)
            ypos=0
        if self.editpos > 0:
            disp.rect(xpos, ypos,    xpos+14, ypos+14, filled=False, col=color.RED)
            disp.rect(xpos, ypos+14, xpos+14, ypos+15, filled=False, col=color.RED)
            disp.update()

clock = Clock()
clock.loop()
