#include <Adafruit_NeoPixel.h>
#include <FastLED.h>

/*
Fire Animation with 3 button features:
red: control the speed of the flame by adding delay
green: set the brightness
blue: select the flame color
*/

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define BRIGHTNESS  255
#define N_PIXELS  36 // Number of pixels in strand
#define LED_PIN  5  // NeoPixel LED strand is connected to this pin
const int buttonPin = A1;

int nbts = 3;
int startpin = 2;
int bts[3];
boolean btgs[3];

#define SPARKING 50
#define COOLING  55
#define LED_TYPE WS2812B     // Only use the LED_PIN for WS2812's
#define COLOR_ORDER GRB

struct CRGB leds[N_PIXELS];
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
static uint16_t dist;         // A random number for noise generator.

int _delay;
int _brightness = BRIGHTNESS;
int _colorPalateIndex;
int _debugDelay = 0;
String _buttonCommand = "";

CRGB _colorPalates[3][4] = 
{
  { CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White },
  { CRGB::Black, CRGB::Blue, CRGB::Yellow, CRGB::White },
  { CRGB(0, 113, 138), CRGB::Blue, CRGB(0, 255, 51), CRGB::White }
};

void setup() {

    strip.begin();
    strip.show(); // all pixels to 'off'

    Serial.begin(57600);
    //delay(3000);
 
    LEDS.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip); 
    LEDS.setBrightness(BRIGHTNESS);
    dist = random16(12345);          // A semi-random number for our noise generator

    for (int i = 0; i < nbts; i++) bts[i] = i + startpin;
    for (int i = 0; i < nbts; i++) btgs[i] = false;
    for (int i = 0; i < nbts; i++) pinMode(bts[i], INPUT_PULLUP);

    Serial.println(_buttonCommand);
}

void loop() {

  for (int i = 0; i < nbts; i++){
    if(!btgs[i]) {
      if(digitalRead(bts[i])==LOW){
        //Serial.println("bt" + String(i));
        btgs[i] = true;

        _buttonCommand = "bt" + String(i);

        if(i==0){
          //Serial.println("red");
          _buttonCommand = "red";
        }
        else if(i==1){
          //Serial.println("green");
          _buttonCommand = "green";
        }
        else if(i==2){
          //Serial.println("blue");
          _buttonCommand = "blue";
        }
      }
    }
    else{
      if(digitalRead(bts[i])==HIGH){
        btgs[i] = false;
      }
    }
  }

  //Serial.println(_buttonCommand);

  if (_buttonCommand == "red")
  {
    Serial.println("red (+5 _delay)");
    if(_delay > 30){
      _delay = 0;
    }
    else{
      _delay+= 5;
    }
    Serial.println(_delay);
    delay(_debugDelay);
  }
  else if (_buttonCommand == "green")
  {
    Serial.println("greem (+5 _brightness)");

    if(_brightness >= BRIGHTNESS){
      _brightness = 105;
    }
    else{
      _brightness+= 10;
    }
    Serial.println(_brightness);
    LEDS.setBrightness(_brightness);
    delay(_debugDelay);
  }
  else if (_buttonCommand == "blue")
  {
    if(_colorPalateIndex > 1)
    {
      _colorPalateIndex = 0;
    }
    else
    {
      _colorPalateIndex++;  
    }
    Serial.println("blue");
    delay(_debugDelay);
  }

  delay(_debugDelay);
  _buttonCommand = "";

  fire();
}

void fire(){

  random16_add_entropy( random());
  // Array of temperature readings at each simulation cell
  static byte heat[N_PIXELS];

  // Step 1.  Cool down every cell a little
  for( int i = 0; i < N_PIXELS; i++) {
    heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / N_PIXELS) + 2));
  }

  delay(_delay);
  
  // Step 2. Heat from each cell drifts 'up' and diffuses a little
  for( int k= N_PIXELS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
  }

  delay(_delay);
    
  // Step 3. Randomly ignite new 'sparks' of heat near the bottom
  if( random8() < SPARKING ) {
    int y = random8(7);
    heat[y] = qadd8( heat[y], random8(160,255) );
  }

  // Step 4. Map from heat cells to LED colors
  for( int j = 0; j < N_PIXELS; j++) {
    // Scale the heat value from 0-255 down to 0-240
    // for best results with color palettes.
    byte colorindex = scale8( heat[j], 240);

    CRGB color = ColorFromPalette(CRGBPalette16(_colorPalates[_colorPalateIndex][_colorPalateIndex], _colorPalates[_colorPalateIndex][_colorPalateIndex+1], _colorPalates[_colorPalateIndex][_colorPalateIndex+2], _colorPalates[_colorPalateIndex][_colorPalateIndex+3]), colorindex);
    
    int pixelnumber;
    pixelnumber = j;
    leds[pixelnumber] = color;
  }
  FastLED.show();
}