//DNA Lamp patterns
//Created: Jan 3 2024

#include <SPI.h>
#include <FastLED.h>


const int powerPin = 7;

int p_time = 15000; //time for each pattern


//11 leds per 'column', 2 sides, and rgb val
//index 0 is the start where the colors come "in"; bottom
byte ledVals[11][2][3];

#define NUM_LEDS 22
#define DATA_PIN 5
CRGB leds[NUM_LEDS];



void setup() {

  // put your setup code here, to run once:
  Serial.begin(115200);

  // initialize button
  pinMode(powerPin, OUTPUT);
  digitalWrite(powerPin, HIGH);



  // initialize LEDs
  Serial.println("starting LEDs");
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  fill_solid(leds, NUM_LEDS, CRGB::Red);
  FastLED.show();
  delay(1000);

  fill_solid(leds, NUM_LEDS, CRGB::Black);
  FastLED.show();
}


unsigned long t = millis();
int x = 0;
void loop() {
  t = millis();

  Serial.println(x);
  switch (x) {
    case 0: pattern0(); break;
    case 1: pattern1(); break;
    case 2: pattern2(); break;
    case 3: pattern3(); break;
    case 4: pattern4(); break;
    case 5: pattern5(); break;
    case 6: pattern6(); break;
    case 7: pattern7(); break;
    case 8: pattern8(); break;
    default: Serial.println("You dided something wrong"); break;
  }


  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Black;
  }
  FastLED.show();
  delay(2000);
  x++;
  if (x == 9) x = 0;
}

void pattern0() {

  uint8_t hue = 0;
  while (abs(millis() - t) < p_time) {
    //do pattern


    // Fill the LEDs with a rainbow pattern
    fill_rainbow(leds, NUM_LEDS, hue, 7);

    // Show the rainbow on the LED strip
    FastLED.show();

    // Increment the hue for the next iteration
    hue++;

    // Wait for a short duration
    delay(50);
  }
}

void pattern1() {

  uint8_t startIndex = 0;
  uint8_t colorIndex = 0;
  while (abs(millis() - t) < p_time) {


    // Set all LEDs to black
    fill_solid(leds, NUM_LEDS, CRGB::Black);

    // Set the color of the current LED
    leds[startIndex] = CHSV(colorIndex, 255, 255);

    // Show the colors on the LED strip
    FastLED.show();

    // Increment the color index and move the starting position
    colorIndex += 5;  // You can adjust the speed by changing this value
    startIndex = (startIndex + 1) % NUM_LEDS;

    // Wait for a short duration
    delay(50);
  }
}

void pattern2() {
  Serial.println("pattern2");

  uint8_t brightness = 0;
  int c = random(0, 256);
  while (abs(millis() - t) < p_time) {
    while (brightness < 255) {
      fill_solid(leds, NUM_LEDS, CHSV(c, 255, brightness));
      FastLED.show();
      delay(5);
      brightness++;
    }

    while (brightness > 0) {
      fill_solid(leds, NUM_LEDS, CHSV(c, 255, brightness));
      brightness--;
      FastLED.show();
      delay(5);
    }
    c = random(0, 256);
  }
}

void pattern3() {


  while (abs(millis() - t) < p_time) {
    static uint8_t startIndex = 0;
    static uint8_t colorIndex = 0;

    // Set all LEDs to black
    fill_solid(leds, NUM_LEDS, CRGB::Black);

    // Create a moving color wave effect
    for (int i = 0; i < 5; i++) {
      int index = (startIndex + i * 4) % NUM_LEDS;
      leds[index] = CHSV(colorIndex + i * 10, 255, 255);
    }

    // Show the colors on the LED strip
    FastLED.show();

    // Increment the color index and move the starting position
    colorIndex += 3;  // You can adjust the speed by changing this value
    startIndex = (startIndex + 1) % NUM_LEDS;

    // Wait for a short duration
    delay(100);
  }
}

void pattern4() {


  while (abs(millis() - t) < p_time) {
    static uint8_t startIndex = 0;

    // Set all LEDs to black
    fill_solid(leds, NUM_LEDS, CRGB::Black);

    // Create a rotating rainbow effect
    for (int i = 0; i < NUM_LEDS; i++) {
      int index = (startIndex + i) % NUM_LEDS;
      leds[index] = CHSV((i * 255 / NUM_LEDS) + startIndex, 255, 255);
    }

    // Show the colors on the LED strip
    FastLED.show();

    // Rotate the rainbow
    startIndex = (startIndex + 1) % 255;

    // Wait for a short duration
    delay(50);
  }
}

void pattern5() {
  int c = random(0, 256);
  int ballPosition = 0;
  while (abs(millis() - t) < p_time) {
    do {


      static int ballDirection = 1;

      // Set all LEDs to black
      fill_solid(leds, NUM_LEDS, CRGB::Black);

      // Draw the bouncing ball
      leds[ballPosition] = CHSV(c, 255, 255);
      leds[ballPosition + 11] = CHSV(c, 255, 255);
      // Show the colors on the LED strip
      FastLED.show();

      // Move the ball position
      ballPosition += ballDirection;

      // Change direction when reaching the end
      if (ballPosition == 0 || ballPosition == 11 - 1) {
        ballDirection *= -1;
        c = random(0, 256);
      }

      // Wait for a short duration
      delay(50);
    } while (ballPosition != 0);
  }
}

void pattern6() {
  // Set all LEDs to a dim orange color


  while (abs(millis() - t) < p_time) {
    fill_solid(leds, NUM_LEDS, CRGB(50, 10, 0));

    // Randomly flicker some LEDs to simulate fire
    for (int i = 0; i < 5; i++) {
      int flickerIndex = random(NUM_LEDS);
      leds[flickerIndex] = CRGB(255, 150, 0);  // Brighter and more intense color
    }

    // Show the colors on the LED strip
    FastLED.show();

    // Introduce a slight delay for a more natural flickering effect
    delay(random(50, 90));
  }
}

void pattern7() {

  while (abs(millis() - t) < p_time) {
    // Shift all LEDs downward to simulate gravity
    for (int i = NUM_LEDS - 1; i > 0; i--) {
      leds[i] = leds[i - 1];
    }

    // Generate a random color for the new "raindrop"
    leds[0] = CHSV(random(256), 255, 255);

    // Show the colors on the LED strip
    FastLED.show();

    // Introduce a delay for the raindrop effect
    delay(100);
  }
}

void pattern8() {
  while (abs(millis() - t) < p_time) {
    static int scannerPos = 0;
    static int scannerSize = 5;

    // Set all LEDs to black
    fill_solid(leds, NUM_LEDS, CRGB::Black);

    // Draw the scanner effect
    for (int i = 0; i < scannerSize; i++) {
      int pos = (scannerPos + i) % NUM_LEDS;
      leds[pos] = CHSV((pos * 20) % 255, 255, 255);
    }

    // Show the colors on the LED strip
    FastLED.show();

    // Move the scanner position
    scannerPos = (scannerPos + 1) % (NUM_LEDS * 2 - 2);

    // Wait for a short duration
    delay(50);
  }
}
