#include "button.h"

#include <stdint.h>

#include "driver/gpio.h"
#include "esp_check.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "portrait_engine.h"

static const char *TAG = "button";

static void button_task(void *arg)
{
    const gpio_num_t pin = (gpio_num_t)(intptr_t)arg;
    int last_level = gpio_get_level(pin);
    int stable_level = last_level;
    int64_t last_change_us = esp_timer_get_time();

    while (true) {
        int level = gpio_get_level(pin);
        int64_t now_us = esp_timer_get_time();
        if (level != last_level) {
            last_level = level;
            last_change_us = now_us;
        }

        if ((now_us - last_change_us) > 50000 && level != stable_level) {
            stable_level = level;
            if (stable_level == 0) {
                ESP_LOGI(TAG, "capture button pressed");
                portrait_engine_request_capture();
            }
        }

        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

esp_err_t button_init(void)
{
    const gpio_num_t pin = (gpio_num_t)CONFIG_SCARA_BUTTON_GPIO;
    gpio_config_t config = {
        .pin_bit_mask = 1ULL << pin,
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    ESP_RETURN_ON_ERROR(gpio_config(&config), TAG, "gpio_config failed");

    BaseType_t ok = xTaskCreate(button_task, "capture_button", 2048, (void *)(intptr_t)pin, 6, NULL);
    if (ok != pdPASS) {
        return ESP_ERR_NO_MEM;
    }

    ESP_LOGI(TAG, "capture button on GPIO%d active-low", (int)pin);
    return ESP_OK;
}
