#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/timer/nrf_grtc_timer.h>
#include <zephyr/drivers/hwinfo.h>

#define PRESS_NODE DT_ALIAS(press_int)
#define MEMS_INT1_NODE DT_ALIAS(mems_int1)
#define MEMS_INT2_NODE DT_ALIAS(mems_int2)
#define ACTIVE_TIMEOUT_MS 15000  // 20 seconds before auto-sleep
#define GRTC_WAKEUP_S     12      // GRTC wakeup after 5s in sleep

const struct gpio_dt_spec press = GPIO_DT_SPEC_GET(PRESS_NODE, gpios);
const struct gpio_dt_spec mems_int1 = GPIO_DT_SPEC_GET(MEMS_INT1_NODE, gpios);
const struct gpio_dt_spec mems_int2 = GPIO_DT_SPEC_GET(MEMS_INT2_NODE, gpios);

void enter_system_off(void)
{

    hwinfo_clear_reset_cause();
	int err = z_nrf_grtc_wakeup_prepare(GRTC_WAKEUP_S * USEC_PER_SEC);
    if (err < 0) {
        printf("GRTC wakeup prepare failed: %d\n", err);
    } else {
        printf("Will also wake from GRTC in %d sec\n", GRTC_WAKEUP_S);
    }
    sys_poweroff();
}

void schedule_sleep_work(struct k_work *work)
{
    printf("Sleep timeout reached, going to system off\n");
    enter_system_off();
}

K_WORK_DELAYABLE_DEFINE(ble_sleep_work, schedule_sleep_work);
void rtc_wakeup_schedule(void){
	// k_work_schedule(&adv_on_work, K_NO_WAIT);
    // Schedule system-off after ACTIVE_TIMEOUT_MS
    k_work_schedule(&ble_sleep_work, K_MSEC(ACTIVE_TIMEOUT_MS));
}

int setup_press_int_wakeup(){
	int rc;
	if (!device_is_ready(press.port)) {
	printf("Pressure INT GPIO device not ready");
	return 0;
    }
	rc = gpio_pin_configure_dt(&press, GPIO_INPUT);
    if (rc < 0) {
        printf("GPIO config failed (%d)\n", rc);
        return 0;
    }

    rc = gpio_pin_interrupt_configure_dt(&press, GPIO_INT_LEVEL_ACTIVE);
    if (rc < 0) {
        printf("GPIO interrupt config failed (%d)\n", rc);
        return 0;
    }
	return rc;
}

int setup_memsint1_wakeup(void) {
    int rc=1;

    if (!device_is_ready(mems_int1.port)) {
        printf("MEMS INT1 GPIO device not ready\n");
        return 0;
    }
printf("Device ready. Configuring pin...\n");
    rc = gpio_pin_configure_dt(&mems_int1, GPIO_INPUT);
    if (rc < 0) {
        printf("MEMS INT1 GPIO config failed \n");
        return 0;
    }
printf("Pin config result: %d\n", rc);
    rc = gpio_pin_interrupt_configure_dt(&mems_int1, GPIO_INT_LEVEL_ACTIVE);

    if (rc < 0) {
        printf("MEMS INT1 interrupt config failed \n");
        return 0;
    }
printf("Interrupt config result: %d\n", rc);
    return rc;
}

int setup_memsint2_wakeup(void) {
    int rc;

    if (!device_is_ready(mems_int2.port)) {
        printf("MEMS INT2 GPIO device not ready\n");
        return -ENODEV;
    }

    rc = gpio_pin_configure_dt(&mems_int2, GPIO_INPUT);
    if (rc < 0) {
        printf("MEMS INT2 GPIO config failed (%d)\n", rc);
        return rc;
    }

    rc = gpio_pin_interrupt_configure_dt(&mems_int2, GPIO_INT_LEVEL_ACTIVE);
    if (rc < 0) {
        printf("MEMS INT2 interrupt config failed (%d)\n", rc);
        return rc;
    }
    return 0;
}

void print_reset_cause(void)
{
    uint32_t cause;
    hwinfo_get_reset_cause(&cause);

    if (cause & RESET_PIN) {
        // printf("Reset by pin\n");
		printf("Start\n");
    } else if (cause & RESET_SOFTWARE) {
        printf("Reset by software\n");
    } else if (cause & RESET_POR) {
        printf("Power-on reset\n");
    } else if (cause & RESET_LOW_POWER_WAKE) {
        // printf("Wake from low power state\n");
		printf("GPIO wakeup\n");
    } else {
        // printf("Reset cause unknown: 0x%08X\n", cause);
		printf("RTC wakeup\n");
    }
}
int main(void)
{
        print_reset_cause();
        setup_press_int_wakeup();
	setup_memsint1_wakeup();
        
	rtc_wakeup_schedule();
        return 0;
        while(1){
             k_msleep(1000);   
        }
}
