#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define OLED_RESET -1
Adafruit_SSD1306 oled(128, 64, &Wire, OLED_RESET);

Encoder rotaryEncoder(2, 3);
int relayPin = 7;
int buttonPin = 4;

OneWire oneWire(5);
DallasTemperature sensors(&oneWire);

int desiredTemperature = 100;
int desiredTime = 5;  // Time in minutes
int currentTemperature = 0;
bool isHeating = false;
unsigned long startTime = 0;

unsigned long buttonPressStart = 0;  // For detecting long press
bool buttonHeld = false;  // To track if the button is being held
bool buttonWasPressed = false;  // To handle quick presses

enum Mode {TEMPERATURE, TIME};  // Define modes for setting temperature and time
Mode currentMode = TEMPERATURE;  // Start in temperature mode

void setup() {
  pinMode(relayPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  digitalWrite(relayPin, LOW);  // Relay off by default
  
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.clearDisplay();
  oled.setTextColor(WHITE);
  oled.setTextSize(1);
  sensors.begin();
}

void loop() {
  long currentEncoderPosition = rotaryEncoder.read();  // Get the current encoder position

  if (currentMode == TEMPERATURE) {
    int change = currentEncoderPosition / 4;  // Adjust desired temperature
    desiredTemperature += change;
    
    if (desiredTemperature < 20) {
      desiredTemperature = 20;  // Minimum temperature
    } else if (desiredTemperature > 300) {
      desiredTemperature = 300;  // Maximum temperature
    }
  } else if (currentMode == TIME) {
    int change = currentEncoderPosition / 4;  // Adjust desired heating time
    desiredTime += change;
    
    if (desiredTime < 1) {
      desiredTime = 1;  // Minimum time
    } else if (desiredTime > 60) {
      desiredTime = 60;  // Maximum time
    }
  }

  rotaryEncoder.write(0);  // Reset encoder
  
  sensors.requestTemperatures();  // Update temperature readings
  currentTemperature = sensors.getTempCByIndex(0);  // Get the temperature
  
  if (digitalRead(buttonPin) == LOW) {
    if (!buttonHeld) {  // If the button is pressed
      buttonPressStart = millis();  // Record when the press started
      buttonHeld = true;  // Indicate the button is being held
    }
    
    if ((millis() - buttonPressStart) > 1500) {  // If the button is held for more than 1 second
      isHeating = !isHeating;  // Toggle heating state
      buttonHeld = false;  // Reset the hold flag
    }
  } else {
    if (buttonHeld && (millis() - buttonPressStart) < 1000) {  // Short press to switch modes
      currentMode = (currentMode == TEMPERATURE) ? TIME : TEMPERATURE;  // Toggle mode
    }
    buttonHeld = false;  // Reset the hold flag if the button is released
  }

  if (isHeating) {
    if (currentTemperature < desiredTemperature) {
      digitalWrite(relayPin, HIGH);  // Turn on heating
    } else {
      digitalWrite(relayPin, LOW);  // Turn off heating
    }

    if ((millis() - startTime) > (desiredTime * 60 * 1000)) {  // Check if time exceeded
      isHeating = false;  // Stop heating
      digitalWrite(relayPin, LOW);  // Turn off relay
    }
  } else {
    digitalWrite(relayPin, LOW);  // Relay off when not heating
  }

  // Display the status on the OLED
  oled.clearDisplay();  // Clear the previous text
  oled.setTextSize(1.9);  // Ensure the text size is small enough to fit

  // Display the current temperature
  oled.setCursor(0, 0);
  oled.print("Current Temp: ");  // Aligned properly
  oled.print(currentTemperature);

  // Display the desired temperature
  oled.setCursor(0, 17);
  oled.print("Set Temp:     ");
  oled.print(desiredTemperature);

  // Display the set time in minutes
  oled.setCursor(0, 30);
  oled.print("Set Time:     ");
  oled.print(desiredTime);
  oled.print(" min");

  // Display the current mode
  oled.setCursor(0, 43);
  oled.print("Mode:         ");
  oled.print(currentMode == TEMPERATURE ? "Temp" : "Time");

  // Display the heating status
  oled.setCursor(0, 56);
  oled.print("Heating:      ");
  oled.print(isHeating ? "Yes" : "No");

  oled.display();  // Refresh the display to show the changes
}
NOCOMNCVCCGNDINLED1PWRRelay Module