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

// Define OLED display parameters
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Define DS18B20 data pin
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Define digital output pins
const int outputPin1 = 3;
const int outputPin2 = 4;

// Define digital input pins for overrides
const int inputPin1 = 5;
const int inputPin2 = 6;

// Variables to track digital input states
bool input1State = false;
bool input2State = false;

void setup() {
  // Initialize the OLED display
  if(!display.begin(0x3C, OLED_RESET, SDA, SCL)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }

  // Initialize DS18B20 sensor
  sensors.begin();

  // Set digital output pins as OUTPUT
  pinMode(outputPin1, OUTPUT);
  pinMode(outputPin2, OUTPUT);

  // Set digital input pins as INPUT_PULLUP
  pinMode(inputPin1, INPUT_PULLUP);
  pinMode(inputPin2, INPUT_PULLUP);

  // Initialize Serial communication
  Serial.begin(9600);
}

void loop() {
  // Request temperature from DS18B20 sensor
  sensors.requestTemperatures();
  float temperatureC = sensors.getTempCByIndex(0);

  // Display temperature on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.print(F("Temperature: "));
  display.print(temperatureC);
  display.print(F("C"));

  // Display blank line
  display.setCursor(0, 20);
  display.println();

  // Display digital output status
  display.print(F("Fan 1: "));
  display.setTextColor(digitalRead(outputPin1) == HIGH ? SSD1306_WHITE : SSD1306_WHITE);
  display.println(digitalRead(outputPin1) == HIGH ? "On" : "Off");
  display.setTextColor(SSD1306_WHITE);

  display.print(F("Fan 2: "));
  display.setTextColor(digitalRead(outputPin2) == HIGH ? SSD1306_WHITE : SSD1306_WHITE);
  display.println(digitalRead(outputPin2) == HIGH ? "On" : "Off");
  display.setTextColor(SSD1306_WHITE);

  display.display();

  // Check temperature thresholds and control digital outputs
  if (temperatureC >= 97) {
    digitalWrite(outputPin1, HIGH);
  } else if (temperatureC <= 86) {
    digitalWrite(outputPin1, LOW);
  }

  if (temperatureC >= 106) {
    digitalWrite(outputPin2, HIGH);
  } else if (temperatureC <= 94) {
    digitalWrite(outputPin2, LOW);
  }

  // Check digital input overrides
  bool newInput1State = digitalRead(inputPin1) == HIGH;
  bool newInput2State = digitalRead(inputPin2) == HIGH;

  if (newInput1State && !input1State) {
    // Digital input 1 turned on, turn on Fan 1
    digitalWrite(outputPin1, HIGH);
  } else if (newInput2State && !input2State && !newInput1State) {
    // Digital input 2 turned on (and input 1 is off), turn on Fan 1 and Fan 2
    digitalWrite(outputPin1, HIGH);
    digitalWrite(outputPin2, HIGH);
  }

  // Update input states
  input1State = newInput1State;
  input2State = newInput2State;

  // Print temperature and output status to Serial Monitor
  Serial.print(F("Temperature: "));
  Serial.print(temperatureC);
  Serial.println(F("C"));
  Serial.print(F("Fan 1: "));
  Serial.println(digitalRead(outputPin1) == HIGH ? "On" : "Off");
  Serial.print(F("Fan 2: "));
  Serial.println(digitalRead(outputPin2) == HIGH ? "On" : "Off");

  // Delay for a moment to avoid rapid updates
  delay(1000);
}
