//https://github.com/Jestriker/police-lights-arduino
//https://maker.pro/arduino/projects/20-leds-based-led-chaser-project-using-arduino-uno

#define t   30
#define t1  20
#define t2  100
#define t3  50
//#define numLeds 12

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

// https://www.arduino.cc/reference/en/language/variables/utilities/sizeof/
// sizeof(); https://forum.arduino.cc/t/how-do-you-check-the-length-of-an-array/88325/7
int numLeds = sizeof(leds) / sizeof(int);

void setup() {
  for (int pin = 0; pin < numLeds; pin++) {
    pinMode(leds[pin], OUTPUT);
  }
}

//Main Loop - Switches different LED Patterns
void loop() {
  for (int j = 0; j < 10 ; j++) {
    onrun(20);
    offrun(50);
    flash(150);
    alternate(200);
    stack(20);
    drawstack(random(18));
    chaser(50);
  }
}

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

void fillall() {
  for (int pin = 0; pin < numLeds; pin++) {
    digitalWrite(leds[pin], HIGH);
  }
}

//One ON LED Run and all other OFF
void onrun(int delaytime) {
  for (int pin = 0; pin < numLeds; pin++)  {
    clearall();
    digitalWrite(leds[pin], HIGH);
    delay(delaytime);
  }
  for (int pin = numLeds - 1; pin >= 0; pin--) {
    clearall();
    digitalWrite(leds[pin], HIGH);
    delay(delaytime);
  }
}

//One OFF LED Run and all other OFF
void offrun(int delaytime) {
  for (int pin = 0; pin <= 19; pin++) {
    fillall();
    digitalWrite(pin, LOW);
    delay(delaytime);
  }
  for (int pin = 19; pin >= 0; pin--) {
    fillall();
    digitalWrite(pin, LOW);
    delay(delaytime);
  }
}

//Flashing all LEDs ON and OFF
void flash(int delaytime) {
  for (int i = 0; i < numLeds; i++) {
    clearall();
    delay(delaytime);
    fillall();
    delay(delaytime);
  }
}

//Alternate Flash - Similar to Flash but alternate LEDs
void alternate(int delaytime) {
  for (int n = 1; n <= 5; n++) {
    clearall();
    for (int i = 0; i < numLeds; i += 2) {
      digitalWrite(leds[i], HIGH);
    }
    delay(delaytime);
    clearall();
    for (int j = 1; j < numLeds; j += 2) {
      digitalWrite(leds[j], HIGH);
    }
    delay(delaytime);
  }
}

//Putting all LEDs one by one in a stack
void stack(int delaytime) {
  int stack = 0;
  while (stack < numLeds) {
    for (int pos = 0; pos <= (numLeds - 1 - stack); pos++) {
      clearall();
      digitalWrite(leds[pos], HIGH);
      drawstack(stack);
      delay(delaytime);
    }
    stack++;
  }
}
//Subfunction of the stack function
void drawstack(int stack) {
  for (int n = numLeds - 1; n > (numLeds - 1 - stack); n--) {
    if (n >= 0) {
      digitalWrite(leds[n], HIGH);
      delay(20);
    }
  }
  clearall();
}
//One LED chases another LED front and back
void chaser(int delaytime) {
  int div = 40;
  int flashtime = delaytime / div;
  int A = random(2, 7);
  int B = random(7, 12);
  int Av = 1;
  int Bv = 1;
  if (random(0, 2)) {
    Av *= -1;
  }
  if (random(0, 2)) {
    Bv *= -1;
  }
  for (int time = 1; time < 100; time++) {
    if (abs(A - B) == 1 && (Av * Bv) == -1) {
      for (int f = 1; f < round(div / 4); f++) {
        clearall();
        delay(flashtime);
        digitalWrite(A, HIGH);
        digitalWrite(B, HIGH);
        delay(flashtime);
      }
      Av *= -1;
      Bv *= -1;
      A += Av;
      B += Bv;
    }
    else {
      clearall();
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      A += Av;
      B += Bv;
      delay(delaytime);
    }
    if (A < 0) {
      A = 1;
      Av *= -1;
    }
    if (B > numLeds + 1) {
      B = numLeds;
      Bv *= -1;
    }
    if (A >= B) {
      A = B - 1;
    }
  }
}