// Button management library
#include <Toggle.h>
const byte buttonPin = 4; // Our button is on pin 4
Toggle button;

// Pins used for LEDs
const byte pinRedLed = 8;
const byte pinOrangeLed = 9;
const byte pinYellowLed = 10;
const byte pinGreenLed = 11;

// Introducing time as an additional event
unsigned long chrono; // Note: unsigned long, like millis()
const unsigned long TimeOut = 15000ul; // 15 seconds (ul at the end for unsigned long, a good habit to adopt)

// The list of possible states of our system
// along with a currentState variable taking one of these values
enum {REST, STATE_G, STATE_GY, STATE_GYO, STATE_GYOR} currentState;

void turnLedsOff() {
  digitalWrite(pinGreenLed, LOW);
  digitalWrite(pinYellowLed, LOW);
  digitalWrite(pinOrangeLed, LOW);
  digitalWrite(pinRedLed, LOW);
}

void runStateMachine() {
  button.poll(); // update the state of the button

  // TEST FOR CLICK
  switch (currentState) {
    case REST:                            // we are at rest and if we get a click, turn on the green LED
      if (button.onPress()) {             // this is our event detection
        digitalWrite(pinGreenLed, HIGH);  // execute the associated action. Green LED powered
        chrono = millis();                // We just had an action, so we reset our stopwatch
        currentState = STATE_G;           // note the new state of our system
      }
      break;

    case STATE_G:                         // green LED was on and if we get a click, turn on the yellow LED
      if (button.onPress()) {             // this is our event detection
        digitalWrite(pinYellowLed, HIGH); // execute the associated action. Yellow LED powered
        chrono = millis();                // We just had an action, so we reset our stopwatch
        currentState = STATE_GY;          // note the new state of our system
      }
      break;

    case STATE_GY:                        // green and yellow were on, if we get a click, turn on the orange LED
      if (button.onPress()) {             // this is our event detection
        digitalWrite(pinOrangeLed, HIGH); // execute the associated action. Orange LED powered
        chrono = millis();                // We just had an action, so we reset our stopwatch
        currentState = STATE_GYO;         // note the new state of our system
      }
      break;

    case STATE_GYO:                       // green, orange, and yellow were on, if we get a click, turn on the red LED
      if (button.onPress()) {             // this is our event detection
        digitalWrite(pinRedLed, HIGH);    // execute the associated action. Red LED powered
        chrono = millis();                // We just had an action, so we reset our stopwatch
        currentState = STATE_GYOR;        // note the new state of our system
      }
      break;

    case STATE_GYOR:                      // everything was on, if we get a click a click, return to rest
      if (button.onPress()) {             // this is our event detection
        turnLedsOff();                    // execute the associated action. return to the initial state
        chrono = millis();                // We just had an action, so we reset our stopwatch
        currentState = REST;
      }
      break;
  }

  // TEST FOR TIMEOUT
  if ((currentState != REST) && (millis() - chrono >= TimeOut)) {     // timeout event
    turnLedsOff();
    currentState = REST;
  }
}

// ------------------------------------------------------
// We initialize our system in the setup
// ------------------------------------------------------
void setup() {
  // configure
  pinMode(pinRedLed, OUTPUT);
  pinMode(pinOrangeLed, OUTPUT);
  pinMode(pinYellowLed, OUTPUT);
  pinMode(pinGreenLed, OUTPUT);

  button.begin(buttonPin);

  // define Initial conditions
  turnLedsOff();
  currentState = REST;

}

void loop() {
  // we update ou system based on possible events
  runStateMachine();

  // Here, we can do other things as long as it doesn't take too long and is non blocking
}