#include <string.h>
//#include "esp_system.h"
#include "esp_log.h"

#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"

#include "H2201_dispatcher.h"
#include "H2201_bluetooth.h"
#include "H2201_a2dp.h"

void h2201_bluetooth_eventhandler(uint16_t event, void *p_param)
// void h2201_bluetooth_gap_register_callback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
{
    // ESP_LOGI(H2201_BLUETOOTH_TAG, "gap register event: %d", event);
    esp_bt_gap_cb_param_t *param = (esp_bt_gap_cb_param_t *)(p_param);

    switch (event)
    {
    case ESP_BT_GAP_AUTH_CMPL_EVT: // Authentication complete event
    {
        if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS)
        {
            ESP_LOGI(H2201_BLUETOOTH_TAG, "authentication success: %s", param->auth_cmpl.device_name);
            esp_log_buffer_hex(H2201_BLUETOOTH_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN);
        }
        else
        {
            ESP_LOGE(H2201_BLUETOOTH_TAG, "authentication failed, status:%d", param->auth_cmpl.stat);
        }
        break;
    }

    case ESP_BT_GAP_CFM_REQ_EVT: // Security Simple Pairing User Confirmation request.
        ESP_LOGI(H2201_BLUETOOTH_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
        esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
        break;

    case ESP_BT_GAP_KEY_NOTIF_EVT: // Security Simple Pairing Passkey Notification
        ESP_LOGI(H2201_BLUETOOTH_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey);
        break;

    case ESP_BT_GAP_KEY_REQ_EVT: // Security Simple Pairing Passkey request
        ESP_LOGI(H2201_BLUETOOTH_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
        break;

    case ESP_BT_GAP_MODE_CHG_EVT: //
        ESP_LOGI(H2201_BLUETOOTH_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode:%d", param->mode_chg.mode);
        break;

    case ESP_BT_GAP_CONFIG_EIR_DATA_EVT: // Config EIR data event
        ESP_LOGI(H2201_BLUETOOTH_TAG, "ESP_BT_GAP_CONFIG_EIR_DATA_EVT");
        break;

    default:
    {
        ESP_LOGI(H2201_BLUETOOTH_TAG, "event: %d", event);
        break;
    }
    }
    return;
}

void h2201_bluetooth_gap_register_callback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
{
    h2201_dispatcher_work_dispatch(h2201_bluetooth_eventhandler, event, param, sizeof(esp_bt_gap_cb_param_t), NULL);
}

void h2201_bluetooth_init()
{
    // release not used BLE memory
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE));
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();

    esp_err_t err;
    if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK)
    {
        ESP_LOGE(H2201_BLUETOOTH_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }

    if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK)
    {
        ESP_LOGE(H2201_BLUETOOTH_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }

    if ((err = esp_bluedroid_init()) != ESP_OK)
    {
        ESP_LOGE(H2201_BLUETOOTH_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }

    if ((err = esp_bluedroid_enable()) != ESP_OK)
    {
        ESP_LOGE(H2201_BLUETOOTH_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err));
        return;
    }

    /* Bluetooth device name, connection mode and profile set up */
    esp_bt_dev_set_device_name(H2201_BLUETOOTH_DEVICENAME);
    esp_bt_gap_register_callback(h2201_bluetooth_gap_register_callback);

    h2201_a2dp_create_sink();

    /* set discoverable and connectable mode, wait to be connected */
    esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);

    /* Set default parameters for Secure Simple Pairing */
    esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
    esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
    esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
}