/**
 * \brief Lampe Rammstein
 * \author Yann Pascaud
 * \CPU ATtiny85 no bootloader
 * \version
 * 1. 20/08/2023 1er version
 *  
 * Copyright (c) 2023 yann pascaud
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with this program.
 * If not, see https://www.gnu.org/licenses/
 * 
 */

#include <Arduino.h>
#include <EEPROM.h>
#include "ButtonHD.h"
#include "NeoRammstein.h"
#include "Color.h"

//---------------------------------------------------------------------------
// PIN definition
//---------------------------------------------------------------------------
#define STRIP_PIN 0    //!< \brief led rgb
#define BUTTON_1_PIN 3 //!< \brief button1 : state cycle
#define BUTTON_2_PIN 4 //!< \brief button2 : brightness cycle

//---------------------------------------------------------------------------
// Constants definition
//---------------------------------------------------------------------------
// Different states
// Here we can reordinate from 0 to N
#define NB_STATES 4  //!< \brief We take only the first N states
#define NEOFIRE_STATE 0
#define ALL_WHITE_STATE 1
#define RED_RING_STATE 2
#define GREEN_RING_STATE 3

#define OFF_STATE 100
#define RAINBOW_STATE 101

// EEPROM addressing map
#define EE_ADD_STATE 0
#define EE_ADD_BRIGHTNESS 1

#define TEMPO_SAVE_EEPROM 30 * 1000 //!< \brief in ms : tempo before saving the current state

//---------------------------------------------------------------------------
// Global variables definition
//---------------------------------------------------------------------------
#ifdef USE_TINYNEOPIXEL_STATIC
byte pixels[NUM_LEDS * 3];
NeoRammstein ledStrip(NUM_LEDS, STRIP_PIN, NEO_GRB + NEO_KHZ800, (byte *)pixels);
#else
NeoRammstein ledStrip(NUM_LEDS, STRIP_PIN, NEO_GRB + NEO_KHZ800);
#endif

ButtonHD button1, button2;

uint8_t lampRammsteinState = 0, brightness = 255;
uint32_t lastTimeStateChange;
bool savedStateChange = false;

void setup()
{
  // Setup EEPROM
  EEPROM.get(EE_ADD_STATE, lampRammsteinState);
  EEPROM.get(EE_ADD_BRIGHTNESS, brightness);
  // outbound security :
  if (lampRammsteinState >= NB_STATES) lampRammsteinState = 0;
  lastTimeStateChange = millis();

  // Setup the button
  button1.attach(BUTTON_1_PIN, INPUT_PULLUP);
  button1.interval(50);
  button1.setPressedState(LOW);
  button2.attach(BUTTON_2_PIN, INPUT_PULLUP);
  button2.interval(50);
  button2.setPressedState(LOW);

  // Setup Led strip
  ledStrip.setBrightness(brightness);
  ledStrip.startSequence();
}

void loop()
{
  button1.update();
  button2.update();

  // button1 : state cycle
  if (button1.pressed())
  {
    lampRammsteinState++;
    if (lampRammsteinState >= NB_STATES) lampRammsteinState = 0;
    if (lampRammsteinState == NEOFIRE_STATE) ledStrip.startSequence();
    if (lampRammsteinState == RAINBOW_STATE) ledStrip.startSequence();

    lastTimeStateChange = millis();
    savedStateChange = false;
  }

  // button1 held down : OFF
  if (button1.heldDown())
  {
    lampRammsteinState = OFF_STATE;
    lastTimeStateChange = millis();
    savedStateChange = false;
  }

  // button2 : brightness cycle
  if (button2.pressed())
  {
    switch (brightness)
    {
    case 255:
      brightness = 190;
      break;
    case 190:
      brightness = 127;
      break;
    case 127:
      brightness = 63;
      break;
    case 63:
      brightness = 255;
      break;
    default:
      brightness = 255;
      break;
    }
    ledStrip.setBrightness(brightness);
    lastTimeStateChange = millis();
    savedStateChange = false;
  }

  // state action
  switch (lampRammsteinState)
  {
  case OFF_STATE:
    ledStrip.fill(BLACK_COLOR);
    break;

  case NEOFIRE_STATE:
    ledStrip.drawFire();
    break;

  case RAINBOW_STATE:
    ledStrip.drawRainbow();
    break;

  case ALL_WHITE_STATE:
    ledStrip.fill(NATURAL_WHITE);
    break;

  case RED_RING_STATE:
    ledStrip.fill(RED_COLOR);
    break;

  case GREEN_RING_STATE:
    ledStrip.fill(0x00F000);
    break;

  default:
    lampRammsteinState = 0;
    lastTimeStateChange = millis();
    savedStateChange = false;
    break;
  }
  ledStrip.show();

  // EEPROM save
  if (millis() - lastTimeStateChange > TEMPO_SAVE_EEPROM && savedStateChange == false)
  {
    EEPROM.put(EE_ADD_STATE, lampRammsteinState);
    EEPROM.put(EE_ADD_BRIGHTNESS, brightness);
    savedStateChange = true;
  }
}
