#include <SoftwareSerial.h>
#include "FastLED.h"
FASTLED_USING_NAMESPACE
#define NUM_LEDS 40
#define LED_PIN 7
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
int R = 50;
int G = 50;
int B = 50;
uint8_t gHue = 0;
int mode = 0;
int frame_rate = 20;
int change_rate = 20;
bool color_change = true;
char data_char ='0';

int brightness = 90; // Initial brightness
String dataIn = "";

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void rainbow() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}

void rainbowWithGlitter() 
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}

void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

void confetti() 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 200, 255);
}

void sinelon()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16( 13, 0, NUM_LEDS-1 );
  leds[pos] += CHSV( gHue, 255, 192);
}

void bpm()
{
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 62;
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}


typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
uint8_t gCurrentPatternNumber = 0;

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

void setup() {
  FastLED.addLeds<WS2812, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(brightness);
  Serial.begin(9600);
  //Bluetooth.begin(38400); // Default baud rate of the Bluetooth module
  for (int led = 0; led < NUM_LEDS; ++led)
      {
        leds[led] = CRGB(R,G,B);
      }

}
void loop() {
  if (Serial.available()>0) {
    while(data_char != '#')
    {
      data_char = (char)Serial.read();
      dataIn += data_char;
    }
    data_char = '0';
    dataIn = dataIn.substring(0, dataIn.indexOf("#"));
    Serial.println(dataIn);
    delay(20);
    if (dataIn.startsWith("0")) {
      String stringBrightness = dataIn.substring(1);
      brightness = stringBrightness.toInt();
      FastLED.setBrightness(brightness);
    }
    else if (dataIn.startsWith("1")) {
      mode = 1;
      String stringR = dataIn.substring(dataIn.indexOf("R") + 1, dataIn.indexOf("G"));
      R = stringR.toInt();
      String stringG = dataIn.substring(dataIn.indexOf("G") + 1, dataIn.indexOf("B"));
      G = stringG.toInt();
      String stringB = dataIn.substring(dataIn.indexOf("B") + 1);
      B = stringB.toInt();
      for (int led = 0; led < NUM_LEDS; ++led)
      {
        leds[led] = CRGB(R,G,B);
      }  
    }
       
    else if (dataIn.startsWith("2")) 
    {
      mode = 2; 
    }
    else if (dataIn.startsWith("3")) 
    {
      mode = 3; 
    }
    else if (dataIn.startsWith("4")) 
    {
      mode = 4; 
    }
    else if (dataIn.startsWith("5")) 
    {
      mode = 5; 
    }
    else if (dataIn.startsWith("6")) 
    {
      mode = 6; 
    }
    else if (dataIn.startsWith("7"))
    {
      mode = 7;
    }
    else if (dataIn.startsWith("8"))
    {
      mode = 8;
    }
    else if (dataIn.startsWith("9"))
    {
      if(color_change)
       {
         color_change = false;
       }
      else
      {
        color_change = true;
      }
    }
    else if (dataIn.startsWith("R"))
    {
      R = dataIn.substring(1).toInt();
      mode=1;
    }
    else if (dataIn.startsWith("G"))
    {
      G = dataIn.substring(1).toInt();
      mode=1;
    }
    else if (dataIn.startsWith("B"))
    {
      B = dataIn.substring(1).toInt();
      mode=1;
    }
    else if (dataIn.startsWith("+"))
    {
      if (change_rate > 5)
      {
        change_rate-=5;
      }
    }
    else if (dataIn.startsWith("-"))
    {
      
      if (change_rate < 500)
      {
        change_rate+=5;
      }
    }
  }
  if(mode==1)
  {
    for (int led = 0; led < NUM_LEDS; ++led)
      {
        leds[led] = CRGB(R,G,B);
      }  
  }
  else if (mode==2)
  {
    rainbow();
  }
  else if(mode==3)
  {
    rainbowWithGlitter();
  }
  else if (mode==4)
  {
    confetti();
  }
  else if (mode==5)
  {
    sinelon();
  }
  else if (mode==6)
  {
    juggle();
  }
  else if (mode==7)
  {
    bpm();
  }
  else if (mode==8)
  {
    gPatterns[gCurrentPatternNumber]();
    EVERY_N_SECONDS( 10 ) { nextPattern(); }
  }
  dataIn = "";
  if(color_change)
  {
    EVERY_N_MILLISECONDS( change_rate ) { gHue++; }
  }
  FastLED.show();
  FastLED.delay(change_rate); 
}


