#ifndef __LED_STRIP_HPP__
#define __LED_STRIP_HPP__
#include <Arduino.h>

#if defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41)
#include <tinyNeoPixel_Static.h>
#else
#include <Adafruit_NeoPixel.h>
#endif /* defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41) */

#include "pin_map.hpp"

/* Leds */

/* Led ring color and led count state */
typedef struct {
  uint16_t ledOnMin;
  uint16_t ledOnMax;
  uint16_t hue;
  uint8_t saturation;
  uint8_t brightness;
} LedRingColorState_t;

uint8_t const PresetMax{8};

// https://hslpicker.com/          = {0, 40, 50, 110, 240, 280, 310, 360 for white}
uint16_t const PresetHue[PresetMax] = {0, 7282, 9102, 20025, 43691, 50972, 56434, 65535};

uint8_t const PresetLevelMax{3};

uint8_t const PresetBrightness[PresetLevelMax] = {16, 64, 127};

/* Preset state */
typedef struct {
  uint8_t index;
  uint8_t level;
} PresetState_t;

#if defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41)
class LedStrip : tinyNeoPixel {
#else
class LedStrip : Adafruit_NeoPixel {
#endif /* defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41) */

public:
#if defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41)
  LedStrip(void) : tinyNeoPixel{LedCount, LedPin, NEO_GRB + NEO_KHZ800, pixels} {}
  void fill(uint32_t c = 0, uint16_t first = 0, uint16_t count = 0);
#else
  LedStrip(void) : Adafruit_NeoPixel{LedCount, LedPin, NEO_GRB + NEO_KHZ800} {}
#endif /* defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41) */
  virtual ~LedStrip() {}

  void setup();
  void refresh();

  void next_preset();
  void previous_preset();
  void display_led_ring(bool is_preset_enabled);

private:
  uint16_t static const LedCount{24};

/*  IO Objects */
#if defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41)
  byte pixels[LedCount * 3];
#endif /* defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX41) */

  LedRingColorState_t ledRingColorState = {
      .ledOnMin = 0, .ledOnMax = LedCount / 2, .hue = 0, .saturation = 255, .brightness = 16};
  PresetState_t presetState = {.index = 0, .level = 0};
  void refresh_led_ring(LedRingColorState_t const *ledRingColorState = nullptr);
};

#endif /* __LED_STRIP_HPP__ */
