#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_now.h"
#include "esp_crc.h"
#include "espnow_example.h"
#include "cJSON.h"
#include "driver/gpio.h"
#include "iot_button.h"

// IP 0x94 ,0xe6 ,0x86 ,0x43 ,0xc6 ,0x34

#define ESPNOW_MAXDELAY 512

#define BUTTON1 GPIO_NUM_0
#define BUTTON2 GPIO_NUM_1
#define BUTTON3 GPIO_NUM_2
#define BUTTON4 GPIO_NUM_3

#define RELAY1  GPIO_NUM_14
#define RELAY2  GPIO_NUM_15
#define RELAY3  GPIO_NUM_16
#define RELAY4  GPIO_NUM_17

int switch1_state = 0;
int switch2_state = 0;
int switch3_state = 0;
int switch4_state = 0;

button_handle_t button1;
button_handle_t button2;
button_event_t event;
static const char *TAG = "espnow_发送";

char switch1_config[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch1\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\"\n}";
char switch1_state_on[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch1\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\",\n\"state\":\"ON\"\n}";
char switch1_state_off[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch1\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\",\n\"state\":\"OFF\"\n}";
char switch2_config[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch2\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\"\n}";
char switch2_state_on[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch2\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\",\n\"state\":\"ON\"\n}";
char switch2_state_off[] = "{\n\"~\": \"homeassistant/switch/kitchen\",\n\"name\": \"bedroomswitch\",\n\"unique_id\": \"kitchen_switch2\",\n\"cmd_t\": \"~/set\",\n\"stat_t\": \"~/state\",\n\"schema\": \"json\",\n\"state\":\"OFF\"\n}";

static uint8_t target_mac[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

static void state_up_task(void *pvParameter);
static void example_espnow_send_cb(const uint8_t *mac_addr, esp_now_send_status_t status);

void button_init()
{
    // create gpio button1
    button_config_t gpio_btn_cfg1 = {
        .type = BUTTON_TYPE_GPIO,
        .long_press_time = 1000,
        .short_press_time = 180,
        .gpio_button_config = {
            .gpio_num = BUTTON1,
            .active_level = 1,
        },
    };
    button1 = iot_button_create(&gpio_btn_cfg1);
    if(NULL == button1) {
        ESP_LOGE("BUTTON", "Button1 create failed");
    }
    // create gpio button2
    button_config_t gpio_btn_cfg2 = {
        .type = BUTTON_TYPE_GPIO,
        .long_press_time = 1000,
        .short_press_time = 180,
        .gpio_button_config = {
            .gpio_num = BUTTON2,
            .active_level = 1,
        },
    };
    button2 = iot_button_create(&gpio_btn_cfg2);
    if(NULL == button2) {
        ESP_LOGE("BUTTON", "Button1 create failed");
    }
}

void gpio_init()
{
    gpio_config_t gpio_Init = {
        .pin_bit_mask = (1ULL << RELAY1) | (1ULL << RELAY2),
        .mode = GPIO_MODE_INPUT_OUTPUT_OD,
        .pull_up_en = 1,
        .pull_down_en = 0,
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&gpio_Init);
}

/* 初始化WIFI为ESPNOW准备*/
static void example_wifi_init(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(ESPNOW_WIFI_MODE));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_set_channel(CONFIG_ESPNOW_CHANNEL, WIFI_SECOND_CHAN_NONE));

#if CONFIG_ESPNOW_ENABLE_LONG_RANGE
    ESP_ERROR_CHECK(esp_wifi_set_protocol(ESPNOW_WIFI_IF, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR));
#endif
}

/*初始化ESPNOW*/
static esp_err_t example_espnow_init(void)
{
    /* 初始化espnow并注册发送回调函数。*/
    ESP_ERROR_CHECK(esp_now_init());
    /*注册回调发送函数*/
    ESP_ERROR_CHECK(esp_now_register_send_cb(example_espnow_send_cb));

    /* Add broadcast peer information to peer list. */
    esp_now_peer_info_t *peer = malloc(sizeof(esp_now_peer_info_t));
    if (peer == NULL)
    {
        ESP_LOGE(TAG, "Malloc peer information fail");
        esp_now_deinit();
        return ESP_FAIL;
    }
    memset(peer, 0, sizeof(esp_now_peer_info_t));
    peer->channel = 1;
    peer->ifidx = ESPNOW_WIFI_IF;
    peer->encrypt = false;
    memcpy(peer->peer_addr, target_mac, 6); // 设置接收数据的开发板的地址
    ESP_ERROR_CHECK(esp_now_add_peer(peer));
    free(peer);
    xTaskCreate(state_up_task, "state_up_task", 2048, NULL, 4, NULL);

    return ESP_OK;
}

static void button_single_click_cb1(void *arg,void *usr_data)
{
    ESP_LOGI(TAG, "按钮按下并弹起");
    ESP_LOGI(TAG, "%d",switch1_state);
    gpio_set_level(RELAY1,switch1_state%2);
    switch1_state += 1;
}

static void button_single_click_cb2(void *arg,void *usr_data)
{
    ESP_LOGI(TAG, "按钮按下并弹起");
    ESP_LOGI(TAG, "%d",switch2_state);
    gpio_set_level(RELAY2,switch2_state%2);
    switch2_state += 1;
}

/* espnow发送或接收回调函数被调用的wifi的任务。*/
static void example_espnow_send_cb(const uint8_t *mac_addr, esp_now_send_status_t status)
{
    if (status == ESP_NOW_SEND_SUCCESS)
    {
        ESP_LOGI("ESP_NOW_SEND_SUCCESS", "数据上传成功！");
    }
    else
    {
        ESP_LOGI("ESP_NOW_SEND_FAIL", "数据上传失败！");
    }
}

static void state_up_task(void *pvParameter)
{
    iot_button_register_cb(button2, BUTTON_PRESS_UP, button_single_click_cb2,NULL);
    iot_button_register_cb(button1, BUTTON_PRESS_UP, button_single_click_cb1,NULL);
    esp_now_send(target_mac, (uint8_t *)switch1_config, strlen(switch1_config));
    esp_now_send(target_mac, (uint8_t *)switch2_config, strlen(switch2_config));
    vTaskDelay(500);
    while (1)
    {
        /*上传switch１状态*/
        if(!gpio_get_level(RELAY1))
        {
            esp_now_send(target_mac, (uint8_t *)switch1_state_on, strlen(switch1_state_on));
            ESP_LOGE("GPIO","ON");
        }else
        {
            esp_now_send(target_mac, (uint8_t *)switch1_state_off, strlen(switch1_state_off));
            ESP_LOGE("GPIO","OFF");
        }
        vTaskDelay(50);
        /*上传switch２状态*/
        if(!gpio_get_level(RELAY2))
        {
            esp_now_send(target_mac, (uint8_t *)switch2_state_on, strlen(switch2_state_on));
        }else
        {
            esp_now_send(target_mac, (uint8_t *)switch2_state_off, strlen(switch2_state_off));
        }
        vTaskDelay(50);
    }
}



void app_main(void)
{
    uint8_t IP[6] = {0};
    esp_efuse_mac_get_default(IP);
    ESP_LOGE(TAG, "0x%x ,0x%x ,0x%x ,0x%x ,0x%x ,0x%x", IP[0], IP[1], IP[2], IP[3], IP[4], IP[5]);
    button_init();
    gpio_init();
    example_wifi_init();
    example_espnow_init();
}
