#include <FastLED.h> // https://github.com/FastLED/FastLED

#define NUM_LEDS 60
#define MATRIX_PIN 6
// #define MATRIX_PIN 0 // ATtiny88
#define MAXBRIGHT 255

CRGB leds[NUM_LEDS];

volatile bool button; // type volatile for interrupt handler
int buttonPin = 2; // interrupt pin INT0

int count = 0; // indicates the button was pressed
int cases = 6; // number of functions available

unsigned long timer, timeout = 10 * 1000; // 5 seconds test

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();

  // configureButtonInterrupt();

  Serial.print(count);
  zero();
}

void loop() {
  // buttonRead();

  if (millis() - timer > timeout) {
    timer = millis();
    count++;
    if (count > cases)
      count = 1;
    FastLED.clear();
    FastLED.show();
    Serial.print(count);
  }

  switch (count) {
    case 0: zero(); break; // One pix, RGB.  The remaining pix are "white"
    case 1: scan(); break;
    case 2: evenodd(); break;
    case 3: sweep(); break;
    case 4: randomletters(); break;
    case 5: throbber(); break;
    case 6: marquee(); break;
  }
}

void zero() {
  int delayer = 250;
  leds[0] = CRGB::Red;   // red
  leds[1] = CRGB::Green; // grn
  leds[2] = CRGB::Blue;  // blu
  leds[3] = CRGB::White; // wht
  leds[4] = CRGB(random(1, 2) * random(MAXBRIGHT),
                 random(1, 2) * random(MAXBRIGHT),
                 random(1, 2) * random(MAXBRIGHT)); // random
  FastLED.show();
  delay(delayer);
}

void scan() {
  for (int whiteLed = 0; whiteLed < NUM_LEDS - 8; whiteLed = whiteLed + 1) {
    for (int j = 0; j < 9; j++) {
      leds[whiteLed + j] = CRGB::White;
    }
    FastLED.show();
    delay(25);
    leds[whiteLed] = CRGB::Black;
  }
  FastLED.clear();
  FastLED.show();
}

void randomletters() { // light random sections underlining letters
  int sectionLEDs[] = {10, 10, 10, 10, 10, 10};
  int sectionRandom = random(6); // number of sections
  int sectionStart = 0;
  int dimmer = 1;
  for (int i = 0; i < sectionRandom; i++) // first pixel of 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(500);
  FastLED.clear();
}

void throbber() { // throb all pixels
  int delayer = 100, dimmer = 1;
  for (int j = 25; j < MAXBRIGHT / dimmer; j += 10) { // brightness
    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) {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] =  CRGB(j, j, j);
    }
    FastLED.show();
    delay(delayer);
  }
}

void evenodd() { // wigwag
  int delayer = 100, dimmer = 2;
  for (int i = 0; i < NUM_LEDS; i += 2) {
    leds[i] =  CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  }
  FastLED.show();
  delay(delayer);
  FastLED.clear();
  for (int i = 1; i < NUM_LEDS; i += 2) {
    leds[i] =  CRGB(MAXBRIGHT / dimmer, MAXBRIGHT / dimmer, MAXBRIGHT / dimmer);
  }
  FastLED.show();
  delay(delayer);
  FastLED.clear();
}

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

void marquee() {
  int delay1 = 333, dimmer = 1;
  for (int j = 0; j < 3; j++) {
    for (int i = 0; i < NUM_LEDS; 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 |--|-|---|        |=| ** button removed for LOGO LIGHT
         | RST                 RST |  | |   +--------+
    +----| GND   5V  DO GND    TX1 |  | |
    | +--| Vin   DI  SCK  RST  RX1 |  | |
    | |  +-------------------------+  | |   +--------------+
    | |                               | |   | POWER SUPPLY |====||= MAINS
    | +-------------------------------+-|---| VCC 12vdc    |====||= MAINS
    +-----------------------------------+---| GND          |
                                            +--------------+
*/

void buttonRead() {
  if (button) { // button flag is returned from ISR
    delay(150); // debounce
    button = 0; // reset ISR flag
    count++; // increment selected pattern
    if (count > cases) { // if counter reached last case...
      count = 1; // ... reset counter to first case
    }
    FastLED.clear();
    FastLED.show();
    Serial.print(count);
  }
}

void configureButtonInterupt() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING); // INT#, ISR, TRIGGER
  Serial.print("Press the button to start animations.\nAnimation: ");
}

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
}