#include "HomeSpan.h"
#include "esp_timer.h"  // Include esp_timer for scheduling tasks on ESP32

// Define GPIO pins for controlling the alarm
#define GPIO_ALARM_ON  7   // GPIO number to trigger the alarm ON
#define GPIO_ALARM_OFF 6   // GPIO number to trigger the alarm OFF

// Timer handles
esp_timer_handle_t timerOn;
esp_timer_handle_t timerOff;

// Function to turn GPIO_ALARM_ON low
void resetOnPin(void *arg) {
  digitalWrite(GPIO_ALARM_ON, LOW);
}

// Function to turn GPIO_ALARM_OFF low
void resetOffPin(void *arg) {
  digitalWrite(GPIO_ALARM_OFF, LOW);
}

// Custom accessory for burglar alarm interface
struct AlarmSwitch : Service::Switch {

  // Characteristic for switch state
  SpanCharacteristic *power;

  // Constructor: Setup the GPIO and initialize HomeSpan service
  AlarmSwitch() : Service::Switch() {
    power = new Characteristic::On();  // Define the On characteristic for the switch

    // Set GPIO mode to output for alarm control
    pinMode(GPIO_ALARM_ON, OUTPUT);
    pinMode(GPIO_ALARM_OFF, OUTPUT);

    // Ensure both pins are LOW initially
    digitalWrite(GPIO_ALARM_ON, LOW);
    digitalWrite(GPIO_ALARM_OFF, LOW);

    // Configure the timers for one-shot use
    esp_timer_create_args_t timerOnArgs = {
      .callback = &resetOnPin,
      .arg = NULL,
      .dispatch_method = ESP_TIMER_TASK,
      .name = "resetOnPin"
    };
    esp_timer_create(&timerOnArgs, &timerOn);

    esp_timer_create_args_t timerOffArgs = {
      .callback = &resetOffPin,
      .arg = NULL,
      .dispatch_method = ESP_TIMER_TASK,
      .name = "resetOffPin"
    };
    esp_timer_create(&timerOffArgs, &timerOff);
  }

  // Override set() method to control the GPIO pins
  bool update() override {
    if (power->getNewVal()) {   // If switch turned ON
      // Trigger alarm ON by setting GPIO_ALARM_ON high for 1 second
      digitalWrite(GPIO_ALARM_ON, HIGH);

      // Start a one-shot timer to reset GPIO_ALARM_ON after 1 second
      esp_timer_start_once(timerOn, 1000000);  // 1 second in microseconds

    } else {  // If switch turned OFF
      // Trigger alarm OFF by setting GPIO_ALARM_OFF high for 1 second
      digitalWrite(GPIO_ALARM_OFF, HIGH);

      // Start a one-shot timer to reset GPIO_ALARM_OFF after 1 second
      esp_timer_start_once(timerOff, 1000000);  // 1 second in microseconds
    }

    return true;  // Return true to indicate successful update
  }
};

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

  // Initialize HomeSpan with a category label (Switch category for alarm control)
  homeSpan.begin(Category::Switches, "Burglar Alarm Control");

  // Add accessory (this is the burglar alarm switch)
  new SpanAccessory();

    // Add required Accessory Information service
    new Service::AccessoryInformation();
      new Characteristic::Identify();
      new Characteristic::Name("Security System");
    new AlarmSwitch();   

}

void loop() {
  // Run the HomeSpan loop
  homeSpan.poll();
}

