#include <Button_SL.hpp>   // Description: https://github.com/DoImant/Button_SL

using namespace Btn;

//
// Global constants
//
constexpr uint8_t LEDGRP_PINS[] {2, 3, 4, 5};
constexpr uint8_t LEDGRP_NUM {sizeof(LEDGRP_PINS) / sizeof(LEDGRP_PINS[0])};
constexpr uint8_t LEDEXTRA_PIN {11};
constexpr uint32_t DELAY_MS {1000};

//////////////////////////////////////////////////////////////////////////////
/// Helperclass for timer operations
///
//////////////////////////////////////////////////////////////////////////////
class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const uint32_t duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  uint32_t timeStamp {0};
};

///
/// Global variables / objects
///
enum class State : uint8_t { idle, sequence, waitForReset };

ButtonSL startBtn {8};
ButtonSL resetBtn {9};
ButtonSL extraBtn {10};
Timer wait;

///
/// Function(s)
///
void fsm() {
  static State state {State::idle};
  static uint8_t ledIdx {0};

  switch (state) {
    case State::idle:
      if (startBtn.tick() != ButtonState::notPressed) { state = State::sequence; }
      break;
    case State::sequence:
      if (extraBtn.tick() == ButtonState::shortPressed && !digitalRead(LEDEXTRA_PIN)) {
        digitalWrite(LEDEXTRA_PIN, HIGH);
      }
      if (wait(DELAY_MS)) {
        digitalWrite(LEDGRP_PINS[ledIdx], HIGH);
        if (++ledIdx < LEDGRP_NUM) {
          wait.start();
        } else {
          state = State::waitForReset;
        }
      }
      break;
    case State::waitForReset:
      if (resetBtn.tick() != ButtonState::notPressed) {
        for (const auto &pin : LEDGRP_PINS) { digitalWrite(pin, LOW); }
        digitalWrite(LEDEXTRA_PIN, LOW);
        ledIdx = 0;
        state = State::idle;
      }
      break;
    default: break;
  }
}

///
/// Main
///
void setup() {
  //  Init Buttons
  startBtn.begin();
  resetBtn.begin();
  extraBtn.begin();
  startBtn.setDebounceTime_ms(40);
  resetBtn.setDebounceTime_ms(40);
  extraBtn.setDebounceTime_ms(40);

  for (const auto &pin : LEDGRP_PINS) { pinMode(pin, OUTPUT); }
  pinMode(LEDEXTRA_PIN, OUTPUT);
}

void loop() { fsm(); }
start
reset
extra