/* Play music from Bluetooth device

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <inttypes.h>
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "esp_peripherals.h"
#include "periph_touch.h"
#include "periph_adc_button.h"
#include "periph_button.h"
#include "esp_bt_defs.h"
#include "esp_gap_bt_api.h"
#include "esp_hf_client_api.h"

#include "audio_element.h"
#include "audio_pipeline.h"
#include "audio_event_iface.h"
#include "audio_mem.h"

#include "i2s_stream.h"
#include "board.h"
#include "bluetooth_service.h"
#include "filter_resample.h"
#include "raw_stream.h"
#include <esp_hf_client_api.h>
#include "argtable3/argtable3.h"
#include "esp_hf_ag_api.h"
#include "a2dp_stream.h"
#include "board.h"
#include "input_key_service.h"
#include "a2dp_sink_and_hfp.h"
#include "gatts_table_creat_demo.h"
#if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
#include "filter_resample.h"
#endif
#include "bt_keycontrol.h"

#include "audio_idf_version.h"

#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0))
#define HFP_RESAMPLE_RATE 16000
#else
#define HFP_RESAMPLE_RATE 8000
#endif

static const char *TAG = "BLUETOOTH_EXAMPLE";
static const char *BT_HF_TAG = "BT_HF";
static const char *BT_RC_CT_TAG = "BT_RC_CT_TAG";
static const char *BT_AV_TAG = "BT_AV_TAG";

BT_Music Bt_Music_Data;
BT_Phone Bt_Phone_Data;
BT_User Bt_User_Data;





static audio_element_handle_t raw_read, bt_stream_reader, i2s_stream_writer, i2s_stream_reader;
static audio_pipeline_handle_t pipeline_d, pipeline_e;
static bool is_get_hfp = true;

const char *c_hf_evt_str[] = {
    "CONNECTION_STATE_EVT",      /*!< connection state changed event */
    "AUDIO_STATE_EVT",           /*!< audio connection state change event */
    "VR_STATE_CHANGE_EVT",       /*!< voice recognition state changed */
    "CALL_IND_EVT",              /*!< call indication event */
    "CALL_SETUP_IND_EVT",        /*!< call setup indication event */
    "CALL_HELD_IND_EVT",         /*!< call held indicator event */
    "NETWORK_STATE_EVT",         /*!< network state change event */
    "SIGNAL_STRENGTH_IND_EVT",   /*!< signal strength indication event */
    "ROAMING_STATUS_IND_EVT",    /*!< roaming status indication event */
    "BATTERY_LEVEL_IND_EVT",     /*!< battery level indication event */
    "CURRENT_OPERATOR_EVT",      /*!< current operator name event */
    "RESP_AND_HOLD_EVT",         /*!< response and hold event */
    "CLIP_EVT",                  /*!< Calling Line Identification notification event */
    "CALL_WAITING_EVT",          /*!< call waiting notification */
    "CLCC_EVT",                  /*!< listing current calls event */
    "VOLUME_CONTROL_EVT",        /*!< audio volume control event */
    "AT_RESPONSE",               /*!< audio volume control event */
    "SUBSCRIBER_INFO_EVT",       /*!< subscriber information event */
    "INBAND_RING_TONE_EVT",      /*!< in-band ring tone settings */
    "LAST_VOICE_TAG_NUMBER_EVT", /*!< requested number from AG event */
    "RING_IND_EVT",              /*!< ring indication event */
};

// esp_hf_client_connection_state_t
const char *c_connection_state_str[] = {
    "disconnected",
    "connecting",
    "connected",
    "slc_connected",
    "disconnecting",
};

// esp_hf_client_audio_state_t
const char *c_audio_state_str[] = {
    "disconnected",
    "connecting",
    "connected",
    "connected_msbc",
};

/// esp_hf_vr_state_t
const char *c_vr_state_str[] = {
    "disabled",
    "enabled",
};

// esp_hf_service_availability_status_t
const char *c_service_availability_status_str[] = {
    "unavailable",
    "available",
};

// esp_hf_roaming_status_t
const char *c_roaming_status_str[] = {
    "inactive",
    "active",
};

// esp_hf_client_call_state_t
const char *c_call_str[] = {
    "NO call in progress",
    "call in progress",
};

// esp_hf_client_callsetup_t
const char *c_call_setup_str[] = {
    "NONE",
    "INCOMING",
    "OUTGOING_DIALING",
    "OUTGOING_ALERTING"};

// esp_hf_client_callheld_t
const char *c_call_held_str[] = {
    "NONE held",
    "Held and Active",
    "Held",
};

// esp_hf_response_and_hold_status_t
const char *c_resp_and_hold_str[] = {
    "HELD",
    "HELD ACCEPTED",
    "HELD REJECTED",
};

// esp_hf_client_call_direction_t
const char *c_call_dir_str[] = {
    "outgoing",
    "incoming",
};

// esp_hf_client_call_state_t
const char *c_call_state_str[] = {
    "active",
    "held",
    "dialing",
    "alerting",
    "incoming",
    "waiting",
    "held_by_resp_hold",
};

// esp_hf_current_call_mpty_type_t
const char *c_call_mpty_type_str[] = {
    "single",
    "multi",
};

// esp_hf_volume_control_target_t
const char *c_volume_control_target_str[] = {
    "SPEAKER",
    "MICROPHONE"};

// esp_hf_at_response_code_t
const char *c_at_response_code_str[] = {
    "OK",
    "ERROR"
    "ERR_NO_CARRIER",
    "ERR_BUSY",
    "ERR_NO_ANSWER",
    "ERR_DELAYED",
    "ERR_BLACKLILSTED",
    "ERR_CME",
};

// esp_hf_subscriber_service_type_t
const char *c_subscriber_service_type_str[] = {
    "unknown",
    "voice",
    "fax",
};

// esp_hf_client_in_band_ring_state_t
const char *c_inband_ring_state_str[] = {
    "NOT provided",
    "Provided",
};

static void bt_app_hf_client_audio_open(void)
{
    ESP_LOGE(BT_HF_TAG, "bt_app_hf_client_audio_open");
    int sample_rate = HFP_RESAMPLE_RATE;
    audio_element_info_t bt_info = {0};
    audio_element_getinfo(bt_stream_reader, &bt_info);
    bt_info.sample_rates = sample_rate;
    bt_info.channels = 1;
    bt_info.bits = 16;
    audio_element_setinfo(bt_stream_reader, &bt_info);
    audio_element_report_info(bt_stream_reader);
}

static void bt_app_hf_client_audio_close(void)
{
    ESP_LOGE(BT_HF_TAG, "bt_app_hf_client_audio_close");
    int sample_rate = periph_bluetooth_get_a2dp_sample_rate();
    audio_element_info_t bt_info = {0};
    audio_element_getinfo(bt_stream_reader, &bt_info);
    bt_info.sample_rates = sample_rate;
    bt_info.channels = 2;
    bt_info.bits = 16;
    audio_element_setinfo(bt_stream_reader, &bt_info);
    audio_element_report_info(bt_stream_reader);
}

static uint32_t bt_app_hf_client_outgoing_cb(uint8_t *p_buf, uint32_t sz)
{
    int out_len_bytes = 0;
    char *enc_buffer = (char *)audio_malloc(sz);
    AUDIO_MEM_CHECK(BT_HF_TAG, enc_buffer, return 0);
    if (is_get_hfp)
    {
        out_len_bytes = raw_stream_read(raw_read, enc_buffer, sz);
    }

    if (out_len_bytes == sz)
    {
        is_get_hfp = false;
        memcpy(p_buf, enc_buffer, out_len_bytes);
        free(enc_buffer);
        return sz;
    }
    else
    {
        is_get_hfp = true;
        free(enc_buffer);
        return 0;
    }
}

/**
 * @brief 蓝牙耳机客户端接收数据回调函数
 *
 * 当蓝牙耳机客户端接收到数据时，此函数被调用。
 * 其目的是处理接收到的数据，并将其传递给音频元素进行进一步处理。
 * 如果音频元素处于运行状态，数据将被输出到音频管道的下一阶段。
 *
 * @param buf 指向接收数据缓冲区的指针
 * @param sz 接收数据的字节数
 */
static void bt_app_hf_client_incoming_cb(const uint8_t *buf, uint32_t sz)
{
    /* 检查音频流读取器是否已初始化 */
    if (bt_stream_reader)
    {
        /* 判断音频元素当前状态是否为正在运行 */
        if (audio_element_get_state(bt_stream_reader) == AEL_STATE_RUNNING)
        {
            /* 将接收到的数据输出到音频元素进行处理 */
            audio_element_output(bt_stream_reader, (char *)buf, sz);
            /* 通知蓝牙耳机客户端输出数据已准备就绪 */
            esp_hf_client_outgoing_data_ready();
        }
    }
}
/**
 * @brief 蓝牙免提配置文件（Hands-Free Profile, HFP）客户端事件处理回调函数。
 *
 * 本函数响应HFP客户端接收到的所有关键事件，涵盖连接管理、音频控制、AT指令交互等多个方面，
 * 并针对每种事件执行相应的处理逻辑，同时记录详细的日志信息，以支持故障排查与系统调试。
 *
 * @param event 定义了当前触发的事件类型，如连接建立、断开、音频状态变化等。
 * @param param 与事件相关的参数集合，包含具体的状态信息或数据细节。
 */
void bt_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param)
{
    // 日志记录事件类型
    if (event <= ESP_HF_CLIENT_RING_IND_EVT)
    {
        ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]);
    }
    else
    {
        ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event);
    }

    // 根据事件类型进行具体处理
    switch (event)
    {
    case ESP_HF_CLIENT_CONNECTION_STATE_EVT:
        // 连接状态事件处理
        ESP_LOGE(BT_HF_TAG, "--connection state %s, peer feats 0x%" PRIx32 ", chld feats 0x%" PRIx32,
                 c_connection_state_str[param->conn_stat.state],
                 param->conn_stat.peer_feat,
                 param->conn_stat.chld_feat);

        if (param->conn_stat.state == 0)
        {
            Bt_User_Data.Status = Disconnect;
        }
        else if (param->conn_stat.state == 2)
        {
            Bt_User_Data.Status = Connect;
        }

        break;
    case ESP_HF_CLIENT_AUDIO_STATE_EVT:
        // 音频状态事件处理
        ESP_LOGE(BT_HF_TAG, "--audio state %s",
                 c_audio_state_str[param->audio_stat.state]);
#if CONFIG_HFP_AUDIO_DATA_PATH_HCI
        // 根据音频状态打开或关闭音频连接
        if ((param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED) || (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC))
        {
            bt_app_hf_client_audio_open();
            esp_hf_client_register_data_callback(bt_app_hf_client_incoming_cb,
                                                 bt_app_hf_client_outgoing_cb);
        }
        else if (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED)
        {
            bt_app_hf_client_audio_close();
        }
#endif /* #if CONFIG_HFP_AUDIO_DATA_PATH_HCI */
        break;
    case ESP_HF_CLIENT_BVRA_EVT:
        // VR状态事件处理
        ESP_LOGE(BT_HF_TAG, "--VR state %s",
                 c_vr_state_str[param->bvra.value]);
        break;
    case ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT:
        // 服务可用性事件处理
        ESP_LOGE(BT_HF_TAG, "--NETWORK STATE %s",
                 c_service_availability_status_str[param->service_availability.status]);
        break;
    case ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT:
        // 流动状态事件处理
        ESP_LOGE(BT_HF_TAG, "--ROAMING: %s",
                 c_roaming_status_str[param->roaming.status]);
        break;
    case ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT:
        // 信号强度事件处理
        ESP_LOGE(BT_HF_TAG, "-- signal strength: %d",
                 param->signal_strength.value);
        break;
    case ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT:
        // 电池电量事件处理
        ESP_LOGE(BT_HF_TAG, "--battery level %d",
                 param->battery_level.value);
        break;
    case ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT:
        // 当前操作员事件处理
        ESP_LOGE(BT_HF_TAG, "--operator name: %s",
                 param->cops.name);
        break;
    case ESP_HF_CLIENT_CIND_CALL_EVT:
        // 呼叫指示事件处理
        // ESP_LOGE(BT_HF_TAG, "--Call indicator %s",
        //          c_call_str[param->call.status]);
        if (param->call.status != 0)
        {
            Bt_Phone_Data.Status = Call_In_Progress;
        }
        else
        {
            Bt_Phone_Data.Status = Call_idel;
        }

        break;
    case ESP_HF_CLIENT_CIND_CALL_SETUP_EVT:
        // 呼叫设置指示事件处理
        // ESP_LOGE(BT_HF_TAG, "--Call setup indicator %s",
        //          c_call_setup_str[param->call_setup.status]);
        switch (param->call_setup.status)
        {
        case 0:
            if (Bt_Phone_Data.Status != Call_In_Progress)
            {
                Bt_Phone_Data.Status = Call_idel;
                memset(Bt_Phone_Data.Number, 0XFF, BTIPHONENUMBERMAX);
            }
            break;
        case 1:
            Bt_Phone_Data.Status = Call_Incoming;
            break;
        case 2:
            Bt_Phone_Data.Status = Call_Outgoing_Dialing;
            break;
        case 3:
            Bt_Phone_Data.Status = Call_OUtgoing_Alerting;
            break;
        default:
            break;
        }

        break;
    case ESP_HF_CLIENT_CIND_CALL_HELD_EVT:
        // 呼叫保持指示事件处理
        ESP_LOGE(BT_HF_TAG, "--Call held indicator %s",
                 c_call_held_str[param->call_held.status]);
        break;
    case ESP_HF_CLIENT_BTRH_EVT:
        // 响应和保持事件处理
        ESP_LOGE(BT_HF_TAG, "--response and hold %s",
                 c_resp_and_hold_str[param->btrh.status]);
        break;
    case ESP_HF_CLIENT_CLIP_EVT:
        // 来电号码事件处理
        ESP_LOGE(BT_HF_TAG, "--clip number %s",
                 (param->clip.number == NULL) ? "NULL" : (param->clip.number));
        break;
    case ESP_HF_CLIENT_CCWA_EVT:
        // 呼叫等待事件处理
        ESP_LOGE(BT_HF_TAG, "--call_waiting %s",
                 (param->ccwa.number == NULL) ? "NULL" : (param->ccwa.number));
        break;
    case ESP_HF_CLIENT_CLCC_EVT:
        // 当前呼叫事件处理
        ESP_LOGE(BT_HF_TAG, "--Current call: idx %d, dir %s, state %s, mpty %s, number %s",
                 param->clcc.idx,
                 c_call_dir_str[param->clcc.dir],
                 c_call_state_str[param->clcc.status],
                 c_call_mpty_type_str[param->clcc.mpty],
                 (param->clcc.number == NULL) ? "NULL" : (param->clcc.number));
        memset(Bt_Phone_Data.Number, 0XFF, BTIPHONENUMBERMAX);
        if (param->clcc.idx != 0)
        {
            memcpy(Bt_Phone_Data.Number, param->clcc.number, BTIPHONENUMBERMAX);
        }
        break;
    case ESP_HF_CLIENT_VOLUME_CONTROL_EVT:
        // 音量控制事件处理
        ESP_LOGE(BT_HF_TAG, "--volume_target: %s, volume %d",
                 c_volume_control_target_str[param->volume_control.type],
                 param->volume_control.volume);
        printf("ESP_HF_CLIENT_VOLUME_CONTROL_EVT \n");

        break;
    case ESP_HF_CLIENT_AT_RESPONSE_EVT:
        // AT命令响应事件处理
      //  ESP_LOGE(BT_HF_TAG, "--AT response event, code %d, cme %d",
      //           param->at_response.code, param->at_response.cme);
        break;
    case ESP_HF_CLIENT_CNUM_EVT:
        // 订阅者信息事件处理
        ESP_LOGE(BT_HF_TAG, "--subscriber type %s, number %s",
                 c_subscriber_service_type_str[param->cnum.type],
                 (param->cnum.number == NULL) ? "NULL" : param->cnum.number);
        break;
    case ESP_HF_CLIENT_BSIR_EVT:
        // 带内铃声状态事件处理
        ESP_LOGE(BT_HF_TAG, "--inband ring state %s",
                 c_inband_ring_state_str[param->bsir.state]);
        break;
    case ESP_HF_CLIENT_BINP_EVT:
        // 上一个语音标签号码事件处理
        ESP_LOGE(BT_HF_TAG, "--last voice tag number: %s",
                 (param->binp.number == NULL) ? "NULL" : param->binp.number);
        break;
    default:
        // 未知事件处理
        ESP_LOGE(BT_HF_TAG, "HF_CLIENT EVT: %d", event);
        break;
    }
}

/**
 * @brief 蓝牙AVRC(高级音频分发配置文件)通知事件处理函数。
 *
 * 此函数负责处理由蓝牙AVRC模块发送的各种通知事件，
 * 包括曲目变更、播放状态变更以及播放位置变更等。
 *
 * @param event_id 事件ID，标识具体的事件类型。
 * @param event_parameter 指向事件参数的指针，包含关于事件的具体信息。
 */
static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter)
{
    printf("bt_av_notify_evt_handler %d \n", event_id);
    switch (event_id)
    {
    /* 处理曲目变更事件 */
    /* 当新曲目加载时，触发此事件 */
    case ESP_AVRC_RN_TRACK_CHANGE:
        // bt_av_new_track();

        break;
    /* 处理播放状态变更事件 */
    /* 当曲目状态发生变化时，触发此事件 */
    case ESP_AVRC_RN_PLAY_STATUS_CHANGE:
        // ESP_LOGI(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback);

        Bt_Music_Data.MusicStatus = event_parameter->playback;
        // printf("Bt_Music_Data.MusicStatus %d \n",Bt_Music_Data.MusicStatus);

        // bt_av_playback_changed();
        break;
        /* 处理播放位置变更事件 */
    /* 当曲目播放位置发生变化时，触发此事件 */
    case ESP_AVRC_RN_PLAY_POS_CHANGED:
        ESP_LOGI(BT_AV_TAG, "Play position changed: %" PRIu32 "-ms", event_parameter->play_pos);
        // bt_av_play_pos_changed();
        break;
    /* others */
    default:
        ESP_LOGI(BT_AV_TAG, "unhandled event: %d", event_id);
        break;
    }
}

/**
 * @brief 处理AVRC控制器事件的函数
 *
 * 该函数用于处理AVRC控制器触发的各种事件，根据事件类型执行相应的处理逻辑。
 *
 * @param event 事件类型
 * @param p_param 事件参数指针，具体事件参数类型取决于事件类型
 */
static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param)
{
    // 将通用参数指针转换为AVRC控制器事件参数指针
    esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param);

    // 日志记录函数调用和事件类型
    ESP_LOGD(BT_RC_CT_TAG, "%s bt_av_hdl_avrc_ct_evt: %d", __func__, event);

    // 如果事件是状态改变通知事件
    if (event == ESP_AVRC_CT_CHANGE_NOTIFY_EVT)
    {
        // 调用状态改变通知处理函数，传递事件ID和事件参数
        bt_av_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter);
    }
}

/**
 * @brief AVRCP控制器回调函数
 *
 * 该函数作为AVRCP控制器事件的回调函数，用于处理不同的AVRCP事件。
 * 根据事件类型，它执行相应的操作，如处理元数据响应、连接状态变化等。
 *
 * @param event 事件类型
 * @param p_param 事件参数指针
 */
static void bt_app_avrc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *p_param)
{
    esp_avrc_ct_cb_param_t *rc = p_param;
    switch (event)
    {
    case ESP_AVRC_CT_METADATA_RSP_EVT:
    {
        // 动态分配内存以存储元数据属性文本
        uint8_t *tmp = audio_calloc(1, rc->meta_rsp.attr_length + 1);
        memcpy(tmp, rc->meta_rsp.attr_text, rc->meta_rsp.attr_length);

        // 根据属性ID处理不同的元数据
        if (rc->meta_rsp.attr_id == 0X1)
        {
            // 清空歌词缓冲区，并记录歌词信息
            memset(Bt_Music_Data.MusicLyrics, 0xff, BTMUSICBUFFMAX);
            ESP_LOGI(TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, tmp);
            ESP_LOGI(TAG, "len %d", rc->meta_rsp.attr_length);
            if (rc->meta_rsp.attr_length < BTMUSICBUFFMAX)
            {
                memcpy(Bt_Music_Data.MusicLyrics, tmp, rc->meta_rsp.attr_length);
            }
        }
        else if (rc->meta_rsp.attr_id == 0x2)
        {
            // 清空艺术家缓冲区，并记录艺术家信息
            memset(Bt_Music_Data.MusicActor, 0xff, BTMUSICBUFFMAX);
            ESP_LOGI(TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, tmp);
            if (rc->meta_rsp.attr_length < BTMUSICBUFFMAX)
            {
                memcpy(Bt_Music_Data.MusicActor, tmp, rc->meta_rsp.attr_length);
            }
        }
        else if (rc->meta_rsp.attr_id == 0x4)
        {
            // 清空专辑缓冲区，并记录专辑信息
            memset(Bt_Music_Data.MusicAlbum, 0xff, BTMUSICBUFFMAX);
            ESP_LOGI(TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, tmp);
            if (rc->meta_rsp.attr_length < BTMUSICBUFFMAX)
            {
                memcpy(Bt_Music_Data.MusicAlbum, tmp, rc->meta_rsp.attr_length);
            }
        }

        // 释放之前分配的内存
        audio_free(tmp);
        break;
    }
    // 处理其他类型的AVRCP事件
    case ESP_AVRC_CT_CONNECTION_STATE_EVT:
    case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT:
    case ESP_AVRC_CT_CHANGE_NOTIFY_EVT:
    case ESP_AVRC_CT_REMOTE_FEATURES_EVT:
    case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT:
        bt_av_hdl_avrc_ct_evt(event, p_param);
        break;
    default:
        break;
    }
}

int timertest = 0;
esp_periph_handle_t bt_periph;
esp_bd_addr_t peer_addr[6] = {0};
int bond_dev_num;

/**
 * 获取已配对蓝牙设备的数量并保存第一个设备的地址
 *
 * @return 如果存在已配对设备，则返回1；否则返回0。
 */
uint8_t app_BT_Get_BondDev(void)
{
    uint8_t ret = 0; // 初始化返回值为0，表示未找到已配对设备
    // 获取已配对设备的数量
    bond_dev_num = esp_bt_gap_get_bond_device_num();
    // 打印已配对设备的数量
    // printf("bond_dev_num %d \n",bond_dev_num);

    // 检查是否存在已配对设备
    if (bond_dev_num)
    {
        // 分配内存以存储已配对设备的地址列表
        esp_bd_addr_t *dev_list = (esp_bd_addr_t *)malloc(sizeof(esp_bd_addr_t) * bond_dev_num);
        // 获取已配对设备的地址列表
        esp_bt_gap_get_bond_device_list(&bond_dev_num, dev_list);
        // 复制第一个设备的地址到peer_addr变量
        memcpy(peer_addr, dev_list, 6);

        // 打印第一个设备的地址

        // for (int i = 0; i < bond_dev_num; i++)
        // {
        //     printf("addr %p \n",peer_addr[i]);
        // }


        ret = 1; // 设置返回值为1，表示找到了已配对设备
    }
    else
    {
        // 如果没有已配对设备，清零peer_addr
        memset(peer_addr, 0, 6);
        ret = 0; // 设置返回值为0，表示未找到已配对设备
    }

    return ret;
}

/**
 * @brief 本函数用于检查是否有已配对的蓝牙设备，并尝试自动连接到该设备。如果存在已配对的设备，且尚未连接，则函数将发起连接。
 * @return - 0：没有执行连接操作或连接操作失败或已连接；
 *         - 1：发起连接操作。
 */
uint8_t Auto_Connect_Bt(void)
{
    uint8_t result = 0;

    if (Bt_User_Data.Status == Connect)
    {
        return result;
    }

    if (app_BT_Get_BondDev() == 1)
    {
        esp_hf_client_connect(peer_addr[0]); /* 自动连接蓝牙 */
        result = 1;
    }
    return result;
}

/**
 * @brief 自动断开蓝牙电话连接函数
 *
 * 该函数用于在特定条件下自动断开与蓝牙设备的音频连接。
 * 主要用于当系统检测到需要断开连接的情况时，主动发起断开操作。
 *
 * @return uint8_t 返回执行结果，1表示成功发起断开连接操作，0表示未执行断开操作。
 */
uint8_t Bt_AutoCut_Phone(void)
{
    uint8_t result = 0;

    if (Bt_User_Data.Status == Connect)
    {
        esp_hf_client_disconnect_audio(peer_addr[0]);
        result = 1;
    }
    return result; // 返回执行结果
}

/**
 * @brief 自动接听蓝牙电话
 * 该函数用于配置蓝牙耳机自动接听电话。当有来电时，无需用户操作，耳机将自动接听电话。
 * @note 该功能需要蓝牙耳机支持，并且在配对时已正确配置了相关蓝牙属性。
 */
void Bt_Call_Auto_Answer(void)
{
    esp_hf_client_answer_call();
}

/**
 * @brief 自动拒绝来电函数
 *
 * 该函数用于在蓝牙 Hands-Free 模式下自动拒绝来电。
 * 当应用程序或系统需要自动拒绝来电时，可以调用此函数。
 *
 * @note 调用此函数将导致当前来电被拒绝。
 */
void Bt_Call_Auto_Reject(void)
{
    esp_hf_client_reject_call();
}
/**
 * @brief 获取蓝牙电话状态
 * @return 详见枚举 _phone_status
 */
_phone_status Get_Bt_Phone_Status(void)
{
    return Bt_Phone_Data.Status;
}
/**
 * @brief 获取电话号码
 * @return 最大长度为20，0XFF为无效值；
 */
uint8_t *Get_Bt_Phone_Num(void)
{
    return Bt_Phone_Data.Number;
}




/**
 * @brief 控制蓝牙音乐播放函数
 * @return uint8_t 返回值为1表示音乐播放已启动，返回值为0表示未启动音乐播放。
 */
uint8_t Bt_Music_Play(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_play(bt_periph);
        result = 1;
    }
    return result;
}

/**
 * @brief 控制蓝牙音乐暂停函数
 * @return 1 暂停成功 0 当前蓝牙未连接 暂停失败
 */
uint8_t Bt_Music_Stop(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_pause(bt_periph);
        result = 1;
    }
    return result;
}

/**
 * @brief 控制蓝牙音乐切换到下一曲目
 * @return 1 切换成功 0 当前蓝牙未连接 切换失败
 */
uint8_t Bt_Music_Next(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_avrc_next(bt_periph);
        result = 1;
    }
    return result;
}
/**
 * @brief 控制蓝牙音乐切换到上一曲目
 * @return 1 切换成功 0 当前蓝牙未连接 切换失败
 */
uint8_t Bt_Music_Previous(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_avrc_prev(bt_periph);
        result = 1;
    }
    return result;
}
/**
 * @brief 增加蓝牙音乐音量
 * @return 1 增加成功 0 当前蓝牙未连接 增加失败
 */
uint8_t Bt_Music_Volume_Up(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_volume_up(bt_periph);
        result = 1;
    }
    return result;
}
/**
 * @brief 降低蓝牙音乐音量
 * @return uint8_t 操作结果，1表示音量降低操作成功，0表示操作未执行。
 */
uint8_t Bt_Music_Volume_Down(void)
{
    uint8_t result = 0;
    if (Bt_User_Data.Status == Connect)
    {
        periph_bt_volume_down(bt_periph);
        result = 1;
    }
    return result;
}
/**
 * @brief  获取蓝牙歌词信息数据
 * @return 数据长度最大50,0XFF为无效数据
 */
uint8_t *Get_BT_Music_Lyrics(void)
{
    return Bt_Music_Data.MusicLyrics;
}

/**
 * @brief 获取蓝牙音乐作者
 * @return 数据长度最大50，0XFF为无效数据
 */
uint8_t *Get_BT_Music_Actor(void)
{
    return Bt_Music_Data.MusicActor;
}

/**
 * @brief 获取蓝牙音乐专辑信息
 * @return 数据长度最大50，0XFF为无效数据
 */
uint8_t *Get_BT_Music_Album(void)
{
    return Bt_Music_Data.MusicAlbum;
}


/**
 * @brief 获取蓝牙播放状态
 * @return 详见枚举_music_status
 */
_music_status Get_Bt_Music_Status(void)
{
    return Bt_Music_Data.MusicStatus;
}























void test_Tasks(void *arg)
{
    // create_example_freetype();
    Bt_User_Data.Status = Disconnect;
    while (1)
    {


        // esp_bt_dev_set_device_name("YEDEA-C011-L");
        // printf("next \n");
        //periph_bluetooth_next(bt_periph); /* 下一首 */
        // periph_bluetooth_prev(bt_periph);       /* 上一首 */

        // periph_bluetooth_play(bt_periph);   /* bofang */
        // periph_bluetooth_pause(bt_periph);  /* zan ting  */


    // periph_bt_volume_up(bt_periph);
    // periph_bt_volume_down(bt_periph);

     //periph_bt_avrc_next(bt_periph);

    // periph_bt_volume_up(bt_periph);

    // Bt_Music_Previous();

// printf("test \n");
        // test();
        //test_BTMUSIC();

        // if(app_BT_Get_BondDev() == 1)
        // {
        //     esp_hf_client_connect(peer_addr);   /* 自动连接蓝牙 */
        // }

// Bt_Music_Next();
        // Bt_Music_Play();

// Bt_Music_Stop();
        if (Bt_User_Data.Status == Connect)
        {
            esp_hf_client_query_current_calls();
            //test_volume();
        }

        if (Bt_Phone_Data.Status == Call_Incoming)
        {
            // Bt_Call_Auto_Reject();
        }

        if (Bt_Phone_Data.Status == Call_In_Progress)
        {
            Bt_Phone_Data.Duration++;
            Bt_AutoCut_Phone();
        }
        else
        {
            Bt_Phone_Data.Duration = 0;
          //  Auto_Connect_Bt();
        }

        // printf("duration %ld \n",Bt_Phone_Data.Duration);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}


static esp_err_t input_key_service_cb(periph_service_handle_t handle, periph_service_event_t *evt, void *ctx)
{
    if (evt->type == INPUT_KEY_SERVICE_ACTION_CLICK_RELEASE) {
        ESP_LOGI(TAG, "[ * ] input key id is %d", (int)evt->data);
        switch ((int)evt->data) {
            case INPUT_KEY_USER_ID_PLAY:
                ESP_LOGI(TAG, "[ * ] [Play] play");
                periph_bt_play(bt_periph);
                break;
            case INPUT_KEY_USER_ID_SET:
                ESP_LOGI(TAG, "[ * ] [Set] pause");
                periph_bt_pause(bt_periph);
                break;
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0))
            case INPUT_KEY_USER_ID_VOLUP:
                ESP_LOGI(TAG, "[ * ] [long Vol+] Vol+");
                periph_bt_volume_up(bt_periph);
                break;
            case INPUT_KEY_USER_ID_VOLDOWN:
                ESP_LOGI(TAG, "[ * ] [long Vol-] Vol-");
                periph_bt_volume_down(bt_periph);
                break;
#endif
        }
    } else if (evt->type == INPUT_KEY_SERVICE_ACTION_PRESS) {
        ESP_LOGI(TAG, "[ * ] input key id is %d", (int)evt->data);
        switch ((int)evt->data) {
            case INPUT_KEY_USER_ID_VOLUP:
                ESP_LOGI(TAG, "[ * ] [long Vol+] next");
                periph_bt_avrc_next(bt_periph);
                break;
            case INPUT_KEY_USER_ID_VOLDOWN:
                ESP_LOGI(TAG, "[ * ] [long Vol-] Previous");
                periph_bt_avrc_prev(bt_periph);
                break;
        }

    }
    return ESP_OK;
}
esp_periph_set_handle_t set;
audio_event_iface_handle_t evt;
void BT_KL30_Wakeup_Init(void)
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES)
    {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }



    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set(TAG, ESP_LOG_DEBUG);

    ESP_LOGI(TAG, "[ 1 ] Create Bluetooth service");
    bluetooth_service_cfg_t bt_cfg_service = {
        .device_name = "YEDEA-C011-L",
        .mode = BLUETOOTH_A2DP_SINK,
        .user_callback.user_avrc_ct_cb = bt_app_avrc_ct_cb,
    };
    bluetooth_service_start(&bt_cfg_service);
    esp_hf_client_register_callback(bt_hf_client_cb);
    esp_hf_client_init();

    // ESP_LOGI(TAG, "[ 2 ] Start codec chip");
    // audio_board_handle_t board_handle = audio_board_init();
    // audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START);

    // ESP_LOGI(TAG, "[ 3 ] Create audio pipeline for playback");
    // audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    // pipeline_d = audio_pipeline_init(&pipeline_cfg);
    // pipeline_e = audio_pipeline_init(&pipeline_cfg);

//     ESP_LOGI(TAG, "[3.1] Create i2s stream to write data to codec chip and read data from codec chip");
//     i2s_stream_cfg_t i2s_cfg1 = I2S_STREAM_CFG_DEFAULT();
//     i2s_cfg1.type = AUDIO_STREAM_WRITER;
//     i2s_stream_writer = i2s_stream_init(&i2s_cfg1);

//     i2s_stream_cfg_t i2s_cfg2 = I2S_STREAM_CFG_DEFAULT();
//     i2s_cfg2.type = AUDIO_STREAM_READER;
// #if defined CONFIG_ESP_LYRAT_MINI_V1_1_BOARD
//     i2s_cfg2.i2s_port = 1;
//     i2s_cfg2.i2s_config.use_apll = false;
// #endif
//     i2s_stream_reader = i2s_stream_init(&i2s_cfg2);

//     raw_stream_cfg_t raw_cfg = RAW_STREAM_CFG_DEFAULT();
//     raw_cfg.type = AUDIO_STREAM_READER;
//     raw_read = raw_stream_init(&raw_cfg);

//     ESP_LOGI(TAG, "[4.1] Get Bluetooth stream");
//     a2dp_stream_config_t a2dp_config = {
//         .type = AUDIO_STREAM_READER,
//         .user_callback = {0},
// #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0))
//         .audio_hal = board_handle->audio_hal,
// #endif
//     };
//    bt_stream_reader = a2dp_stream_init(&a2dp_config);







// #if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
//     rsp_filter_cfg_t rsp_d_cfg = DEFAULT_RESAMPLE_FILTER_CONFIG();
//     audio_element_handle_t filter_d = rsp_filter_init(&rsp_d_cfg);
//     audio_pipeline_register(pipeline_d, filter_d, "filter_d");

//     rsp_filter_cfg_t rsp_e_cfg = DEFAULT_RESAMPLE_FILTER_CONFIG();
//     rsp_e_cfg.src_rate = 48000;
//     rsp_e_cfg.src_ch = 2;
//     rsp_e_cfg.dest_rate = HFP_RESAMPLE_RATE;
//     rsp_e_cfg.dest_ch = 1;
//     audio_element_handle_t filter_e = rsp_filter_init(&rsp_e_cfg);
//     audio_pipeline_register(pipeline_e, filter_e, "filter_e");
// #endif

//     ESP_LOGI(TAG, "[3.3] Register all elements to audio pipeline");
//     audio_pipeline_register(pipeline_d, bt_stream_reader, "bt");
//     audio_pipeline_register(pipeline_d, i2s_stream_writer, "i2s_w");

//     audio_pipeline_register(pipeline_e, i2s_stream_reader, "i2s_r");
//     audio_pipeline_register(pipeline_e, raw_read, "raw");

//     ESP_LOGI(TAG, "[3.4] Link it together [Bluetooth]-->bt_stream_reader-->i2s_stream_writer-->[codec_chip]");
// #if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
//     const char *link_d[3] = {"bt", "filter_d", "i2s_w"};
//     audio_pipeline_link(pipeline_d, &link_d[0], 3);

//     const char *link_e[3] = {"i2s_r", "filter_e", "raw"};
//     audio_pipeline_link(pipeline_e, &link_e[0], 3);
// #else
//     const char *link_d[2] = {"bt", "i2s_w"};
//     audio_pipeline_link(pipeline_d, &link_d[0], 2);

//     const char *link_e[2] = {"i2s_r", "raw"};
//     audio_pipeline_link(pipeline_e, &link_e[0], 2);
// #endif

    ESP_LOGI(TAG, "[ 4 ] Initialize peripherals");
    esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
    set = esp_periph_set_init(&periph_cfg);

    // ESP_LOGI(TAG, "[4.1] Initialize Touch peripheral");
    // audio_board_key_init(set);



    // ESP_LOGI(TAG, "[ 5.1 ] Create and start input key service");
    // input_key_service_info_t input_key_info[] = INPUT_KEY_DEFAULT_INFO();
    // input_key_service_cfg_t input_cfg = INPUT_KEY_SERVICE_DEFAULT_CONFIG();
    // input_cfg.handle = set;
    // periph_service_handle_t input_ser = input_key_service_create(&input_cfg);
    // input_key_service_add_key(input_ser, input_key_info, INPUT_KEY_NUM);
    // periph_service_set_callback(input_ser, input_key_service_cb, NULL);


    ESP_LOGI(TAG, "[4.2] Create Bluetooth peripheral");
    bt_periph = bluetooth_service_create_periph();

    ESP_LOGI(TAG, "[4.2] Start all peripherals");
    esp_periph_start(set, bt_periph);

    // ESP_LOGI(TAG, "[ 5 ] Set up  event listener");
    // audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
    // evt = audio_event_iface_init(&evt_cfg);

    // ESP_LOGI(TAG, "[5.1] Listening event from all elements of pipeline");
    // audio_pipeline_set_listener(pipeline_d, evt);

    // ESP_LOGI(TAG, "[5.2] Listening event from peripherals");
    // audio_event_iface_set_listener(esp_periph_set_get_event_iface(set), evt);

    // ESP_LOGI(TAG, "[ 6 ] Start audio_pipeline");
    // audio_pipeline_run(pipeline_d);
    // audio_pipeline_run(pipeline_e);

    // ESP_LOGI(TAG, "[ 7 ] Listen for all pipeline events");





    xTaskCreatePinnedToCore(test_Tasks, "test_Tasks", 1024 * 4, NULL, 6, NULL, 0);

    ESP_LOGI(TAG, "[ 8 ] test_Tasks");
}

void BT_Sleep_Init(void)
{
    ESP_LOGI(TAG, "[ 8 ] Stop audio_pipeline");
    audio_pipeline_stop(pipeline_d);
    audio_pipeline_wait_for_stop(pipeline_d);
    audio_pipeline_terminate(pipeline_d);
    audio_pipeline_stop(pipeline_e);
    audio_pipeline_wait_for_stop(pipeline_e);
    audio_pipeline_terminate(pipeline_e);

    audio_pipeline_unregister(pipeline_d, bt_stream_reader);
    audio_pipeline_unregister(pipeline_d, i2s_stream_writer);

    audio_pipeline_unregister(pipeline_e, i2s_stream_reader);
    audio_pipeline_unregister(pipeline_e, raw_read);

#if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
    audio_pipeline_unregister(pipeline_d, filter_d);
    audio_pipeline_unregister(pipeline_e, filter_e);
#endif
    /* Terminate the pipeline before removing the listener */
    audio_pipeline_remove_listener(pipeline_d);

    /* Stop all peripherals before removing the listener */
    esp_periph_set_stop_all(set);
    audio_event_iface_remove_listener(esp_periph_set_get_event_iface(set), evt);

    /* Make sure audio_pipeline_remove_listener & audio_event_iface_remove_listener are called before destroying event_iface */
    audio_event_iface_destroy(evt);

    /* Release all resources */
    audio_pipeline_deinit(pipeline_d);
    audio_element_deinit(bt_stream_reader);
    audio_element_deinit(i2s_stream_writer);
    audio_element_deinit(i2s_stream_reader);
    audio_element_deinit(raw_read);
#if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
    audio_element_deinit(filter_d);
    audio_element_deinit(filter_e);
#endif
    esp_periph_set_destroy(set);
    bluetooth_service_destroy();
}
