using uint = unsigned int;
using ulong = unsigned long;

constexpr byte LED_PINS[5] {3, 4, 5, 6, 7};

// Time im milliseconds (ms)
constexpr ulong LIGHT_DELAY_MS {500};   // Time between two LDR measurements

// Class / struct Definition(s)

//////////////////////////////////////////////////////////////////////////////
/// @brief Helper class for non-blocking execution of
/// code sections at certain intervals.
///
//////////////////////////////////////////////////////////////////////////////
class Interval {
public:
  //////////////////////////////////////////////////////////////////////////////
  /// @brief  Determine whether the specified interval has expired.
  ///
  /// @param duration    Interval duration
  /// @return true       when the interval has elapsed
  /// @return false      interval not elapsed yet
  //////////////////////////////////////////////////////////////////////////////
  bool operator()(const ulong duration) {
    if (false == isStarted) { return start(false); }
    return (millis() - timeStamp >= duration) ? start(true) : retFalse();
  }

private:
  bool start(bool state = false) {
    isStarted = !state;   // Set the value to true on the first call
    timeStamp = millis();
    return state;
  }
  bool retFalse() { return false; }

private:
  bool isStarted {false};   // Flag = true if the first Operator() call has been made.
  ulong timeStamp {0};
};

// Class / struct Definition(s) end

//
// Global variables/objects
//
Interval timer;

//
// Functions
//
template <size_t N> void setLeds(const byte (&pins)[N], byte &lastIdx ){
  byte idx;
  do {   // Prevents the same (random)number from being used twice in a row.
    idx = random(0, N);   
  } while (idx == lastIdx);   
  digitalWrite(pins[lastIdx], LOW);
  lastIdx = idx;
  digitalWrite(pins[idx], HIGH);
}

//
// Main
//
void setup() {
  Serial.begin(115200);
  for (auto pin : LED_PINS) { pinMode(pin, OUTPUT); }
  randomSeed(A0);
}

void loop() {
  static byte currentLedIndex {0};
  if (true == timer(LIGHT_DELAY_MS)) { setLeds(LED_PINS, currentLedIndex); }  
}