#include <stdio.h>
#include "string.h"

#include "t1001.h"

#include "controller/ll.h"
#include "common/bt_buf.h"
#include "host/att.h"

#include "omw_dbg.h"
#include "omw_ver.h"

#define LOG_MODULE_NAME bt_init
#include "bt_log.h"


uint8_t __dyn_ram[OMW_DATA_BUF_SIZE] __aligned(4);

simple_ram_pool_t g_ram_pool;

void bt_buf_pool_init(simple_ram_pool_t* ram_pool)
{
    LOG_DBG("bt_buf_pool_init");
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
    LOG_DBG("hci_evt_pool");
    SIMPLE_BUF_POOL_PTR_RAM_POOL_INIT(hci_evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, BT_BUF_EVT_SIZE(CONFIG_BT_BUF_EVT_RX_SIZE), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
    LOG_DBG("hci_cmd_pool");
    SIMPLE_BUF_POOL_PTR_RAM_POOL_INIT(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
#if defined(CONFIG_BT_CONN)
    LOG_DBG("hci_acl_in_pool");
    SIMPLE_BUF_POOL_PTR_RAM_POOL_INIT(hci_acl_in_pool, CONFIG_BT_BUF_ACL_RX_COUNT, BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
    LOG_DBG("hci_acl_out_pool");
    SIMPLE_BUF_POOL_PTR_RAM_POOL_INIT(hci_acl_out_pool, CONFIG_BT_BUF_ACL_TX_COUNT, BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_TX_SIZE), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
#endif

#if defined(CONFIG_BT_CONN)
#define NUM_COMLETE_EVENT_SIZE                                                                     \
    BT_BUF_SIZE(sizeof(struct bt_hci_evt_hdr) +                                                    \
                sizeof(struct bt_hci_cp_host_num_completed_packets) +                              \
                CONFIG_BT_CONN * sizeof(struct bt_hci_handle_count))
    LOG_DBG("num_complete_pool");
    SIMPLE_BUF_POOL_PTR_RAM_POOL_INIT(num_complete_pool, 1, NUM_COMLETE_EVENT_SIZE, ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
#endif
}


#define PDU_TX_DATA_CNT    (CONFIG_BT_CTRL_DATA_TX_BUFFERS)
#define PDU_TX_LL_CNT        (CONFIG_BT_CTRL_TX_BUFFERS)

#define ADV_RX_CNT    (CONFIG_BT_CTRL_RX_BUFFERS)
#define PDU_RX_DATA_CNT        (CONFIG_BT_CTRL_DATA_RX_BUFFERS)
void ll_buf_pool_init(simple_ram_pool_t* ram_pool)
{
    LOG_DBG("ll_buf_pool_init");



    LOG_DBG("adv_rx_free");
    SIMPLE_POOL_PTR_RAM_POOL_INIT(adv_rx_free, ADV_RX_CNT, sizeof(struct node_rx_pdu_sub_adv), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);

    LOG_DBG("pdu_data_rx_free");
    SIMPLE_POOL_PTR_RAM_POOL_INIT(pdu_data_rx_free, PDU_RX_DATA_CNT, sizeof(struct node_rx_pdu_sub_data), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);

    LOG_DBG("pdu_data_tx_free");
    SIMPLE_POOL_PTR_RAM_POOL_INIT(pdu_data_tx_free, PDU_TX_DATA_CNT, sizeof(struct node_tx_pdu_sub_data), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);

    LOG_DBG("pdu_ctrl_tx_free");
    SIMPLE_POOL_PTR_RAM_POOL_INIT(pdu_ctrl_tx_free, PDU_TX_LL_CNT, sizeof(struct node_tx_pdu_sub_ctrl), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);

    #define MSG_BUFFER_CNT 20
    LOG_DBG("msg_fifo");
    SIMPLE_DATA_FIFO_PTR_RAM_POOL_INIT(msg_fifo, MSG_BUFFER_CNT, sizeof(struct ll_msg_node), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
}

void bt_att_pool_init(simple_ram_pool_t* ram_pool)
{
    LOG_DBG("bt_att_pool_init");
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);

    LOG_DBG("att_req_pool");
    SIMPLE_POOL_PTR_RAM_POOL_INIT(att_req_pool, CONFIG_BT_BUF_ACL_TX_COUNT, sizeof(struct bt_att_req), ram_pool);
    LOG_DBG("ram_pool, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
}

void bt_buf_init(uint8_t* ram_start, uint16_t ram_size)
{
    simple_ram_pool_t* ram_pool = &g_ram_pool;
    simple_ram_pool_init(ram_pool, ram_start, ram_size);

    bt_buf_pool_init(ram_pool);
    ll_buf_pool_init(ram_pool);
    bt_att_pool_init(ram_pool);

    // check pool total len.
    if(ram_pool->offset >= ram_pool->total_len)
    {
        LOG_ERR("ram_pool overflow, base_addr: 0x%x, offset: 0x%x, total_len: 0x%x", ram_pool->base_addr, ram_pool->offset, ram_pool->total_len);
        while(1);
    }
}

void bt_buf_init_ext(void)
{
    bt_buf_init(__dyn_ram, sizeof(__dyn_ram));
}

const char * omw_svc_get_cpt()
{
    return OMW_COMPILE_TIME;
}