import threading
from time import perf_counter
from telemetrix_rpi_pico import telemetrix_rpi_pico
import time
from kuukar.kuukar_config import LEDS_DATA_PIN, LEDS_NUM, HEADLIGHT_LEDS, LEFT_SIGNAL_LEDS, RIGHT_SIGNAL_LEDS, REVERSE_LEDS


class leds:
    flashing = False
    headlight = False
    reverse_signal = False
    left_signal = False
    right_signal = False
    ambient_light = [0, 0, 0]

    start_time = perf_counter()

    def __init__(self, mcu: telemetrix_rpi_pico.TelemetrixRpiPico) -> None:
        self.mcu = mcu
        self.mcu.set_pin_mode_neopixel(LEDS_DATA_PIN, LEDS_NUM)
        self.ambient_light = [2, 2, 10] #Keke Image Color
        self.__update_leds()

    def set_headlights(self, state: bool):
        self.headlight = state
        self.__update_leds()

    def set_left_signal_led(self, state: bool):
        self.left_signal = state
        self.__update_leds()

    def set_right_signal_led(self, state: bool):
        self.right_signal = state
        self.__update_leds()

    def set_ambient_led(self, r: int, g: int, b: int):
        self.ambient_light = [r, g, b]
        self.__update_leds()

    def set_reverse_led(self, state: bool):
        self.reverse_signal = state
        self.__update_leds()

    def __update_leds(self):
        self.mcu.neopixel_fill(
            r=self.ambient_light[0], g=self.ambient_light[1], b=self.ambient_light[2], auto_show=False)
        if self.headlight:
            for led in HEADLIGHT_LEDS:
                self.mcu.neo_pixel_set_value(led, self.headlight * 255, self.headlight * 255,
                                             self.headlight * 255)
        if self.left_signal:
            for led in LEFT_SIGNAL_LEDS:
                self.mcu.neo_pixel_set_value(led, 255, 0, 0)
        if self.right_signal:
            for led in RIGHT_SIGNAL_LEDS:
                self.mcu.neo_pixel_set_value(led, 255, 0, 0)
        if self.reverse_signal:
            for led in REVERSE_LEDS:
                self.mcu.neo_pixel_set_value(led, 255, 0, 0)
        self.mcu.neopixel_show()

    def flash(self, r: int, g: int, b: int, duration: int):
        if not self.flashing:
            self.flashing = True
            self.start_time = perf_counter()
            threading.Thread(target=self.__flasher, args=(r, g, b, duration))

    @staticmethod
    def __blink_func(t: float, dur: float):
        if t > dur:
            return 0
        return (-1 / (dur / 2.0) ** 2) * (t - dur / 2.0) ** 2 + 1

    def __get_time(self) -> float:
        return perf_counter() - self.start_time

    def __flasher(self, r: int, g: int, b: int, duration: int):
        while True:
            print(leds.__blink_func(self.__get_time(), duration))
            time.sleep(0.05)
            if self.__get_time() > duration:
                self.flashing = False
                break
