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

#define SCREEN_WIDTH 128 // OLED width,  in pixels
#define SCREEN_HEIGHT 64 // OLED height, in pixels

// create an OLED display object connected to I2C
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);




// 'fan_bitmap', 16x16px
const unsigned char fan_bitmap_16px [] PROGMEM = {
	0x00, 0x00, 0x06, 0x18, 0x05, 0x00, 0x04, 0x80, 0x04, 0x9f, 0x07, 0x80, 0x3e, 0xfc, 0x4c, 0x44, 
	0x8c, 0x48, 0xfe, 0xf0, 0x07, 0x80, 0x04, 0x9f, 0x04, 0x80, 0x02, 0x80, 0x01, 0x98, 0x00, 0x00
};

// 'thermometer_bitmap', 16x16px
const unsigned char thermometer_bitmap_16px [] PROGMEM = {
	0x01, 0x80, 0x02, 0x40, 0x02, 0x5c, 0x02, 0x40, 0x02, 0x48, 0x02, 0x40, 0x02, 0x40, 0x02, 0x5c, 
	0x06, 0x60, 0x0d, 0xb0, 0x0b, 0xd0, 0x0b, 0xd0, 0x0b, 0xd0, 0x09, 0x90, 0x06, 0x60, 0x03, 0xc0
};

// 'humidity_bitmap', 16x16px
const unsigned char humidity_bitmap_16px [] PROGMEM = {
	0x02, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x09, 0x80, 0x10, 0x80, 0x30, 0x00, 0x60, 0x00, 0x40, 0xee, 
	0xc1, 0xbb, 0x80, 0x00, 0x8e, 0xee, 0xdb, 0xbb, 0x40, 0x00, 0x60, 0x40, 0x39, 0xc0, 0x0f, 0x80
};




void display_border(){
	oled.drawRect(0, 0, 128, 64, WHITE);
	// oled.drawRoundRect(0, 0, 128, 64, 4, WHITE);
}


void display_fan(int x, int y,int fan_number, String fan_state){
  oled.setTextColor(WHITE);    // set text color
	oled.setTextSize(1);

	oled.drawBitmap(x, y, fan_bitmap_16px, 16, 16, 1);
	
	oled.setCursor(x, y+20);     // set position to display (x,y)
	oled.print("Fan");
	oled.println(fan_number); 
	
	oled.fillRoundRect(x+28, y+8, 22, 10, 2, WHITE);

	oled.setTextColor(BLACK, WHITE);  // 'inverted' text
	oled.setCursor(x+30, y+10);       // set position to display (x,y)
	oled.println(fan_state);          // set text
}


void display_temperature_sensor(int x, int y,int sensor_number, float temperature){
  oled.setTextColor(WHITE);    // set text color
	oled.setTextSize(1);

	oled.drawBitmap(x, y, thermometer_bitmap_16px, 16, 16, 1);

	oled.setCursor(x, y+20);      // set position to display (x,y)
	oled.print("Temp");
	oled.println(sensor_number);  // set text

	oled.fillRoundRect(x+28, y+8, 27, 10, 2, WHITE);

	oled.setTextColor(BLACK, WHITE);  // 'inverted' text
	oled.setCursor(x+30, y+10);       // set position to display (x,y)
  oled.println(temperature, 1);     // set text
}


void display_humidity_sensor(int x, int y,int sensor_number, int humidity){
  oled.setTextColor(WHITE);    // set text color
	oled.setTextSize(1);

	oled.drawBitmap(x, y, humidity_bitmap_16px, 16, 16, 1); //good1

	oled.setCursor(x, y+20);      // set position to display (x,y)
	oled.print("Hum");
	oled.println(sensor_number);  // set text

	oled.fillRoundRect(x+28, y+8, 22, 10, 2, WHITE);

	oled.setTextColor(BLACK, WHITE); // 'inverted' text

	oled.setCursor(x+30, y+10);   // set position to display (x,y)
  oled.print(humidity);         // set text
	oled.println("%");            // set text
}


void display_ammonia_sensor(int x, int y,int sensor_number, int ammonia){
  oled.setTextColor(WHITE);    // set text color
	oled.setTextSize(1);

	oled.drawBitmap(x, y, humidity_bitmap_16px, 16, 16, 1); //good1

	oled.setCursor(x, y+20);      // set position to display (x,y)
	oled.print("NH3");
	oled.println(sensor_number);  // set text

	oled.fillRoundRect(x+28, y+8, 22, 10, 2, WHITE);

	oled.setTextColor(BLACK, WHITE); // 'inverted' text

	oled.setCursor(x+25, y+10);   // set position to display (x,y)
  oled.print(ammonia);         // set text
	oled.println("ppm");            // set text
  // Parts per million (ppm)
}

void display_sensor_setpoint(String sensor, float sensor_value, float sensor_setpoint, char unit, int num_fractional_digits){
  oled.setTextColor(WHITE);    // set text color
	oled.setTextSize(2);
	
	//sp and pv
  oled.setCursor(40, 10);
  oled.println(sensor);
  oled.setTextSize(1);
  oled.setCursor(35, 35);
  oled.print("PV : ");
  oled.print(sensor_value, num_fractional_digits);
	oled.println(unit);
  oled.setCursor(35, 45);
  oled.print("SP : ");
  oled.print(sensor_setpoint, num_fractional_digits);
	oled.println(unit);
}





unsigned long previousMillis = 0;
const long interval = 2000; // interval in milliseconds for updating display




void updateDisplay() {
  static int state = 0; // Keeps track of which display state we are in
  oled.clearDisplay(); // clear display
  display_border();


  switch (state) {
    case 0:
		  oled.drawLine(0, 32, oled.width() - 1, 32, WHITE);
			oled.drawLine(64, 0, 64, oled.height() - 1, WHITE);
      display_fan(5, 2, 1, "ON");
      display_fan(5, 35, 2, "OFF");
      display_fan(70, 2, 3, "OFF");
      display_fan(70, 35, 4, "ON");
      break;
    case 1:
			oled.drawLine(0, 32, oled.width() - 1, 32, WHITE);
  		oled.drawLine(64, 0, 64, oled.height() - 1, WHITE);
      display_temperature_sensor(5, 2, 1, 37.3);
      display_temperature_sensor(5, 35, 2, 25.5);
      display_temperature_sensor(70, 2, 3, 33.2);
      display_temperature_sensor(70, 35, 4, 30.0);
      break;
    case 2:
			oled.drawLine(0, 32, oled.width() - 1, 32, WHITE);
  		oled.drawLine(64, 0, 64, oled.height() - 1, WHITE);
      display_humidity_sensor(5, 2, 1, 10);
      display_humidity_sensor(5, 35, 2, 20);
      display_humidity_sensor(70, 2, 3, 30);
      display_humidity_sensor(70, 35, 4, 40);
      break;
    case 3:
      display_sensor_setpoint("Temp", 32.32, 34.34, 'C', 1);
      break;
    case 4:
      display_sensor_setpoint("Hum", 10, 50, '%', 0);
      break;
  }

  oled.display();

  // Increment state and loop back to 0 if greater than 4
  state = (state + 1) % 5;
}

void setup() {
  Serial.begin(9600);

  // initialize OLED display with I2C address 0x3C
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("failed to start SSD1306 OLED"));
    while (1);
  }
  
	oled.setTextSize(1);         // set text size
  oled.setTextColor(WHITE);    // set text color
  display_ammonia_sensor(5, 2, 1, 10);
}


void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    updateDisplay();
  }
}

esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA