#include <FastSPI_LED.h>

#define NUM_LEDS 110
#define PIN 11
int switchPin = 8;

struct CRGB { unsigned char b; unsigned char g; unsigned char r;};
struct CRGB *leds;

struct colors { int redVal; int greenVal; int blueVal;};
struct colors red = {255,0,0};
struct colors orange = {255,50,0};
struct colors yellow = {255,225,0};
struct colors green = {0,255,0};
struct colors aqua = {0,245,255};
struct colors blue = {0,0,255};
struct colors purple = {205,0,255};
struct colors white = {255,255,255};


boolean lastButton = LOW;
boolean currentButton = LOW;
boolean buttonClicked = false;
boolean firstPass = true;
int ledMode = 0;

void setup()
{
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setPin(PIN);
  pinMode(switchPin, INPUT); 
  FastSPI_LED.setDataRate(2);
  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
   
}

void checkButton(){
   currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    if(firstPass == false)
    {
      ledMode = ledMode + 1; 
      buttonClicked = true;
    }
  }
  else
  {
   buttonClicked = false; 
  }
  firstPass = false;
  lastButton = currentButton;
  if (ledMode > 9) ledMode = 0;
  
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void loop(){
  int r = 0; int g = 0; int b = 0;
  switch(ledMode)
  {
   case 0:
       {
        struct colors aquaColors[] = {aqua};
        rainbow(aquaColors, sizeof(aquaColors)/sizeof(colors));
       }
       break;
   case 1:
       {
        struct colors redColors[] = {red};
        rainbow(redColors, sizeof(redColors)/sizeof(colors));
       }
       break;
   case 2:
       {
        struct colors orangeColors[] = {orange};
        rainbow(orangeColors, sizeof(orangeColors)/sizeof(colors));
       }
        break;
   case 3:
       {
        struct colors yellowColors[] = {yellow};
        rainbow(yellowColors, sizeof(yellowColors)/sizeof(colors));
       } 
       break;
   case 4:
       {
        struct colors greenColors[] = {green};
        rainbow(greenColors, sizeof(greenColors)/sizeof(colors));
       }
        break;
   case 5:
       {
        struct colors blueColors[] = {blue};
        rainbow(blueColors, sizeof(blueColors)/sizeof(colors));
       }
        break;
   case 6:
       {
        struct colors purpleColors[] = {purple};
        rainbow(purpleColors, sizeof(purpleColors)/sizeof(colors));
       }
        break;
   case 7:
       {
        struct colors whiteColors[] = {white};
        rainbow(whiteColors, sizeof(whiteColors)/sizeof(colors));
       }
        break;
   case 8:
     {
        struct colors rainbowColors[] = {red, orange, yellow, green, blue, purple};
        rainbow(rainbowColors, sizeof(rainbowColors)/sizeof(colors));
     }
        break; 
   case 9:
     {
         struct colors matchingColors[] = {red, aqua, orange, blue, yellow, green, purple};
         rainbow(matchingColors, sizeof(matchingColors)/sizeof(colors));
     }
        break; 
  }  
}

void rainbow(struct colors colorsf[], int length){
  int red = 0;
  int green = 0;
  int blue = 0;
    for(int x = 0; x < length; x++)
    { 
      red = colorsf[x].redVal;
      green = colorsf[x].greenVal;
      blue = colorsf[x].blueVal; 
      for(int i = 0; i < NUM_LEDS+1; i++ ) 
      {
          int interval = analogRead(A0);
          interval = map(interval, 0, 1023, 75, 5);
          if(red!=0)
          {
            leds[i].r = red;
            leds[i-1].r = red-20;
            leds[i+1].r = red-20;
            leds[i-2].r = red-40;
            leds[i+2].r = red-40;
          }
          if(green!=0)
          {
            leds[i].g = green;
            leds[i-1].g = green-20;
            leds[i+1].g = green-20;
            leds[i-2].g = green-40;
            leds[i+2].g = green-40;
          }
          if(blue!=0)
          {
            leds[i].b = blue;
            leds[i-1].b = blue-20;
            leds[i+1].b = blue-20;
            leds[i-2].b = blue-40;
            leds[i+2].b = blue-40;
          }
          FastSPI_LED.show();
          for(int j = 0; j < i; j++ ) 
          {
              if(red>150)
              leds[j].r = red-150;
              if(red==0)
              leds[j].r = 0;
              if(green>150)
              leds[j].g = green-150;
              if(green==0)
              leds[j].g = 0;
              if(blue>150)
              leds[j].b = blue-150;
              if(blue==0)
              leds[j].b = 0;
           }  
           checkButton();
           if(buttonClicked == true)
           {
             memset(leds, 0, NUM_LEDS * 3);
             break;
           }
           FastSPI_LED.show();
           delay(interval);
       } 
       if(buttonClicked == true)
         {
           memset(leds, 0, NUM_LEDS * 3);
           break;
         }     
    }
}