// waterfal.ino
// https://youtu.be/IwoQO7lnJRE
// https://forum.arduino.cc/t/hi-i-need-a-white-color-water-run-effect-for-arduino-when-arduino-starts-run-the-effect-and-stay-the-light-on/1186544/
// - Four LED strands increasing length - 10m, 11m, 12m, 13m
// - Start extending at 1m/s with the shortest strand
// - Longest strand finishes last
// - Start retracting at 2m/s with longest strand

#include <FastLED.h>

#define LEDs_per_meter 10
int stripLEDStart[] = {0, 100, 210, 330}; // pixels (0 - 99) (100 - 209) (210 - 329) (330 - 459)
int stripLEDCount[] = {100, 110, 120, 130}; // length of strip in cm
int stripCounter[4]; // count the LEDs
#define totalLEDs 460
#define MULTIPLIER 1 // change to 3 for 1380 Neopixels at 30 LEDs per meter

float paceExtend[] = {0, .5, 1.0, 1.5}; // strips extend proportionally
float paceRetract[] = {6, 4, 2, 0}; // strips retract proportionally

int buttonPin = 2; // select the effect
bool effect = 0; // 0 (extend) or 1 (retract)

#define MATRIX_PIN 5
#define BRIGHTNESS 255

// colors
#define full 255 // full bright
#define some full / 2 // 1 = full bright, 2 = half bright, 4 = quarter bright
#define none 0

#define red some, none, none // the color red
#define grn none, some, none
#define blu none, none, some
#define cyn none, some, some
#define yel some, some, none
#define mag some, none, some
#define wht some, some, some
#define blk none, none, none
 
CRGB leds[totalLEDs];

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, MATRIX_PIN, GRB>(leds, totalLEDs * MULTIPLIER);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();

  for (int i = 0; i > 4; i++) {
    paceExtend[i] = paceExtend[i] * LEDs_per_meter;
    paceRetract[i] = paceRetract[i] * LEDs_per_meter;
  }

  pinMode(buttonPin, INPUT_PULLUP); // start button on pin 2
  Serial.print(F("Press the red button to Extend.  "));
}

void loop() {
  checkButton();
}

void checkButton() {
  if (digitalRead(buttonPin) == 0) {
    delay(150); // debounce
    if (effect == 0) {
      Serial.print(F("Extending.  Shortest ("));
      Serial.print(stripLEDCount[0]);
      Serial.println(F("cm) first. Spacing 1.0 meter."));
      extend();
    }
    if (effect == 1) {
      Serial.print(F("Retracting. Longest ("));
      Serial.print(stripLEDCount[3]);
      Serial.println(F("cm) first.  Spacing 2.0 meters."));
      retract();
    }
    effect = !effect;
  }
}

void extend() { // start with the shortest string in intervals of half a second
  for (int i = 0; i < stripLEDCount[3] + LEDs_per_meter * 1.5; i++) {
    for (int x = 0; x < 4; x++) {
      if (i >= LEDs_per_meter * paceExtend[x] && i < stripLEDCount[x] + LEDs_per_meter * paceExtend[x]) {
        leds[stripCounter[x] + stripLEDStart[x]] = CRGB(wht);
        stripCounter[x]++;
      }
    } 
    FastLED.show();
  }
  for (int i = 0; i < 4; i++)
    stripCounter[i] = 0;
  Serial.print(F("Press the red button to Retract. "));
}

void retract() { // start with the longest string in intervals of two meters
  for (int i = 0; i < stripLEDCount[3] + LEDs_per_meter * 3; i++) {
    for (int x = 0; x < 4; x++) {
      if (i >= LEDs_per_meter * paceRetract[x] && i < stripLEDCount[x] + LEDs_per_meter * paceRetract[x]) {
        leds[stripLEDCount[x] + stripLEDStart[x] - stripCounter[x] - 1] = CRGB(blk);
        stripCounter[x]++;
      }
    }
    FastLED.show();
  }
  for (int i = 0; i < 4; i++)
    stripCounter[i] = 0;
  Serial.print(F("Press the red button to Extend.  "));
}