#include <Arduino.h>

constexpr byte ledPins[3] {9, 10, 11};   // red, yellow, green
constexpr char *userPrompt {"Please select red, yellow, green LED color-"};

constexpr byte numChars {10};
char buffer[numChars];   // an array to store the received data

enum class Color : byte { red, yellow, green, off, noColor };
const char *compare[4] {"red", "yellow", "green", "off"};   // Compare input with this strings

//
// Handle the input
//
bool recvWithEndMarker(char *receivedChars) {
  static byte ndx = 0;
  char rc;
  bool newData {false};
  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (rc != '\r' && rc != '\n') {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) { ndx = numChars - 1; }
    } else {
      receivedChars[ndx] = '\0';   // terminate the string
      ndx = 0;
      newData = true;
    }
  }
  return newData;
}

//
// Compare strings with the input
//
template <size_t N> Color cmpStr(const char *(&cmpstr)[N], const char *str) {
  for (byte i = 0; i < N; ++i) {
    if (!strcmp(cmpstr[i], str)) { return static_cast<Color>(i); }
  }
  return Color::noColor;
}

//
// Switch the LEDs according to the color entered
//
template <size_t N> void switchLeds(const byte (&ledPins)[N], Color color) {
  for (byte i = 0; i < N; ++i) { digitalWrite(ledPins[i], (static_cast<Color>(i) == color) ? HIGH : LOW); }
}

//
// Switch the LEDs off
//
template <size_t N> void switchLedsOff(const byte (&ledPins)[N]) {
  for (byte i = 0; i < N; ++i) { digitalWrite(ledPins[i], LOW); }
}

void setup() {
  Serial.begin(115200);
  for (auto &ledPin : ledPins) { pinMode(ledPin, OUTPUT); }   // Init ledPins as output
  Serial.println(userPrompt);
}

void processInput() {
  switch (cmpStr(compare, buffer)) {   // check input (compare strings)
    case Color::red: switchLeds(ledPins, Color::red); break;
    case Color::yellow: switchLeds(ledPins, Color::yellow); break;
    case Color::green: switchLeds(ledPins, Color::green); break;
    case Color::off: switchLedsOff(ledPins); break;
    case Color::noColor: break;   // String not recognized. Do nothing.
    default: break;
  }
  Serial.println(buffer);
  Serial.println();
  Serial.println(userPrompt);
  buffer[0] = '\0';
}

void loop() {
  if (recvWithEndMarker(buffer)) { processInput(); }
}