#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_timer.h"

/* Most development boards have "boot" button attached to GPIO0.
 * You can also change this to another pin.
 */
#define STARTUP_PERIOD_MS 30000
#define WAITING_PERIOD_MS 30000

#define STATUS_LED 13

#define BIKE_BAT_SIG 4

static bool Sleep = false;
const char * TAG = "APP";

void set_sleep(){
    Sleep = true;
}


const esp_timer_create_args_t oneshot_timer_args = {
        .callback = &set_sleep,
        /* argument specified here will be passed to timer callback function */
        .name = "30_seconds"
};






void app_main(void)
{
    esp_timer_handle_t oneshot_timer;
    ESP_ERROR_CHECK(esp_timer_create(&oneshot_timer_args, &oneshot_timer));
    /* Configure the button GPIO as input, enable wakeup */
    const TickType_t startup_period = pdMS_TO_TICKS(STARTUP_PERIOD_MS);
    const TickType_t waiting_period = pdMS_TO_TICKS(WAITING_PERIOD_MS);
    // gpio_pad_select_gpio(STATUS_LED);
    //gpio_set_direction(STATUS_LED,GPIO_MODE_OUTPUT);

    //gpio_set_level(STATUS_LED,0);
    const int button_gpio_num = BIKE_BAT_SIG;
    const int wakeup_level = 1;
    gpio_config_t config = {
            .pin_bit_mask = BIT64(button_gpio_num),
            .mode = GPIO_MODE_INPUT
    };
    ESP_ERROR_CHECK(gpio_config(&config));
    gpio_wakeup_enable(button_gpio_num,
            wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);

    ESP_LOGI(TAG,"Wainting %d MS\n",STARTUP_PERIOD_MS);
    vTaskDelay(startup_period);
    while (true) {
        /* Wake up in 2 seconds, or when button is pressed */
        //gpio_set_level(STATUS_LED,1);
        if (Sleep){
        esp_sleep_enable_timer_wakeup(WAITING_PERIOD_MS*1000);
        esp_sleep_enable_gpio_wakeup();

        printf("Entering light sleep\n");
        /* To make sure the complete line is printed before entering sleep mode,
         * need to wait until UART TX FIFO is empty:
         */
        uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);

        /* Get timestamp before entering sleep */
        int64_t t_before_us = esp_timer_get_time();

        /* Enter sleep mode */
        esp_light_sleep_start();
        /* Execution continues here after wakeup */

        /* Get timestamp after waking up from sleep */
        int64_t t_after_us = esp_timer_get_time();

        /* Determine wake up reason */
        const char* wakeup_reason;
        switch (esp_sleep_get_wakeup_cause()) {
            case ESP_SLEEP_WAKEUP_TIMER:
                wakeup_reason = "timer";
                break;
            case ESP_SLEEP_WAKEUP_GPIO:
                wakeup_reason = "pin";
                break;
            default:
                wakeup_reason = "other";
                break;
        }

        ESP_LOGI(TAG,"Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n",
                wakeup_reason, t_after_us / 1000, (t_after_us - t_before_us) / 1000);
        Sleep=false;
    }
    else{
        vTaskDelay(10);
        if(gpio_get_level(BIKE_BAT_SIG)==0){
            esp_timer_star_once(oneshot_timer,30000000);
        }
        else{
            esp_timer_stop(oneshot_timer);
        }
    }
}

}