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

const int SCK_PIN = 2;
const int DT_PIN = 3;
const int clearWeightButtonGPIO = 9;
const int storeWeightButtonGPIO = 10;
const float unitDivisor = 420;

LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows

HX711 scale;

float storedWeight = 0;

void setupStoreWeightButton() {
  pinMode(storeWeightButtonGPIO, INPUT_PULLUP);
}

void setupClearWeightButton() {
  pinMode(clearWeightButtonGPIO, INPUT_PULLUP);
}

void setupButtons() {
  setupStoreWeightButton();
  setupClearWeightButton();
}

void setupLCD() {
  lcd.init();
  lcd.backlight();
  lcd.begin(16, 2);  // Initialize the display
  lcd.print("Weight: ");
}

void setup() {
  setupLCD();
  setupButtons();
  scale.begin(DT_PIN, SCK_PIN);
}

float measureWeight() {
  return scale.get_units() / unitDivisor;
}

void displayWeight(float weight) {
  lcd.setCursor(0, 0);
  lcd.print("Weight: ");
  lcd.print(weight);
  lcd.print("    ");
}

void displayDifference(float difference) {
  lcd.setCursor(8, 1);
  lcd.print(difference);
  lcd.print("    ");
}

void handleWeight() {
  static float lastWeight;
  float currentWeight = measureWeight();

  bool weightDidNotChange = currentWeight == lastWeight;

  if (weightDidNotChange) return;
  lastWeight = currentWeight;

  displayWeight(currentWeight);

  if (storedWeight) {
    float difference = currentWeight - storedWeight;
    displayDifference(difference);
  }
}

void storeWeight(float weight) {
  storedWeight = weight;

  lcd.setCursor(0, 1);
  lcd.print(storedWeight);
  lcd.print("    ");

  displayDifference(0);
}

void clearStoredWeight() {
  storedWeight = 0;
  lcd.setCursor(0, 1);
  lcd.print("                    ");
}

void handleStoreWeightButton() {
  static bool lastState;

  bool currentState = digitalRead(storeWeightButtonGPIO);
  bool stateDidNotChange = currentState == lastState;
  if (stateDidNotChange) return;

  lastState = currentState;

  bool isPressed = currentState == LOW;
  if (isPressed) storeWeight(measureWeight());
}

void handleClearWeightButton() {
  static bool lastState;
  
  bool currentState = digitalRead(clearWeightButtonGPIO);
  bool stateDidNotChange = currentState == lastState;
  if (stateDidNotChange) return;

  lastState = currentState;

  bool isPressed = currentState == LOW;
  if (isPressed) clearStoredWeight();
}

void handleButtons() {
  handleStoreWeightButton();
  handleClearWeightButton();
}

void loop() {
  handleWeight();
  handleButtons();
}