#include "led.h"

c_leds ledlist;

#define MARGIN 20

//#############################################
//#          common functions                 #
//#############################################

c_leds *getledlist(void)
{
  return &ledlist;
}

void initLeds(void)
{
  ledlist.init();
  ledlist.AddLed(LED1, DETECT1, 1, 844, YELLOW, true);
  ledlist.AddLed(LED2, DETECT2, 2, 512, RED,    true);
  ledlist.AddLed(LED3, DETECT3, 3, 92,  GREEN,  true);

  ledlist.begin();
}

void turnOnLed(e_ledcolor color)
{
  ledlist.turnOnLed(color);
}

void turnOffLed(uint16_t index)
{
  ledlist.turnOffLed(index);
}

void turnOnLed(uint16_t index)
{
  ledlist.turnOnLed(index);
}

void turnOffLed(e_ledcolor color)
{
  ledlist.turnOffLed(color);
}

void turnOffAllLed()
{
  ledlist.turnAllOff();
}

//#############################################
//#            leds functions                 #
//#############################################

void c_leds::init(void)
{
  v_ledports.clear();
  v_leds.clear();
}

void c_leds::AddLed(uint32_t pin, uint32_t analogpin, uint16_t index, uint16_t value, e_ledcolor color, bool invert)
{
  c_ledport port(pin, analogpin, index, invert);
  v_ledports.push_back(port);

  c_led led(color, value, index);
  v_leds.push_back(led);
}

void c_leds::begin(void)
{
  for (auto &&thisled : v_ledports)
  {
    thisled.begin();
  }
}

void c_leds::turnOnLed(e_ledcolor color)
{
  if (verifyLed(color))
  {
    getLed(color)->turnOn();
  }
}

void c_leds::turnOnLed(uint16_t index)
{
  if (verifyLed(index))
  {
    getLed(index)->turnOn();
  }
}

void c_leds::turnOffLed(e_ledcolor color)
{
  if (verifyLed(color))
  {
    getLed(color)->turnOff();
  }
}

void c_leds::turnOffLed(uint16_t index)
{
  if (verifyLed(index))
  {
    getLed(index)->turnOff();
  }
}

void c_leds::turnAllOff(void)
{
  for (auto &&port : v_ledports)
  {
    port.turnOff();
  }
}

c_ledport *c_leds::getLed(e_ledcolor color)
{
  for (auto &&port : v_ledports)
  {
    uint16_t read = port.ledRead();
    for (auto &&thisled : v_leds)
    {
      if (thisled.checkThreshold(read) & thisled.checkcolor(color))
      {
        return &port;
      }
    }
  }
  return NULL;
}

c_ledport *c_leds::getLed(uint16_t index)
{
  for (auto &&port : v_ledports)
  {
    if (port.getIndex() == index)
    {
      return &port;
    }
  }
  return NULL;
}

bool c_leds::verifyLed(e_ledcolor color)
{
  for (auto &&thisled : v_leds)
  {
    if (thisled.checkcolor(color))
    {
      return true;
    }
  }
  return false;
}

bool c_leds::verifyLed(uint16_t index)
{
  for (auto &&thisled : v_leds)
  {
    if (thisled.checkIndex(index))
    {
      return true;
    }
  }
  return false;
}

//#############################################
//#        c_ledport functions                #
//#############################################

void c_ledport::begin(void)
{
#ifndef UNIT_TEST
  pinMode(_pin, OUTPUT);
  pinMode(_analogPin, INPUT_ANALOG);
#endif
  turnOff();
}

void c_ledport::turnOn(void)
{
  writeLed(true);
}

void c_ledport::turnOff(void)
{
  writeLed(false);
}

void c_ledport::writeLed(bool state)
{
  _state = state;
  if (_invert)
  {
    state = !state;
  }
  digitalWrite(_pin, state);
}

uint16_t c_ledport::ledRead(void)
{
  return analogRead(_analogPin);
}

//#############################################
//#        c_led functions                    #
//#############################################

bool c_led::checkThreshold(uint16_t value)
{
  uint16_t upperthreshold = _value + MARGIN;
  uint16_t lowerthreshold = _value - MARGIN;

  if ((lowerthreshold < value) & (value < upperthreshold))
  {
    return true;
  }
  return false;
}

bool c_led::checkcolor(e_ledcolor color)
{
  if (_color == color)
  {
    return true;
  }
  return false;
}

bool c_led::checkIndex(uint16_t index)
{
  if (_index == index)
  {
    return true;
  }
  return false;
}

