/***************************************************************************
 *
 * Copyright 2015-2019 BES.
 * All rights reserved. All unpublished rights reserved.
 *
 * No part of this work may be used or reproduced in any form or by any
 * means, or stored in a database or retrieval system, without prior written
 * permission of BES.
 *
 * Use of this work is governed by a license granted by BES.
 * This work contains confidential and proprietary information of
 * BES. which is protected by copyright, trade secret,
 * trademark and other intellectual property rights.
 *
 ****************************************************************************/
#include <stdio.h>
#include "cmsis_os.h"
#include "hal_uart.h"
#include "hal_timer.h"
#include "audioflinger.h"
#include "lockcqueue.h"
#include "hal_trace.h"
#include "hal_cmu.h"
#include "analog.h"
#include "app.h"
#include "bt_drv.h"
#include "app_audio.h"
#include "bluetooth.h"
#include "nvrecord.h"
#include "nvrecord_env.h"
#include "nvrecord_dev.h"
#include "hal_location.h"
#include "a2dp_api.h"
#if defined(NEW_NV_RECORD_ENABLED)
#include "nvrecord_bt.h"
#endif

#include "a2dp_api.h"
#include "avrcp_api.h"
#include "besbt.h"

#include "cqueue.h"
#include "app_bt.h"
#include "apps.h"
#include "resources.h"
#include "app_bt_media_manager.h"
#include "tgt_hardware.h"
#include "bt_drv_interface.h"
#include "hci_api.h"

#define _FILE_TAG_ "A2DP"
#include "color_log.h"
#include "app_bt_func.h"
#include "os_api.h"

#if (A2DP_DECODER_VER >= 2)
#include "a2dp_decoder.h"
#endif

#include "btapp.h"
#include "app_a2dp_codecs.h"
#include "app_a2dp.h"

extern struct BT_DEVICE_T  app_bt_device;

int a2dp_codec_source_init(void)
{
    struct BT_DEVICE_T POSSIBLY_UNUSED *bt_dev = &app_bt_device;

#if defined(APP_LINEIN_A2DP_SOURCE)||defined(APP_I2S_A2DP_SOURCE)
    if(bt_dev->src_or_snk == BT_DEVICE_SRC)
    {
        a2dp_avdtpcodec.codecType = BTIF_AVDTP_CODEC_TYPE_SBC;
        a2dp_avdtpcodec.discoverable = 1;
        a2dp_avdtpcodec.elements = (U8 *)&a2dp_codec_elements;
        a2dp_avdtpcodec.elemLen  = 4;
        btif_a2dp_register(bt_dev->a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream, BTIF_A2DP_STREAM_TYPE_SOURCE, &a2dp_avdtpcodec, NULL, 0,0, a2dp_callback);
    }
#endif

    return 0;
}

int a2dp_codec_sink_init(void)
{
    int i;
    struct BT_DEVICE_T POSSIBLY_UNUSED *bt_dev = &app_bt_device;

#if defined(APP_LINEIN_A2DP_SOURCE)||defined(APP_I2S_A2DP_SOURCE)
    if(bt_dev->src_or_snk != BT_DEVICE_SRC)
#endif
    {
        for(i = 0; i < BT_DEVICE_NUM; i++)
        {
            a2dp_codec_sbc_init(i);
#if defined(A2DP_AAC_ON)
            a2dp_codec_aac_init(i);
#endif
#if defined(A2DP_LDAC_ON)
            a2dp_codec_ldac_init(i);
#endif
#if defined(A2DP_LHDC_ON)
            a2dp_codec_lhdc_init(i);
#endif
#if defined(MASTER_USE_OPUS) || defined(ALL_USE_OPUS)
            a2dp_codec_opus_init(i);
#endif
#if defined(A2DP_SCALABLE_ON)
            a2dp_codec_scalable_init(i);
#endif
        }
    }

    return 0;
}

uint8_t a2dp_codec_confirm_stream_state(uint8_t index, uint8_t old_state, uint8_t new_state)
{
    btif_a2dp_confirm_stream_state(app_bt_device.a2dp_stream[index]->a2dp_stream, old_state, new_state);
#if defined(A2DP_AAC_ON)
    btif_a2dp_confirm_stream_state(app_bt_device.a2dp_aac_stream[index]->a2dp_stream, old_state, new_state);
#endif
#if defined(A2DP_LHDC_ON)
    btif_a2dp_confirm_stream_state(app_bt_device.a2dp_lhdc_stream[index]->a2dp_stream, old_state, new_state);
#endif
#if defined(A2DP_SCALABLE_ON)
    btif_a2dp_confirm_stream_state(app_bt_device.a2dp_scalable_stream[index]->a2dp_stream, old_state, new_state);
#endif
#if defined(A2DP_LDAC_ON)
    btif_a2dp_confirm_stream_state(app_bt_device.a2dp_ldac_stream[index]->a2dp_stream, old_state, new_state);
#endif

    return 0;
}

static void a2dp_set_codec_info(btif_dev_it_e dev_num, const uint8_t *codec)
{
    app_bt_device.codec_type[dev_num] = codec[0];
    app_bt_device.sample_bit[dev_num] = codec[1];
    app_bt_device.sample_rate[dev_num]= codec[2];
#if defined(A2DP_LHDC_ON)
    app_bt_device.a2dp_lhdc_llc[dev_num] = codec[3];
#endif
#if defined(A2DP_LDAC_ON)
    app_ibrt_restore_ldac_info(app_bt_device.sample_rate[dev_num]);
#endif

}

static void a2dp_get_codec_info(btif_dev_it_e dev_num, uint8_t *codec)
{
    codec[0] = app_bt_device.codec_type[dev_num];
    codec[1] = app_bt_device.sample_bit[dev_num];
    codec[2] = app_bt_device.sample_rate[dev_num];
#if defined(A2DP_LHDC_ON)
    codec[3] = app_bt_device.a2dp_lhdc_llc[dev_num];
#endif
}

int a2dp_codec_init(void)
{
    a2dp_codec_source_init();
    a2dp_codec_sink_init();
    btif_a2dp_get_codec_info_func(a2dp_get_codec_info);
    btif_a2dp_set_codec_info_func(a2dp_set_codec_info);
    return 0;
}

btif_avdtp_codec_t * app_a2dp_codec_get_avdtp_codec()
{
    return (btif_avdtp_codec_t *)&a2dp_avdtpcodec;
}

#if defined(IBRT)
enum AUD_SAMPRATE_T bt_parse_sbc_sample_rate(uint8_t sbc_samp_rate);
uint32_t app_a2dp_codec_parse_aac_sample_rate(const a2dp_callback_parms_t *info)
{
    uint32_t ret_sample_rate = AUD_SAMPRATE_44100;
    btif_a2dp_callback_parms_t *p_info = (btif_a2dp_callback_parms_t *) info;

    if (p_info->p.configReq->codec.elements[1] & A2DP_AAC_OCTET1_SAMPLING_FREQUENCY_44100)
    {
        ret_sample_rate = AUD_SAMPRATE_44100;
    }
    else if (p_info->p.configReq->codec.elements[2] & A2DP_AAC_OCTET2_SAMPLING_FREQUENCY_48000)
    {
        ret_sample_rate = AUD_SAMPRATE_48000;
    }
    return ret_sample_rate;
}
uint32_t app_a2dp_codec_parse_aac_lhdc_sample_rate(const a2dp_callback_parms_t * info)
{
    btif_a2dp_callback_parms_t *p_info = (btif_a2dp_callback_parms_t *) info;

    switch (A2DP_LHDC_SR_DATA(p_info->p.configReq->codec.elements[6]))
    {
        case A2DP_LHDC_SR_96000:
            return AUD_SAMPRATE_96000;
        case A2DP_LHDC_SR_48000:
            return AUD_SAMPRATE_48000;
        case A2DP_LHDC_SR_44100:
            return AUD_SAMPRATE_44100;
        default:
            return AUD_SAMPRATE_44100;
    }
}
uint32_t app_a2dp_codec_get_sample_rate(const a2dp_callback_parms_t *info)
{
    btif_a2dp_callback_parms_t *p_info = (btif_a2dp_callback_parms_t *) info;
    btif_avdtp_codec_type_t codetype = btif_a2dp_get_codec_type((const a2dp_callback_parms_t *)p_info);

    switch(codetype)
    {
        case BTIF_AVDTP_CODEC_TYPE_SBC:
            return bt_parse_sbc_sample_rate(p_info->p.configReq->codec.elements[0]);
        case BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC:
            return app_a2dp_codec_parse_aac_sample_rate((const a2dp_callback_parms_t *)p_info);
        case BTIF_AVDTP_CODEC_TYPE_LHDC:
            return app_a2dp_codec_parse_aac_lhdc_sample_rate((const a2dp_callback_parms_t *)p_info);
        default:
            ASSERT(0,"btif_a2dp_get_sample_rate codetype error!!");
            return 0;
    }
}
uint8_t app_a2dp_codec_get_sample_bit(const a2dp_callback_parms_t *info)
{
    btif_avdtp_codec_type_t codetype = btif_a2dp_get_codec_type(info);
    btif_a2dp_callback_parms_t *p_info = (btif_a2dp_callback_parms_t *) info;

    if ((codetype == BTIF_AVDTP_CODEC_TYPE_LHDC) &&
        A2DP_LHDC_FMT_DATA(p_info->p.configReq->codec.elements[6]))
    {
        return 24;
    }
    else
    {
        //AAC and SBC sample bit eq 16
        return 16;
    }
}
#endif
