#include "HX711.h"
#include <LiquidCrystal_I2C.h>

HX711 scale;
#define CALIBRATION_FACTOR 928 / 2.21 // (reading)/(known weight)
#define MAX_WEIGHT 4.5
#define BUZZER_PIN 2
LiquidCrystal_I2C lcd(0x27, 16, 2);
double last_tmp = 0.0;
bool buzzerActivated = false;     // Flag to track buzzer activation
bool lcdBlinking = false;         // Flag to track LCD blinking
unsigned long lastWeightTime = 0; // Time tracking for weight change
unsigned long buzzerStartTime = 0; // Time tracking for buzzer timing
bool buzzerDoubleBeep = false;    // Flag for the double beep when weight is over MAX_WEIGHT
unsigned long lastBlinkTime = 0;  // Time for controlling LCD blinking

void setup() {
  Serial.begin(115200);
  Serial.println("Hello, ESP32-C3!");
  Serial.println("Set up LCD");

  Wire.begin(9, 8); 
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 1);

  Serial.println("Initializing the scale");
  scale.begin(A1, A0);
  scale.set_scale(CALIBRATION_FACTOR);   

  pinMode(BUZZER_PIN, OUTPUT);
}

void loop() {
  Serial.print("read: \t\t");
  Serial.println(scale.read());

  String weight = String(scale.get_units(), 3);
  double weight_value = weight.toDouble();

  unsigned long currentTime = millis();

  // Check if weight changed by more than 0.005 kg
  if (abs(weight_value - last_tmp) >= 0.005) {
    last_tmp = weight_value;
    lcd.clear();
    lastWeightTime = currentTime;  // Reset timer on weight change
    buzzerActivated = false;       // Reset buzzer activation state on weight change
    buzzerDoubleBeep = false;      // Reset double beep flag on weight change
  }

  lcd.setCursor(0, 0);
  lcd.print("Weight: " + weight +" "+ "kg");

  // If weight hasn't changed for more than 1 second
  if (currentTime - lastWeightTime >= 1000) {
    if (weight_value < MAX_WEIGHT) {
      lcd.setCursor(0, 1);
      lcd.print("OK");

      // Single beep for 2 seconds if weight is stable and below 4.5 kg
      if (!buzzerActivated) {
        tone(BUZZER_PIN, 1000, 1000);  // Single beep for 1 seconds
        buzzerActivated = true;
      }
      
      // Ensure LCD is not blinking when weight is OK
      lcdBlinking = false; 
      lcd.backlight(); // Keep the backlight on when OK
    } 
    else {
      lcd.setCursor(0, 1);
      lcd.print("Over weight");

      // Double beep logic: 2 beeps with 3-second gap if weight is over 4.5 kg
      if (!buzzerDoubleBeep) {
        if (currentTime - buzzerStartTime >= 1000) {  // Wait 1 seconds between beeps
          tone(BUZZER_PIN, 1000, 500);                // Beep for 500ms
          buzzerStartTime = currentTime;              // Record time of the first beep
          buzzerDoubleBeep = !buzzerDoubleBeep;       // Toggle the flag to indicate one beep is done
        }
      }   
      else {
        if (currentTime - buzzerStartTime >= 3500) {  // 3 seconds after the first beep
          tone(BUZZER_PIN, 1000, 500);                // Second beep for 500ms
          buzzerDoubleBeep = false;                   // Reset flag for next round of beeps
        }
      }

      // Control LCD blinking for over weight condition
      if (currentTime - lastBlinkTime >= 500) {  // Blink every 500 ms
        if (lcdBlinking) {
          lcd.backlight();   // Turn on the backlight
        } else {
          lcd.noBacklight(); // Turn off the backlight
        }
        lcdBlinking = !lcdBlinking;  // Toggle blinking state
        lastBlinkTime = currentTime;  // Update last blink time
      }
    }
  } 
}