#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define Plus 2
#define Minus 3
#define Save 4
#define ON_BUTTON 5
#define OFF_BUTTON 6
#define Mode 7
#define PUMP_PIN 8

#define EEPROM_ADDRESS 0 // Address to store X value in EEPROM

const int Auto_time = 60000; // X minutes in auto mode (60,000 milliseconds)

int X = 50; // Default value for X (you can change this based on your needs)

bool autoMode = true; // Initial mode set to Auto

unsigned long previousMillis = 0; // Used for Auto mode timer
bool motorOn = false; // Keeps track of the motor state

void setup() {
  pinMode(Plus, INPUT_PULLUP);
  pinMode(Minus, INPUT_PULLUP);
  pinMode(Save, INPUT_PULLUP);
  pinMode(ON_BUTTON, INPUT_PULLUP);
  pinMode(OFF_BUTTON, INPUT_PULLUP);
  pinMode(Mode, INPUT_PULLUP);
  pinMode(PUMP_PIN, OUTPUT);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // Initialize with the I2C address 0x3C
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("X Value:");
  display.display();

  // Read X value from EEPROM at startup
  X = EEPROM.read(EEPROM_ADDRESS);
  displayXValue();
}

void loop() {
  
  checkTimerButtons();
  checkSaveButton();
  checkModeButton();

  // Check motor buttons and control the pump
  if (autoMode) {
    autoMotorControl();
  } else {
    manualMotorControl();
  }
}

void checkTimerButtons() {
  // Check Timer Plus Button
  if (digitalRead(Plus) == LOW) {
    X = constrain(X + 1, 0, 99); // Increment X by 1, restrict the range to 0-99
    displayXValue();
    delay(200); // Button debouncing delay
  }

  // Check Timer Minus Button
  if (digitalRead(Minus) == LOW) {
    X = constrain(X - 1, 0, 99); // Decrement X by 1, restrict the range to 0-99
    displayXValue();
    delay(200); // Button debouncing delay
  }
}

void checkSaveButton() {
  // Check Save Value Button
  if (digitalRead(Save) == LOW) {
    EEPROM.write(EEPROM_ADDRESS, X); // Save X value to EEPROM
    displayXValue();
    delay(200); // Button debouncing delay
  }
}

void checkModeButton() {
  // Check Auto/Manual Mode Button
  if (digitalRead(Mode) == LOW) {
    autoMode = !autoMode; // Toggle the mode
    displayXValue();
    delay(200); // Button debouncing delay
  }
}

void displayXValue() {
  display.setCursor(60, 0);
  display.print("  "); // Clear the previous value
  display.setCursor(60, 0);
  if (X < 10) {
    display.print("0");
  }
  display.print(X); // Display the current X value
  display.display();
}

void autoMotorControl() {
  if (motorOn) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= X) {
      // Time is up, turn off the motor
      digitalWrite(PUMP_PIN, LOW);
      motorOn = false;
      displayMotorStatus();
    }
  } else {
    // Check Motor ON Button in Auto Mode
    if (digitalRead(ON_BUTTON) == LOW) {
      digitalWrite(PUMP_PIN, HIGH);
      motorOn = true;
      previousMillis = millis(); // Reset the timer
      displayMotorStatus();
      delay(200); // Button debouncing delay
    }
  }

  // Check Motor OFF Button in Auto Mode
  if (digitalRead(OFF_BUTTON) == LOW) {
    digitalWrite(PUMP_PIN, LOW);
    motorOn = false;
    displayMotorStatus();
    delay(200); // Button debouncing delay
  }
}

void manualMotorControl() {
  // Check Motor ON Button in Manual Mode
  if (digitalRead(ON_BUTTON) == LOW) {
    digitalWrite(PUMP_PIN, HIGH);
    motorOn = true;
    displayMotorStatus();
    delay(200); // Button debouncing delay
  }

  // Check Motor OFF Button in Manual Mode
  if (digitalRead(OFF_BUTTON) == LOW) {
    digitalWrite(PUMP_PIN, LOW);
    motorOn = false;
    displayMotorStatus();
    delay(200); // Button debouncing delay
  }
}

void displayMotorStatus() {
  display.setCursor(0, 20);
  display.print("Motor:");
  display.setCursor(60, 20);
  display.print(motorOn ? "ON " : "OFF");
  display.display();
}