#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
//#include <TrueRandom.h>
#endif
#define PIN 6

//RandomHat code
#define randomHatStartNum 1  // starting number in hat
#define randomHatEndNum 20    // ending number in hat - end has to be larger than start  
#define numberInHat (randomHatEndNum - randomHatStartNum) + 1

Adafruit_NeoPixel strip = Adafruit_NeoPixel(21, PIN, NEO_GRB + NEO_KHZ800); //for some reason I can only get 8 lights consistently if the LED's are set to 21

float color[6][12] = { { 100, 200, 255, 80, 170, 255, 2.55, 1.275, 1.00, 3.1875, 1.50, 1.00 }, { 158, 10, 205, 160, 0, 190, 1, 2.5, 1.25, 1.6, 1, 1.9 }, { 255, 14, 5, 255, 18, 5, 1.00, 1.25, 1.00, 1, 1.25, 1.00 }, { 255, 60, 6, 255, 58, 3, 1, 3, 1.5, 1, 4.6, 1.5 }, { 255, 84, 10, 255, 90, 0, 1, 2.4, 1.25, 1, 3.33, 1.25 }, { 220, 220, 18, 220, 220, 10, 1, 1.1, 1.8, 1.8, 1, 1.2 } };


void setup() {
  Serial.begin(9600);
  strip.begin();
  strip.setBrightness(255);
  strip.show();
}

void loop() {
  idle();
  return;
}

 int randomHat() {
  int thePick;		//this is the return variable with the random number from the pool
  int theIndex;
  static int currentNumInHat = 0;
  static int randArray[numberInHat];

  if  (currentNumInHat == 0) {                  // hat is emply - all have been choosen - fill up array again
    for (int i = 0 ; i < numberInHat; i++) {    // Put 1 TO numberInHat in array - starting at address 0.
      if (randomHatStartNum < randomHatEndNum) {
        randArray[i] = randomHatStartNum + i;
      }
    }
    currentNumInHat = abs(randomHatEndNum - randomHatStartNum) + 1;   // reset current Number in Hat
    // Serial.print(" hat is empty ");
    // if something should happen when the hat is empty do it here
  }

  theIndex = random(currentNumInHat);	                 //choose a random index from number in hat
  thePick = randArray[theIndex];
  randArray[theIndex] =  randArray[currentNumInHat - 1]; // copy the last element in the array into the the empty slot
  //                                                     // as the the draw is random this works fine, and is faster
  //                                                     // the previous version. - from a reader suggestion on this page
  currentNumInHat--;    // decrement number in hat
  return thePick;
}

void idle() {
  int Light[8]; //CHANGE THIS NUMBER FOR DIFFERENT ANIMATIONS

  for (int i = 0; i <= 8; i++) { //numberInHat CHANGE THIS NUMBER FOR DIFFERENT ANIMATIONS
    int x = randomHat(); //I think this is where I plug the array in
    Light[i] = x;
  }

  Serial.print(Light[0]); Serial.print(", ");
  Serial.print(Light[1]); Serial.print(", ");
  Serial.print(Light[2]); Serial.print(", ");
  Serial.print(Light[3]); Serial.print(", ");
  Serial.print(Light[4]); Serial.print(", ");
  Serial.print(Light[5]); Serial.print(", ");
  Serial.print(Light[6]); Serial.print(", ");
  Serial.print(Light[7]); Serial.print(", ");

  Serial.println("LIGHTS");

  int p = 0; //Color Profiles: 0 BLUE, 1 PURPLE, 2 RED, 3 ORANGE, 4 YELLOW, 5 GREEN
  int Ron = color[p][0];
  int Gon = color[p][1];
  int Bon = color[p][2];
  int Roff = color[p][3];
  int Goff = color[p][4];
  int Boff = color[p][5];
  float fRon = color[p][6];
  float fGon = color[p][7];
  float fBon = color[p][8];
  float fRoff = color[p][9];
  float fGoff = color[p][10];
  float fBoff = color[p][11];
  
  /*
  int light1 = Light[0]; //Ditch the ints and just plug in the arrays to the light indexes
  int light2 = Light[1];
  int light3 = Light[2];
  int light4 = Light[3];
  int light5 = Light[4];
  int light6 = Light[5];
  int light7 = Light[6];
  int light8 = Light[7];
  */

  for (int i = 0; i <= 455; i++) {  //ON Color THIS IS WORKING DO NOT FUCK WITH THIS
    int b = i;

    strip.setPixelColor(Light[0], constrain(b / fRon, 0, Ron), constrain(b / fGon, 0, Gon), constrain(b / fBon, fBon, Bon));
    strip.setPixelColor(Light[1], constrain(b / fRon, 0, Ron), constrain(b / fGon, 0, Gon), constrain(b / fBon, fBon, Bon));
    strip.setPixelColor(Light[2], constrain(b / fRon, 0, Ron), constrain(b / fGon, 0, Gon), constrain(b / fBon, fBon, Bon));
    strip.setPixelColor(Light[3], constrain(b / fRon, 0, Ron), constrain(b / fGon, 0, Gon), constrain(b / fBon, fBon, Bon));
    strip.setPixelColor(Light[4], constrain((b - 200) / fRon, 0, Ron), constrain((b - 200) / fGon, 0, Gon), constrain((b - 200) / fBon, 0, Bon));
    strip.setPixelColor(Light[5], constrain((b - 200) / fRon, 0, Ron), constrain((b - 200) / fGon, 0, Gon), constrain((b - 200) / fBon, 0, Bon));
    strip.setPixelColor(Light[6], constrain((b - 200) / fRon, 0, Ron), constrain((b - 200) / fGon, 0, Gon), constrain((b - 200) / fBon, 0, Bon));
    strip.setPixelColor(Light[7], constrain((b - 200) / fRon, 0, Ron), constrain((b - 200) / fGon, 0, Gon), constrain((b - 200) / fBon, 0, Bon));

    strip.show();
    delay(1);
  }

  for (int i = 455; i <= 455; i--) {  //OFF Color THIS IS ALSO WORKING DO NOT FUCK WITH THIS
    int b = i;
    if (b > 255) {
      b = 255;
    }

    strip.setPixelColor(Light[0], abs(constrain(b / fRoff, 0, Roff)), abs(constrain(b / fGoff, 0, Goff)), abs(constrain(b / fBoff, 0, Boff)));
    strip.setPixelColor(Light[1], abs(constrain(b / fRoff, 0, Roff)), abs(constrain(b / fGoff, 0, Goff)), abs(constrain(b / fBoff, 0, Boff)));
    strip.setPixelColor(Light[2], abs(constrain(b / fRoff, 0, Roff)), abs(constrain(b / fGoff, 0, Goff)), abs(constrain(b / fBoff, 0, Boff)));
    strip.setPixelColor(Light[3], abs(constrain(b / fRoff, 0, Roff)), abs(constrain(b / fGoff, 0, Goff)), abs(constrain(b / fBoff, 0, Boff)));
    strip.setPixelColor(Light[4], abs(constrain((b + 200) / fRoff, 0, Roff)), abs(constrain((b + 200) / fGoff, 0, Goff)), abs(constrain((b + 200) / fBoff, 0, Boff)));
    strip.setPixelColor(Light[5], abs(constrain((b + 200) / fRoff, 0, Roff)), abs(constrain((b + 200) / fGoff, 0, Goff)), abs(constrain((b + 200) / fBoff, 0, Boff)));
    strip.setPixelColor(Light[6], abs(constrain((b + 200) / fRoff, 0, Roff)), abs(constrain((b + 200) / fGoff, 0, Goff)), abs(constrain((b + 200) / fBoff, 0, Boff)));
    strip.setPixelColor(Light[7], abs(constrain((b + 200) / fRoff, 0, Roff)), abs(constrain((b + 200) / fGoff, 0, Goff)), abs(constrain((b + 200) / fBoff, 0, Boff)));



    strip.show();
    delay(2);

    if (i < -200) {
      break;
    }
  }
}