/*
  Forum: https://forum.arduino.cc/t/arduino-sketch-function-limits-script-kills-all-lights/1208706
  Wokwi: https://wokwi.com/projects/386390922739579905
*/
#include <FastLED.h>
#include <SerialCommand.h>
#include <SoftwareSerial.h>
// LED strip variable ---------------------------------------------------------------------------
#define NUM_LEDS 11
CRGB leds[NUM_LEDS];
#define LED_PIN 9
static int currentAmt;
// Engine fix variables----------------------------------------------------------------------------
struct engineLeds {
  byte pin = 0;
  boolean flash = false;
  byte state = LOW;
  void init(byte aPin) {
    pin = aPin;
    pinMode(pin, OUTPUT);
  }
  void set(byte aState) {
    if (state == aState) {
      return;
    }
    state = aState;
    digitalWrite(pin, state);
  }
  void toggle() {
    set(!state);
  }
  void handle() {
    if (flash) {
      toggle();
    } else {
      set(LOW);
    }
  }
};
const byte noOfLeds {3};
engineLeds led[noOfLeds];
const byte LEDPINs[noOfLeds] = {3, 4, 5};
unsigned long prevMillis = 0;
const long interval = 1000;
// communication between unity and arduino--------------------------------------------------
SerialCommand sCmd;
void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  // commands for fuel bar -----------------------------------------------------------------------
  sCmd.addCommand("FILL", fillHandler);
  sCmd.addCommand("RAISE", raiseHandler);
  sCmd.addCommand("LOWER", lowerHandler);
  sCmd.addCommand("EMPTY", emptyHandler);
  sCmd.addCommand("RED", redHandler);
  sCmd.addCommand("RESETGREEN", resetGreenHandler);
  // commands for engine leds--------------------------------------------------------------
  sCmd.addCommand("BLINK1", blink1);
  sCmd.addCommand("FIX1", fix1);
  sCmd.addCommand("BLINK2", blink2);
  sCmd.addCommand("FIX2", fix2);
  sCmd.addCommand("BLINK3", blink3);
  sCmd.addCommand("FIX3", fix3);
  // sets up the LED strip -------------------------------------------------------------------------
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); // sets up our strip
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500); // limits it to only take 5 volts
  FastLED.clear();
  FastLED.show();
  // sets up the engine LEDS ---------------------------------------------------------------------
  for (int i = 0; i < noOfLeds; i++) {
    led[i].init(LEDPINs[i]);
  }
}
void loop() {
  // for communicating between arduino and unity ----------------------------------------------------
  if (Serial.available() > 0) {
    sCmd.readSerial();
  }
  // engine light stuff ---------------------------------------------------------------------------------
  unsigned long currentMillis = millis();
  // this controls the on/off flashing, and also the ability to turn OFF the flashing
  if (currentMillis - prevMillis >= interval) {
    prevMillis = currentMillis;
    for (int i = 0; i < noOfLeds; i++) {
      led[i].handle();
    }
  }
}
// engine LED commands -----------------------------------------------------------------------------------------
void blink1(const char *command) {
  led[0].flash   = true;
}
void fix1(const char *command) {
  led[0].flash   = false;
}
void blink2(const char *command) {
  led[1].flash   = true;
}
void fix2(const char *command) {
  led[1].flash   = false;
}
void blink3(const char *command) {
  led[2].flash   = true;
}
void fix3(const char *command) {
  led[2].flash   = false;
}
// fuel bar commands ----------------------------------------------------------------------------------------------
void fillHandler(const char *command) {
  fill(CRGB(0, 255, 0), 20, NUM_LEDS);
  currentAmt = NUM_LEDS - 1;
}
void raiseHandler(const char *command) {
  if (currentAmt < NUM_LEDS - 1) {
    leds[currentAmt] = CRGB(0, 255, 0);
    FastLED.show();
    currentAmt += 1;
  } else if (currentAmt == NUM_LEDS - 1) {
    leds[currentAmt] = CRGB(0, 255, 0);
    FastLED.show();
  }
}
void lowerHandler(const char *command) {
  if (currentAmt > 1) {
    leds[currentAmt] = CRGB::Black;
    FastLED.show();
    currentAmt -= 1;
  } else if (currentAmt == 1) {
    leds[currentAmt] = CRGB::Black;
    FastLED.show();
  }
}
void emptyHandler(const char *command) {
  for (int i = currentAmt; i >= 0; i--) {
    leds[i] = CRGB::Black;
    FastLED.show();
    delay(20);
  }
  currentAmt = 1;
}
// turns the whole LED strip red ----------------------------------------------------------
void redHandler (const char *command) {
  fill(CRGB(255, 0, 0), 20, NUM_LEDS);
}
//turns the red off, and LED strip back to the amount of green it last had -----------------------------------------
void resetGreenHandler (const char *command) {
  fill(CRGB::Black, 0, NUM_LEDS);
  for (int i = 0; i < currentAmt; i++) {
    leds[i] = CRGB(0, 255, 0);
    FastLED.show();
    delay(20);
  }
}
void fill(CRGB color, int dely, int lastIndex) {
  for (int i = 0; i < lastIndex; i++) {
    leds[i] = color;
    FastLED.show();
    delay(dely);
  }
}