#define t1 20

#define numLeds 18  // Number of LEDs
#define halfLeds numLeds / 2

int leds[numLeds] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};

void setup() {
  // set up pins 2 to 13 as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(leds[i], OUTPUT);
  }

  randomSeed(analogRead(7));
}

void loop() {
  //kRider(80);
  //test(random(20, 50));
  test(100);
  //test1(random(20, 50));
  //effect1(30);
  //effect3(4);
  //effect3a(4);
  //  effect4();
  //  effect5();
  //  chaseReverse();
  //  knightRider();
  //  rippleEffect(80);
  //  fadingEffect();
  //  randomBlink();
  //  breathingEffect();
  policeLights();
  //  flashEffect();
  //  waveEffect();
  //  heartbeatEffect();
  //  theaterChase();
  //  randomFlashingEffect();
}

void kRider(int t) {
  // Knight Rider effect: LEDs moving back and forth
  for (int i = 0; i < numLeds; i++) {
    // Turn on the current LED
    digitalWrite(leds[i], HIGH);
    // Turn off the previous LED (if it's not the first LED)
    if (i > 0) {
      digitalWrite(leds[i - 1], LOW);
    }
    delay(t); // Adjust the delay time to change the speed
  }

  // Knight Rider effect: LEDs moving back
  for (int i = numLeds - 1; i >= 0; i--) {
    // Turn on the current LED
    digitalWrite(leds[i], HIGH);
    // Turn off the next LED (if it's not the last LED)
    if (i < numLeds - 1) {
      digitalWrite(leds[i + 1], LOW);
    }
    delay(t); // Adjust the delay time to change the speed
  }
}

void test(int t) {
  for (int t = 0; t < 100; t++) {  // Repeat the pattern multiple times
    for (int i = 0; i < numLeds; i = i + 2) {
      digitalWrite(leds[i], HIGH);
      //delay(50);
    }
    delay(t);
    for (int i = 0; i < numLeds; i = i + 2) {
      digitalWrite(leds[i], LOW);
      //delay(50);
    }
    delay(t);
    for (int i = 1; i < numLeds; i = i + 2) {
      digitalWrite(leds[i], HIGH);
      //delay(50);
    }
    delay(t);
    for (int i = 1; i < numLeds; i = i + 2) {
      digitalWrite(leds[i], LOW);
      //delay(50);
    }
    delay(t);
  }
}

void test1(int t) {
  for (int i = 0; i < numLeds; i = i + 2) {
    digitalWrite(leds[i], HIGH);
    delay(50);
  }
  //delay(t);
  for (int i = 0; i < numLeds; i = i + 2) {
    digitalWrite(leds[i], LOW);
    delay(50);
  }
  //delay(t);
  for (int i = 1; i < numLeds; i = i + 2) {
    digitalWrite(leds[i], HIGH);
    delay(50);
  }
  //delay(t);
  for (int i = 1; i < numLeds; i = i + 2) {
    digitalWrite(leds[i], LOW);
    delay(50);
  }
  //delay(t);
}

void clearAll() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(leds[i], LOW);
  }
}

void effect5() {
  // clearAll();  // Optional: Clear all LEDs at the start if necessary

  for (int i = 0; i < numLeds; i++) {
    for (int j = 0; j < numLeds; j++) {
      // Keep the last LED (first in array) lit
      digitalWrite(leds[0], HIGH);  // Keep the first LED on

      // Correcting the index to stay within bounds
      if (numLeds - 1 - i >= 0 && numLeds - 1 - i < numLeds) {
        digitalWrite(leds[numLeds - 1 - i], HIGH);  // Use valid index for i
      }

      delay(t1);

      // Prevent negative index access
      if (j - i >= 0 && j - i < numLeds) {
        digitalWrite(leds[j - i], HIGH);
        delay(t1);
        digitalWrite(leds[j - i], LOW);
        delay(t1);
      }
    }
  }
}


void effect4() {
  // clearAll();  // Optional: Clear all LEDs at the start if necessary

  for (int i = 0; i < numLeds; i++) {
    for (int j = 0; j < numLeds; j++) {
      // Correcting the index to stay within bounds
      if (numLeds - 1 - i >= 0 && numLeds - 1 - i < numLeds) {
        digitalWrite(leds[numLeds - 1 - i], HIGH);  // Use valid index for i
      }

      delay(t1);

      // Prevent negative index access
      if (j - i >= 0 && j - i < numLeds) {
        digitalWrite(leds[j - i], HIGH);
        delay(t1);
        digitalWrite(leds[j - i], LOW);
        delay(t1);
      }
    }
  }
}


void effect3(int t) {
  clearAll();  // Optional: Clear all LEDs at the start if necessary

  for (int i = 0; i < numLeds; i++) {
    for (int j = 0; j < numLeds; j++) {
      // Correcting the index to stay within bounds
      if (numLeds - i >= 0 && numLeds - i < numLeds) {
        digitalWrite(leds[numLeds - i], HIGH);  // Use valid index for i
        delay(t);
      }

      delay(t);

      // Prevent negative index access
      if (j - i >= 0 && j - i < numLeds) {
        digitalWrite(leds[j - i], HIGH);
        delay(t);
        digitalWrite(leds[j - i], LOW);
        delay(t);
      }
    }
  }
}

void effect3a(int t) {
  clearAll();  // Optional: Clear all LEDs at the start if necessary

  for (int i = numLeds - 1 ; i >= 0; i--) {
    for (int j = numLeds - 1 ; j >= 0; j--) {
      // Correcting the index to stay within bounds
      if (numLeds - i >= 0 && numLeds - i < numLeds) {
        digitalWrite(leds[numLeds - i], HIGH);  // Use valid index for i
        delay(t);
      }

      delay(t);

      // Prevent negative index access
      if (j - i >= 0 && j - i < numLeds) {
        digitalWrite(leds[j - i], HIGH);
        delay(t);
        digitalWrite(leds[j - i], LOW);
        delay(t);
      }
    }
  }
}




void effect1(int t) {
  clearAll();
  for (int pin = numLeds - 1 ; pin >= 0; pin--) {
    //for (int j = numLeds - 1 ; j >= 0; j--) {
    //for (int j = 0; j < numLeds; j++) {

    digitalWrite(leds[pin], HIGH);
    delay(t);
    digitalWrite(leds[pin], LOW);
    delay(t);
    //digitalWrite(leds[pin - j], HIGH);
    //delay(t1);
    //}
  }
}

void chaseReverse() {
  clearAll();

  // Forward loop
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(leds[i], HIGH);
    delay(t1);
    digitalWrite(leds[i], LOW);
  }

  // Reverse loop
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(leds[i], HIGH);
    delay(t1);
    digitalWrite(leds[i], LOW);
  }
}

void knightRider() {
  clearAll();

  int delayTime = 100; // Adjust for speed
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(leds[i], HIGH);
    delay(delayTime);
    digitalWrite(leds[i], LOW);
  }
  for (int i = numLeds - 2; i > 0; i--) {
    digitalWrite(leds[i], HIGH);
    delay(delayTime);
    digitalWrite(leds[i], LOW);
  }
}

void rippleEffect(int t) {
  clearAll();

  int center = numLeds / 2;
  for (int i = 0; i <= center; i++) {
    if (center + i < numLeds) digitalWrite(leds[center + i], HIGH);
    if (center - i >= 0) digitalWrite(leds[center - i], HIGH);
    delay(t);
  }
}

void fadingEffect() {
  int pwmPins[] = {3, 5, 6, 9, 10, 11};  // List only the PWM-capable pins
  int numPwmPins = sizeof(pwmPins) / sizeof(pwmPins[0]);

  for (int brightness = 0; brightness <= 255; brightness += 5) {
    for (int i = 0; i < numPwmPins; i++) {
      analogWrite(pwmPins[i], brightness);
    }
    delay(30);
  }

  for (int brightness = 255; brightness >= 0; brightness -= 5) {
    for (int i = 0; i < numPwmPins; i++) {
      analogWrite(pwmPins[i], brightness);
    }
    delay(30);
  }
}


void randomBlink() {
  clearAll();

  for (int i = 0; i < 10; i++) {
    int randomLed = random(0, numLeds);
    digitalWrite(leds[randomLed], HIGH);
    delay(random(20, 200));  // Random delay between blinks
    digitalWrite(leds[randomLed], LOW);
  }
}

void breathingEffect() {
  int pwmPins[] = {3, 5, 6, 9, 10, 11};  // List only the PWM-capable pins
  int numPwmPins = sizeof(pwmPins) / sizeof(pwmPins[0]);
  int brightness = 0;
  int fadeAmount = 5;

  for (int i = 0; i < 255; i++) {
    for (int j = 0; j < numPwmPins; j++) {
      analogWrite(pwmPins[j], brightness);
    }
    brightness += fadeAmount;

    if (brightness <= 0 || brightness >= 255) {
      fadeAmount = -fadeAmount; // Reverse the direction of fading
    }
    delay(30);
  }
}

void policeLights() {
  for (int i = 0; i < 5; i++) {  // Repeat the pattern multiple times
    // Set all LEDs to blue
    for (int j = 0; j < halfLeds; j++) {
      digitalWrite(leds[j], HIGH); // Turn on all LEDs (blue)
    }
    delay(150);
    // Turn off all LEDs
    clearAll();

    // Set all LEDs to red
    for (int j = halfLeds; j < numLeds; j++) {
      digitalWrite(leds[j], HIGH); // Turn on all LEDs (red)
    }
    delay(150);
    // Turn off all LEDs
    clearAll();
  }
}

void flashEffect() {
  clearAll();

  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < numLeds; j++) {
      digitalWrite(leds[j], HIGH);
    }
    delay(200);
    clearAll();
    delay(200);
  }
}

void waveEffect() {
  clearAll();

  for (int i = 0; i < numLeds; i++) {
    digitalWrite(leds[i], HIGH);
    delay(100);
    digitalWrite(leds[i], LOW);
  }

  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(leds[i], HIGH);
    delay(100);
    digitalWrite(leds[i], LOW);
  }
}

void heartbeatEffect() {
  for (int i = 0; i < 3; i++) {
    for (int brightness = 0; brightness < numLeds; brightness++) {
      digitalWrite(leds[brightness], HIGH); // Turn on all LEDs
    }
    delay(300); // Keep them on for a moment
    clearAll(); // Turn them off
    delay(200); // Wait before next heartbeat
  }
}

void theaterChase() {
  for (int j = 0; j < 10; j++) { // Repeat the chase effect
    for (int i = 0; i < numLeds; i += 3) {
      digitalWrite(leds[i], HIGH);
    }
    delay(100);
    clearAll();

    for (int i = 0; i < numLeds; i += 3) {
      digitalWrite(leds[(i + 1) % numLeds], HIGH);
    }
    delay(100);
    clearAll();

    for (int i = 0; i < numLeds; i += 3) {
      digitalWrite(leds[(i + 2) % numLeds], HIGH);
    }
    delay(100);
    clearAll();
  }
}

void randomFlashingEffect() {
  clearAll();

  for (int i = 0; i < 20; i++) {
    int randomLed = random(0, numLeds);
    digitalWrite(leds[randomLed], HIGH);
    delay(random(50, 200));
    digitalWrite(leds[randomLed], LOW);
    delay(random(50, 200));
  }
}