// https://wokwi.com/projects/411231566418972673
// https://forum.arduino.cc/t/i-need-help-with-a-project/1308905

# include <Wire.h>
# include <LiquidCrystal_I2C.h>

// Initialize LCD with I2C address (0x27) and size (20 columns, 4 rows)
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Define pin numbers for LEDs
const int redPin = 2;
const int greenPin = 3;
const int yellowPin = 4;
const int orangePin = 5;
const int bluePin = 6;
const int whitePin = 7;

// Define pin for push button
const int buttonPin = 8;

// Define pin for DC motor
const int motorPin = 9;

// Define pin for potentiometer
const int potPin = A0;

// Variable for button state
int buttonState = 0;

unsigned long previousMillis = 0;  // Store the last time
const long interval = 2000;         // Interval for prompt display
bool awaitingInput = false;

void setup() {
  // Set LED pins as outputs
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(yellowPin, OUTPUT);
  pinMode(orangePin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(whitePin, OUTPUT);

  // Set button pin as input
  pinMode(buttonPin, INPUT_PULLUP);

  // Set motor pin as output
  pinMode(motorPin, OUTPUT);

  // Initialize Serial monitor
  Serial.begin(9600);

  // Initialize LCD
  lcd.begin(20, 4);
  lcd.backlight();

  // Display initial message
  lcd.setCursor(0, 0);
  lcd.print("HAPPY MIDTERM");
  delay(2000);
  lcd.clear();
}

void loop() {
  // Check for button press
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) {
    // Activate the command when button is pressed
    turnOnLights();
  } else {
    // Prompt for command via Serial Monitor if not awaiting input
    if (!awaitingInput) {
      Serial.println("Enter command: TURN ON LIGHT");
      previousMillis = millis();  // Reset the timer
      awaitingInput = true;
    }

    // Check for timeout
    if (awaitingInput && (millis() - previousMillis >= interval)) {
      awaitingInput = false; // Reset input awaiting state
    }

    if (Serial.available() > 0) {
      String command = Serial.readStringUntil('\n');
      command.trim();
      if (command.equalsIgnoreCase("TURN ON LIGHT")) {
        turnOnLights();
      } else {
        Serial.println("Invalid command. Please try again.");
      }
    }
  }
}

// Function to handle turning on lights
void turnOnLights() {
  int number = 0;
  lcd.clear();
  lcd.print("Enter a number:");
  Serial.println("Enter a number:");

  // Wait for user input
  while (Serial.available() == 0) {
    // Non-blocking: check for user input
  }

  // Read the number
  number = Serial.parseInt();

  // Display the number on LCD
  lcd.clear();
  lcd.print("NUMBER: ");
  lcd.print(number);

  // Determine if the number is odd or even
  if (number % 2 == 1) {
    // Odd number - turn on first group of lights
    while (!blinkLights(redPin, yellowPin, bluePin));
  } else {
    // Even number - turn on second group of lights
    while (!blinkLights(greenPin, orangePin, whitePin));
  }
}

// Function to blink specified group of lights
bool blinkLights(int pin1, int pin2, int pin3) {
  static unsigned long lastBlinkTime = 0;
  static int blinkCount = 0;
  const int maxBlinks = 10;  // half blinks

  if (blinkCount < maxBlinks) {
    if (millis() - lastBlinkTime >= 1000) { // Blink every 1 second
      if (digitalRead(pin1) == HIGH) {
        digitalWrite(pin1, LOW);
        digitalWrite(pin2, LOW);
        digitalWrite(pin3, LOW);
        analogWrite(motorPin, 0);  // Stop motor
      } else {
        digitalWrite(pin1, HIGH);
        digitalWrite(pin2, HIGH);
        digitalWrite(pin3, HIGH);
        analogWrite(motorPin, map(analogRead(potPin), 0, 1023, 0, 255));  // Motor control
      }
      blinkCount++;   // actually half a blink
      lastBlinkTime = millis();  // Update last blink time
    }
    return false;
  } else {
    // Reset blink count after done blinking
    blinkCount = 0;
    return true;    // we done
  }
}