#include <LightController.h>
#include <string.h>
#include <Arduino.h>
#include <EEPROM.h>
#include <analogWrite.h>

LightController::LightController(const int bjtPins[], __SIZE_TYPE__ bjtCount)
{
    this->bjtCount = bjtCount;
    this->bjtPins = bjtPins;
    this->bjtState = new int[bjtCount];
    EEPROM.begin(64);
    initializePins();
    initializeState();
}

void LightController::initializeState()
{
    initializeStateDefaultValues();
    restoreState();
}

void LightController::initializePins()
{
    for (__SIZE_TYPE__ i = 0; i < bjtCount; i++)
    {
        pinMode(bjtPins[i], OUTPUT);
    }
}

void LightController::initializeStateDefaultValues()
{
    for (__SIZE_TYPE__ i = 0; i < bjtCount; i++)
    {
        bjtState[i] = 20;
    }
}

void LightController::restoreState()
{
    for (__SIZE_TYPE__ i = 0; i < bjtCount; i++)
    {
        bjtState[i] = EEPROM.readInt(i * sizeof(bjtState[i]));
        commitPinState(i);
    }
}

void LightController::updateState(const char data[], int steps)
{
    for (__SIZE_TYPE__ i = 0; i < bjtCount; i++)
    {
        parseRelativeState(data, i, steps);
        setAbsoluteState(data, i);
        commitState(i);
    }
}

void LightController::parseRelativeState(const char data[], int index, int steps)
{
    char numChar[2];
    itoa(index, numChar, 10);

    if (data[0] == numChar[0])
    {
        if (data[1] == 't')
        {
            if (bjtState[index] != 0)
            {
                bjtState[index] = 0;
            }
            else
            {
                bjtState[index] = 255;
            }
        }
        else if (data[1] == 'i')
        {
            bjtState[index] = clampState(bjtState[index] + steps);
        }
        else if (data[1] == 'd')
        {
            bjtState[index] = clampState(bjtState[index] - steps);
        }
    }
}

void LightController::setAbsoluteState(const char data[], int index)
{
    if (strcmp(data, "off") == 0)
    {
        bjtState[index] = 0;
    }

    if (strcmp(data, "on") == 0)
    {
        bjtState[index] = 255;
    }
}

int LightController::clampState(int stateValue)
{
    int clampedState = stateValue;
    if (stateValue > 255)
    {
        clampedState = 255;
    }
    else if (stateValue < 0)
    {
        clampedState = 0;
    }
    return clampedState;
}

void LightController::commitState(int index)
{
    commitPinState(index);
    EEPROM.writeInt(index * sizeof(bjtState[index]), bjtState[index]);
    EEPROM.commit();
}

void LightController::commitPinState(int index)
{
    analogWrite(bjtPins[index], bjtState[index]);
}

int LightController::getBjtCount()
{
    return bjtCount;
}
const int *LightController::getBjtPins()
{
    return bjtPins;
}
int *LightController::getBjtState()
{
    return bjtState;
}
