// Include Required Libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Define OLED Configuration here
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

byte motorSpeed = 128;  // Set motor speed (for 3v motor it's important not to exceed 128, maximum range is 255)

// Pin definitions
const int buttonPin = 2;       // Push button input
const int motorPin1 = 8;       // L298N IN1
const int motorPin2 = 9;       // L298N IN2
const int ledRelayPin = 7;     // Relay for LED strip
const int fogRelayPin = 6;     // Relay for Fog machine
const int motorEnablePin = 5;  // PWM pin for motor speed

const byte relayLogic = LOW;  // Set the relay working logic here (Set as HIGH/LOW)

// Timer variables
unsigned long startTime;           // Variable to hold start time
unsigned long waitTime = 300000;   // 5 minutes in milliseconds
unsigned long totalTime = 20000; // allowed working time in milliseconds
unsigned long lastUpdateTime = 0;  // variable to hold last time update value
bool ovenActive = false;           // Flag to check current status of oven
bool waiting = false;              // flag to check if waiting time started

void setup() {
  // Initialize pins
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(ledRelayPin, OUTPUT);
  pinMode(fogRelayPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(motorEnablePin, OUTPUT);

  // Turn everything off initially
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(ledRelayPin, LOW);
  digitalWrite(fogRelayPin, LOW);
  analogWrite(motorEnablePin, 0);

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  displayMsg(42, 10, "IPECO", HIGH);
  displayMsg(20, 30, "Time: 20 sec", LOW);
}

void loop() {
  // Check if the button is pressed to start the oven process and we are not in waiting time
  if (digitalRead(buttonPin) == LOW && !ovenActive && !waiting) {
    ovenActive = true;
    startTime = millis();

    // Turn on LED strip
    digitalWrite(ledRelayPin, HIGH);

    // Start motor at 400 RPM (adjust PWM value based on your motor)
    analogWrite(motorEnablePin, motorSpeed);  // Adjust based on motor specs
    digitalWrite(motorPin1, HIGH);
    digitalWrite(motorPin2, LOW);

    // Turn on the fog machine
    digitalWrite(fogRelayPin, HIGH);

    // Display message and start timer
    // displayMsg(byte x, byte y, byte fontSize, String msg, bool clear)
    displayMsg(42, 10, "IPECO", HIGH);
    displayMsg(20, 30, "Time: 20 sec", LOW);
  }

  // If the oven process is active, check the timer
  if (ovenActive) {
    if (millis() - startTime >= totalTime) {
      // Turn everything off after 20 seconds
      digitalWrite(ledRelayPin, LOW);
      digitalWrite(fogRelayPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      analogWrite(motorEnablePin, 0);

      ovenActive = false;
      waiting = true;
      startTime = millis();  // Reset timer for the waiting period
      lastUpdateTime = (millis() - startTime) / 1000;

      // Update display for wait time
      displayMsg(42, 10, "IPECO", HIGH);
      displayMsg(24, 30, "5 Min Wait", LOW);
    } else if (((millis() - startTime) / 1000) != lastUpdateTime) {
      lastUpdateTime = totalTime / 1000 - (millis() - startTime) / 1000;
      // displayMsg(6, 30, "Time: 20 sec", LOW);
      display.setCursor(52, 30);
      display.print(lastUpdateTime);  // display msg on lcd
      display.print(" sec  ");
      display.display();
    }
  }

  // Handle the waiting period
  if (waiting) {
    if (millis() - startTime >= waitTime) {
      waiting = false;
      // Clear the display and wait for button press again
      displayMsg(42, 10, "IPECO", HIGH);
  displayMsg(20, 30, "Time: 20 sec", LOW);
    }
  }
}
void displayMsg(byte x, byte y, String msg, bool clear) {
  if (clear) {  // if clear flag is high clear lcd
    display.clearDisplay();
    display.display();  //Finally display the created image
  }
  display.setCursor(x, y);
  display.print(msg);  // display msg on lcd
  display.display();
}