/*
  Based on countdown timer:
  https://home.et.utwente.nl/slootenvanf/2020/06/08/countdown-timers-tasks-in-parallel/

  Avoid use of delays by using tasks that are executed on a certain time.

  Author: F. van Slooten
*/

#include <Bounce2.h>

#define RED A3    // Red light connected to analog pin A3
#define YELLOW A4 // Yellow light connected to analog pin A5
#define GREEN A5 // Green light connected to analog pin A4
#define BUZZER 9

// leds for difficuly level:
#define LED_EASY_PIN 4
#define LED_MEDIUM_PIN 3
#define LED_HARD_PIN 2

byte button_pins[] = { 5, 6, 7 }; // button pins for difficulty

#define NUMBUTTONS sizeof(button_pins)

Bounce * buttons = new Bounce[NUMBUTTONS];

unsigned long previousMillis = 0, previousMillis2 = 0; // will store last time timer was updated

unsigned long interval = 1000; // 1 second

int difficulty = 2; // 1 = easy, 2 = medium, 3 = hard

int state = 0; // blinking the leds

bool blink = true;

void setup() {
  Serial.begin(9600);

  // Initialize the pins as outputs
  pinMode(GREEN, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(YELLOW, OUTPUT);
  pinMode(LED_EASY_PIN, OUTPUT);
  pinMode(LED_MEDIUM_PIN, OUTPUT);
  pinMode(LED_HARD_PIN, OUTPUT);
  pinMode(BUZZER, OUTPUT);

  // Make input & enable pull-up resistors on switch pins
  for (int i = 0; i < NUMBUTTONS; i++) {
    buttons[i].attach( button_pins[i] , INPUT_PULLUP  );       //setup the bounce instance for the current button
    buttons[i].interval(25);              // interval in ms
  }
  // initialize random generator
  randomSeed(analogRead(0));

  // show difficulty (starts as medium):
  digitalWrite(LED_EASY_PIN, LOW);
  digitalWrite(LED_MEDIUM_PIN, HIGH);
  digitalWrite(LED_HARD_PIN, LOW);
}

void loop() {
  unsigned long currentMillis = millis();

  interval = random(3000, 7000); // Generate random delays for each light change

  // task 1 - update blinking
  if (currentMillis - previousMillis > interval) { // interval passed?
    previousMillis = currentMillis; // save the last time
    if (state==0) {
      red_light();
    } else if (state==1) {
      yellow_light();
    } else if (state==2) {
      green_light();
    } else if (state==3) {
      buzzer_sound();
      yellow_light();
    } else if (state==4) {
      buzzer_sound_off();
      state = -1;
    }
    state++;
  }

  // task 2 - check for pressed buttons
  for (int i = 0; i < NUMBUTTONS; i++) {
    // Update the Bounce instance :
    buttons[i].update();
    if ( buttons[i].fell() ) { // a button was pressed
      difficulty++; // 1 = easy, 2 = medium, 3 = hard
      if (difficulty>3) difficulty = 1;
      // show difficulty:
      if (difficulty==1) {
        digitalWrite(LED_EASY_PIN, HIGH);
        digitalWrite(LED_MEDIUM_PIN, LOW);
        digitalWrite(LED_HARD_PIN, LOW);
      }
      else if (difficulty==2) {
        digitalWrite(LED_EASY_PIN, LOW);
        digitalWrite(LED_MEDIUM_PIN, HIGH);
        digitalWrite(LED_HARD_PIN, LOW);
      }
      else if (difficulty==3) {
        digitalWrite(LED_EASY_PIN, LOW);
        digitalWrite(LED_MEDIUM_PIN, LOW);
        digitalWrite(LED_HARD_PIN, HIGH);
      }

      Serial.print("difficulty "); Serial.println(difficulty);
    } // end if - fell
  } // end for
}


// Function to turn on the green light
void green_light() {
  digitalWrite(GREEN, HIGH);
  digitalWrite(RED, LOW);
  digitalWrite(YELLOW, LOW);
}

// Function to turn on the red light
void red_light() {
  digitalWrite(GREEN, LOW);
  digitalWrite(RED, HIGH);
  digitalWrite(YELLOW, LOW);
}

// Function to turn on the yellow light
void yellow_light() {
  digitalWrite(GREEN, LOW);
  digitalWrite(RED, LOW);
  digitalWrite(YELLOW, HIGH);
}

void buzzer_sound() {
  tone(BUZZER, 1000); // Generate a 1000 Hz tone
  Serial.println("Buzz");
}

void buzzer_sound_off() {
  noTone(BUZZER);
  Serial.println("Buzzer off");
}
$abcdeabcde151015202530354045505560fghijfghij