#include <FastLED.h>

#define NUM_LEDS 49
#define MATRIX_PIN 6
#define MAXBRIGHT 255

CRGB leds[NUM_LEDS];

volatile bool button; // type volatile for interrupt handler
int buttonPin = 3; // interrupt pin INT0
int count = 0; // indicates the button was pressed
int cases = 9; // number of functions available

bool buttonPressed, currentButtonState;

void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(A0));

  FastLED.addLeds<WS2812B, MATRIX_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(MAXBRIGHT); // Adjust the brightness value as needed
  FastLED.clear();
  FastLED.show();

  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING); // INT#, ISR, TRIGGER

  Serial.print("Press the button to see other animations.\nAnimation: ");
  Serial.print(count);
  zero();
}

void loop() {
  readbutton();

  // count = 9; // force a function
  switch (count) {
    case 0: zero(); break; // One pix, RGB.  The remaining pix are "white"
    case 1: trace(); break;
    case 2: evenodd(); break;
    case 3: zap(); break;
    case 4: zzzt(); break;
    case 5: sparklegap(); break;
    case 6: sparkle(); break;
    case 7: sections(); break;
    case 8: pulse(); break;
    case 9: marquee(); break;
  }
}

void buttonISR() {
  noInterrupts(); // disable interrupts while in the ISR
  button = 1; // set the flag that the button was pressed
  interrupts(); // enable interrupts when leaving the ISR
}

void readbutton() {
  // button read without interrupt
  // *****************************
  // bool currentButtonState = !digitalRead(buttonPin);
  // if (currentButtonState != buttonPressed) {
  //   buttonPressed = currentButtonState;
  //   if (buttonPressed) {
  //     button = 1;
  //     FastLED.clear();
  //     FastLED.show();
  //     Serial.print(++count);
  //   }
  // }

  if (button) { // check button flag after returning from ISR
    delay(150); // debounce the button
    button = 0; // reset ISR flag for the next interrupt/button press
    count++; // increment selected pattern/case
    if (count > cases) { // if counter reached last case...
      count = 1; // ... reset counter to first case
    }
    FastLED.clear();
    FastLED.show();
    Serial.print(count);
  }
}

void zero() {
  leds[0] = CRGB(255, 0, 0);    // red
  leds[1] = CRGB(0, 255, 0);    // grn
  leds[2] = CRGB(0, 0, 255);    // blu
  leds[3] = CRGB(255, 255, 255);  // wht
  leds[4] = CRGB(random(1, 2) * random(MAXBRIGHT),
                 random(1, 2) * random(MAXBRIGHT),
                 random(1, 2) * random(MAXBRIGHT));  // random
  FastLED.show();
  delay(200);
}

void pulse() { // 8 - pulse
  int delayer = 100, dimmer = 1;
  for (int j = 25; j < MAXBRIGHT / dimmer; j += 50) { // fade-in quickly
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] =  CRGB(j, j, j);
    }
    FastLED.show();
    delay(delayer);
  }
  for (int j = MAXBRIGHT / dimmer; j > 25; j -= 5) { // fade-out slowly
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] =  CRGB(j, j, j);
    }
    FastLED.show();
    delay(delayer);
  }
}

void sections() { // 7 - light random sections
  int dimmer = 1;
  int sectionLEDs[] = {13, 3, 7, 6, 9, 4, 7};
  int sectionRandom = random(7); // number of sections
  int sectionStart = 0;
  for (int i = 0; i < sectionRandom; i++) // find the start of the random section
    sectionStart += sectionLEDs[i];
  for (int i = sectionStart; i < sectionStart + sectionLEDs[sectionRandom]; i++)
    leds[i] = CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  FastLED.show();
  delay(100);
  FastLED.clear();
  FastLED.show();
  delay(random(300, 1000));
}

void sparkle() { // 6 - one random pixel
  int x = random(0, NUM_LEDS);
  leds[x] =  CRGB(MAXBRIGHT, MAXBRIGHT, MAXBRIGHT);
  FastLED.show();
  delay(random(100, 200));
  FastLED.clear();
  FastLED.show();
  // delay(random(100, 500));
}

void sparklegap() { // 5 - one random gap in the pixels
  int dimmer = 1;
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] =  CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  }
  FastLED.show();
  delay(random(100, 500));
  int x = random(0, NUM_LEDS);
  leds[x] = CRGB(0, 0, 0);
  FastLED.show();
  delay(random(10, 100));
  leds[x] =  CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  FastLED.show();
}

void zzzt() { // 4 - all pixels flickering
  int dimmer = 1;
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] =  CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  }
  FastLED.show();
  delay(random(300, 3000));
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] =  CRGB(0, 0, 0);
  }
  FastLED.show();
  delay(random(20, 80));
}

void zap() { // 3 - pixels lighting to pointy part
  for (int i = 0; i < NUM_LEDS / 2 + 1; i++) {
    leds[24 + i] =  CRGB(MAXBRIGHT, MAXBRIGHT, MAXBRIGHT);
    leds[24 - i] =  CRGB(MAXBRIGHT, MAXBRIGHT, MAXBRIGHT);
    FastLED.show();
    delay(5);
  }
  delay(random(100));
  for (int i = 0; i < NUM_LEDS / 2 + 1; i++) {
    leds[48 - i] =  CRGB(0, 0, 0);
    leds[00 + i] =  CRGB(0, 0, 0);
    FastLED.show();
    delay(5);
  }
  delay(random(2000));
}

void evenodd() { // 2 - marquee
  int local = 250;
  for (int i = 0; i < NUM_LEDS; i += 2) {
    leds[i] =  CRGB(MAXBRIGHT, MAXBRIGHT, MAXBRIGHT);
  }
  FastLED.show();
  delay(local);
  FastLED.clear();
  for (int i = 1; i < NUM_LEDS; i += 2) {
    leds[i] =  CRGB(MAXBRIGHT, MAXBRIGHT, MAXBRIGHT);
  }
  FastLED.show();
  delay(local);
  FastLED.clear();
}

void trace() { // 1 - trace around all pixels
  for (int j = 0; j < 2; j++) {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] =  CRGB(j * MAXBRIGHT, j * MAXBRIGHT, j * MAXBRIGHT);
      FastLED.show();
      delay(50);
    }
  }
}

void marquee() {
  int delay1 = 333, dimmer = 1;
  for (int j = 0; j < 3; j++) {
    for (int i = 0; i < NUM_LEDS - 3; i += 3) {
      leds[i + j] = CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
    }
    FastLED.show();
    FastLED.clear();
    delay(delay1);
  }
}

/*
  WS2812B - VCC - 1000uF ECAP(+)        - Arduino VIN - Power supply (+)
          - SIG - 300-500 Ohm resistor  - Arduino SIG - x
          - GND - 1000uF ECAP(-)        - Arduino GND - Power supply (-)

         +----------| USB |--------+       +-----+
         | D13/SCK        MISO/D12 |       |E.CAP|
         | 3.3V           MOSI/D11~|       |1k uF|
         | Vref             SS/D10~|       +-----+
         | A0                   D9~|      -|     |+        +--------------+
         | A1       NANO        D8 |  +----|-----+---------| VCC          |
         | A2                   D7 |  | +--+---------------| GND          |
         | A3                   D6~|--|-|-----|470R Ohm|---| SIG  WS2812B |
         | A4/SDA               D5~|  | |                  +--------------+
         | A5/SCL               D4 |  | |
         | A6              INT1/D3~|  | |   +--------+
         | A7              INT0/D2 |--|-|---| BUTTON |
         | 5V                  GND |--|-|---|        |=|
         | RST                 RST |  | |   +--------+
    +----| GND   5V  DO GND    TX1 |  | |
    | +--| Vin   DI  SCK  RST  RX1 |  | |
    | |  +-------------------------+  | |   +--------------+
    | |                               | |   | POWER SUPPLY |====||= MAINS
    | +-------------------------------+-|---| VCC          |====||= MAINS
    +-----------------------------------+---| GND          |
                                            +--------------+
*/