#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <NewPing.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int TRIGGER_PIN = 12;
const int ECHO_PIN = 13;
const int BUZZER_PIN = 26;
const int LED_PIN = 27;
const int BLUE_LED_PIN = 32;
const int YELLOW_LED_PIN = 33;
const int RED_LED_PIN = 25;
const int MAX_DISTANCE = 20;
const int TANK_CAPACITY = 20;
const int LOW_THRESHOLD = 9;
const int MED_THRESHOLD = 16;

NewPing sonar(TRIGGER_PIN, ECHO_PIN);

void setup() {
  Wire.begin();
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("H20 LEVEL:");

  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);
  pinMode(YELLOW_LED_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
}

void updateLCDRow(int row, String text) {
  lcd.setCursor(0, row);
  lcd.print("                ");
  lcd.setCursor(0, row);
  lcd.print(text);
}

void controlLEDs(int blue, int yellow, int red) {
  digitalWrite(BLUE_LED_PIN, blue);
  digitalWrite(YELLOW_LED_PIN, yellow);
  digitalWrite(RED_LED_PIN, red);
}

void updateLCD(String text) {
  updateLCDRow(1, text);
}

void loop() {
  unsigned int distance = sonar.ping_cm();
  int invertedDistance = TANK_CAPACITY - distance;
  int percentage = map(invertedDistance, 0, TANK_CAPACITY, 0, 100);

  if (percentage > 100) {
    percentage = 100;
  }
  if (percentage < 0) {
    percentage = 0;
  }

  String status = "";
  
  if (invertedDistance <= LOW_THRESHOLD) {
    status = "LOW";
  } else if (invertedDistance <= MED_THRESHOLD) {
    status = "MED";
  } else {
    status = "HIGH";
  }

  String displayText = status + ", " + String(invertedDistance) + "cm = " + String(percentage) + "%";
  updateLCD(displayText);

  if (percentage < 50) {
    controlLEDs(HIGH, LOW, LOW);
  } else if (percentage < 85) {
    controlLEDs(LOW, HIGH, LOW);
  } else {
    controlLEDs(LOW, LOW, HIGH);
  }

  if (percentage == 95) {
    digitalWrite(BUZZER_PIN, HIGH);
    digitalWrite(LED_PIN, HIGH);
  } else {
    digitalWrite(BUZZER_PIN, LOW);
    digitalWrite(LED_PIN, LOW);
  }

  delay(1000);
}