// Define button pin and debounce time as constants
#define BUTTON_PIN 12     // Pin number for the button
#define DEBOUNCE_TIME 10  // Time in milliseconds for button debounce

// Setup function
void setup() {
  // Begin serial communication at 115200 baud rate
  Serial.begin(115200);

  // Set button pin as input with internal pull-up resistor
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  // Set built-in LED pin as output
  pinMode(LED_BUILTIN, OUTPUT);
}

// Loop function
void loop() {
  // Read the state of the button
  bool isButtonPressed = !digitalRead(BUTTON_PIN);

  // Get the debounced state of the button
  bool isButtonStable = updateButtonState(isButtonPressed);

  // If the debounced state is true, print "Button Pressed" to the serial monitor
  if (isButtonStable) {
    Serial.println("Button Pressed");
  }

  // Set the built-in LED based on the debounced state
  digitalWrite(LED_BUILTIN, isButtonStable);
}

// Function to perform button state debouncing and update stable state
bool updateButtonState(const bool inputState) {
  // Static variables to retain their values between function calls
  static bool previousButtonState = false;
  static bool currentStableState = false;
  static unsigned long startTime = 0;

  // Check for button rising edge and start timing
  if (inputState && !previousButtonState) {
    startTime = millis();  // Record the start time when the button is pressed
  }

  // Store the current state as previous state for the next iteration
  previousButtonState = inputState;

  // Check if input state matches the current stable state
  if (inputState == currentStableState) {
    return false;  // If input state matches the current stable state, return false
  }

  // Calculate elapsed time since the rising edge
  unsigned long elapsedTime = millis() - startTime;  // Calculate the elapsed time

  // Check if elapsed time is less than the debounce delay
  if (elapsedTime < DEBOUNCE_TIME) {
    return false;  // If elapsed time is less than the debounce delay, return false
  }

  // Update the current stable state and return it
  currentStableState = inputState;  // Update the current stable state
  return currentStableState;  // Return the current stable state
}