// https://forum.arduino.cc/t/how-to-delay-using-millis/1142938
// https://wokwi.com/projects/395060119030612993

// version 5. Sue me.

const byte buttonPin = 2;
const byte ledPin = 3;

const unsigned long actionDelay = 3500; // action 3.5 seconds for testing - life too short

void setup() {
  Serial.begin(115200);
  Serial.println("\nWake up!\n");

  pinMode (buttonPin, INPUT_PULLUP);
  pinMode (ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

# define RATE 20    // milliseconds per loop (50 Hz)
# define PRESST LOW

void loop() {
  static unsigned long lastLoop;

  static byte previousButton;
  static byte theState;

  static unsigned long startTime; // time at action
  static bool inTestPhase;        // are we testing?

  bool gotPressed = false;        // set each loop - use it or lose it
  bool gotReleased = false;       // also

  unsigned long now = millis();   // fancier 'currentMillis' ooh!

// just run the rest of this at 1000 / RATE Hz

  if (now - lastLoop < RATE) return;
  lastLoop = now;


// INPUT
// read and deglitch the input
  int button = digitalRead(buttonPin) == PRESST;

  if (button == previousButton) {   // stable input
    if (button != theState) {       // edge detected

      if (button) {
        // Serial.println("I see that go pressed");
        gotPressed = true;
      }
      else {
        // Serial.println("I see that go released");
        gotReleased = true;
      }

      theState = button;
    }
  }
  previousButton = button;

// PROCESS
// now we have theState, and gotPressed and gotReleased to work with and we develop

  bool passed = false;
  bool failed = false;

// when the button is pressed, reset the timer, turn ON the LED

  if (gotPressed) {
    startTime = now;
    digitalWrite(ledPin, HIGH);
    Serial.println("                 new world. LED ON");
    inTestPhase = true;
  }

  if (!theState && inTestPhase) {
    digitalWrite(ledPin, LOW);
    Serial.println("            device failed..."); 
    failed = true;  
    inTestPhase = false; 
  }

// when (if!) the timer expires, see if we made it or not
  if (now - startTime >= actionDelay) {

// but we do the thing just once
    if (inTestPhase) {
      digitalWrite(ledPin, LOW);
      Serial.println("                            timer!"); 

      if (theState) {
        Serial.println("You made it! I hope you feel a m a z i n g!");
        passed = true;
      }
      else {
        Serial.println("this should never print.");
      }
    
      inTestPhase = false;
    }
  }

// OUTPUT
  if (passed) Serial.println("\nPASS");
  if (failed) Serial.println("\nFAIL");
}