#include "include.h"
#include "ab_link.h"

#if LE_APP_EN

#if LE_MASTER_SLAVE_TEST
// BIT[7:2]: unuse
// BIT[1]:   indicate
// BIT[0]:   notify
u8 battery_client_config = 0;
#endif // LE_MASTER_SLAVE_TEST

//----------------------------------------------------------------------------
// BLE advertisement and scan
//----------------------------------------------------------------------------
const uint8_t adv_data_const[] = {
    // Flags general discoverable, BR/EDR not supported
    0x02, 0x01, 0x18,
    // Manufacturer Specific Data
    0x03, 0xff, 0x42, 0x06,
    // Complete Local Name
    0x06, 0x09, 'G', 'e', 'e', 'h', 'y',
};

const uint8_t scan_data_const[] = {
    // Name
    0x08, 0x09, 'P', 'r', 'i', 'n', 't', 'e', 'r',
};

u32 ble_get_scan_data(u8 *scan_buf, u32 buf_size)
{
    memset(scan_buf, 0, buf_size);
    u32 data_len = sizeof(scan_data_const);
    memcpy(scan_buf, scan_data_const, data_len);

    //Read the Bluetooth name configured by BLE
    int len;
    len = strlen(xcfg_cb.le_name);
    if (len > 0) {
        memcpy(&scan_buf[2], xcfg_cb.le_name, len);
        data_len = 2 + len;
        scan_buf[0] = len + 1;
    }
    return data_len;
}

u32 ble_get_adv_data(u8 *adv_buf, u32 buf_size)
{
    memset(adv_buf, 0, buf_size);
    u32 data_len = sizeof(adv_data_const);
    memcpy(adv_buf, adv_data_const, data_len);

    //Read the Bluetooth name configured by BLE
    int len;
    len = strlen(xcfg_cb.le_name);
    if (len > 0) {
        memcpy(&adv_buf[9], xcfg_cb.le_name, len);
        adv_buf[7] = len + 1;
        data_len = 9 + len;
    }
    return data_len;
}


//----------------------------------------------------------------------------
// BLE TX memory pool
//----------------------------------------------------------------------------
#define MAX_NOTIFY_NUM          8       //4
#define MAX_NOTIFY_LEN          256     //512
#define NOTIFY_POOL_SIZE       (MAX_NOTIFY_LEN + sizeof(struct txbuf_tag)) * MAX_NOTIFY_NUM

AT(.ble_tx_buff.att)
uint8_t notify_tx_pool[NOTIFY_POOL_SIZE];

void ble_txpkt_init(void)
{
    txpkt_init(&notify_tx, notify_tx_pool, MAX_NOTIFY_NUM, MAX_NOTIFY_LEN);
    notify_tx.send_kick = ble_send_kick;
}


//----------------------------------------------------------------------------
// BLE service define
//----------------------------------------------------------------------------
//Printer service   1
const uint8_t printer_primay_uuid16[16]={0x10, 0xff};
static const gatts_uuid_base_st uuid_printer_primay_base = {
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = printer_primay_uuid16,
};

const uint8_t printer_write_uuid16[16]={0xf1, 0xff};
static const gatts_uuid_base_st uuid_printer_write_base = {
    .props = ATT_WRITE|ATT_WRITE_WITHOUT_RESPONSE,
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = printer_write_uuid16,
};
static gatts_service_base_st gatts_printer_write_base;

const uint8_t printer_notify_uuid16[16]={0xf2, 0xff};
static const gatts_uuid_base_st uuid_printer_notify_base = {
    .props = ATT_NOTIFY,
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = printer_notify_uuid16,
};
static gatts_service_base_st gatts_printer_notify_base;

//Printer service   2
const uint8_t printer2_primay_uuid16[16]={0x55, 0xe4, 0x05, 0xd2, 0xaf, 0x9f, 0xa9, 0x8f, 0xe5, 0x4a, 0x7d, 0xfe, 0x43, 0x53, 0x53, 0x49 };
static const gatts_uuid_base_st uuid_printer2_primay_base = {
    .type = BLE_GATTS_UUID_TYPE_128BIT,
    .uuid = printer2_primay_uuid16,
};

const uint8_t printer2_write_uuid16[16]={0xb3, 0x9b, 0x72, 0x34, 0xbe, 0xec, 0xd4, 0xa8, 0xf4, 0x43, 0x41, 0x88, 0x43, 0x53, 0x53, 0x49 };

static const gatts_uuid_base_st uuid_printer2_write_base = {
    .props = ATT_WRITE|ATT_WRITE_WITHOUT_RESPONSE,
    .type = BLE_GATTS_UUID_TYPE_128BIT,
    .uuid = printer2_write_uuid16,
};
static gatts_service_base_st gatts_printer2_write_base;

const uint8_t printer2_notify_uuid16[16]={0x16, 0x96, 0x24, 0x47, 0xc6, 0x23, 0x61, 0xba, 0xd9, 0x4b, 0x4d, 0x1e, 0x43, 0x53, 0x53, 0x49 };
static const gatts_uuid_base_st uuid_printer2_notify_base = {
    .props = ATT_NOTIFY|ATT_READ,
    .type = BLE_GATTS_UUID_TYPE_128BIT,
    .uuid = printer2_notify_uuid16,
};
static gatts_service_base_st gatts_printer2_notify_base;

//app service
const uint8_t app_primay_uuid16[16]={0x12, 0xff};
static const gatts_uuid_base_st uuid_app_primay_base = {
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = app_primay_uuid16,
};

const uint8_t app_write_uuid16[16]={0x13, 0xff};
static const gatts_uuid_base_st uuid_app_write_base = {
    .props = ATT_WRITE,
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = app_write_uuid16,
};
static gatts_service_base_st gatts_app_write_base;

const uint8_t app_notify_uuid16[16]={0x14, 0xff};
static const gatts_uuid_base_st uuid_app_notify_base = {
    .props = ATT_NOTIFY,
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = app_notify_uuid16,
};
static gatts_service_base_st gatts_app_notify_base;

#if LE_MASTER_SLAVE_TEST
//Generic Attribute service
const uint8_t gatt_primay_uuid16[2]={0x01, 0x18};
static const gatts_uuid_base_st uuid_gatt_primay_base = {
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = gatt_primay_uuid16,
};

const uint8_t service_change_uuid16[2]={0x05, 0x2A};
static const gatts_uuid_base_st uuid_service_change_base = {
    .props = ATT_INDICATE,
    .type = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid = service_change_uuid16,
};
static gatts_service_base_st gatts_service_change_base;

bool ble_service_change_indicate(void)
{
    u16 start_handle = 0x01;
    u16 end_handle = 0xffff;

    u8 buf[4];

    memcpy(buf, &start_handle, 2);
    memcpy(&buf[2], &end_handle, 2);

    return ble_tx_indication(gatts_service_change_base.att_index, buf, 4);
}
#endif // LE_MASTER_SLAVE_TEST

//----------------------------------------------------------------------------
// APP
//----------------------------------------------------------------------------
bool ble_send_packet1(u8 *buf, u8 len)
{
    return ble_tx_notify(gatts_printer_notify_base.att_index, buf, len);
}
bool ble_send_packet2(u8 *buf, u16 len)
{
    return ble_tx_notify(gatts_printer2_notify_base.att_index, buf, len);
}

/**蓝牙转串口例程宏定义**/
#define BT_Huart 0  //如果是其它例程就给0，蓝牙转串口给1
/*************/
static uint8_t gatt_callback_app(u8 *ptr, u16 len)
{
#if BT_Huart == 1
    hsuart_dma_start(HSUT_TRANSMIT, (uint32_t)ptr, len);
#else
    print_r(ptr, len);
//    printf("BLE_rec:[%x]%x %x...%x\n",len,ptr[0],ptr[1],ptr[len-1]);        /*Test serial port*/
#endif
    return false;
}
/**********/

u32 str = 0;
void ble_read_value(void)
{
    str++;
    ble_init_att_for_handle(gatts_printer2_notify_base.handle,&str,4);
}

void bsp_ble_process(void)
{
}

//----------------------------------------------------------------------------
// FOTA
//----------------------------------------------------------------------------
#if LE_APP_FOT_EN
const uint8_t fota_uuid16[16]={0x15, 0xff};
static const gatts_uuid_base_st uuid_fota_base = {
    .props = ATT_READ|ATT_WRITE_WITHOUT_RESPONSE,
    .type  = BLE_GATTS_UUID_TYPE_16BIT,
    .uuid  = fota_uuid16,
};
static gatts_service_base_st gatts_fota_base;

static u8 gatt_callback_fota(u8 *ptr, u16 len)
{
    if(fot_app_connect_auth(ptr,len)){
        fot_recv_proc(ptr,len);
    }
    return true;
}

bool ble_fot_send_packet(u8 *buf, u8 len)
{
    return ble_tx_notify(gatts_app_notify_base.att_index, buf, len);
}
#endif


//----------------------------------------------------------------------------
// Initialization
//----------------------------------------------------------------------------
void ble_app_gatts_service_init(void)
{
    int ret = 0;

    ble_gatts_init();

    //Print Service
    ret = ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                               uuid_printer_primay_base.uuid,
                               uuid_printer_primay_base.type,
                               NULL);            //PRIMARY

    ret = ble_gatts_characteristic_add(uuid_printer_write_base.uuid,
                                      uuid_printer_write_base.type,
                                      uuid_printer_write_base.props,
                                      &gatts_printer_write_base.handle,
                                      &gatts_printer_write_base.att_index,
                                      &gatt_callback_app);      //characteristic

    ret = ble_gatts_characteristic_add(uuid_printer_notify_base.uuid,
                                      uuid_printer_notify_base.type,
                                      uuid_printer_notify_base.props,
                                      &gatts_printer_notify_base.handle,
                                      &gatts_printer_notify_base.att_index,
                                      NULL);      //characteristic

    //Print2 Service
    ret = ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                               uuid_printer2_primay_base.uuid,
                               uuid_printer2_primay_base.type,
                               NULL);            //PRIMARY

    ret = ble_gatts_characteristic_add(uuid_printer2_write_base.uuid,
                                      uuid_printer2_write_base.type,
                                      uuid_printer2_write_base.props,
                                      &gatts_printer2_write_base.handle,
                                      &gatts_printer2_write_base.att_index,
                                      &gatt_callback_app);      //characteristic

    ret = ble_gatts_characteristic_add(uuid_printer2_notify_base.uuid,
                                      uuid_printer2_notify_base.type,
                                      uuid_printer2_notify_base.props,
                                      &gatts_printer2_notify_base.handle,
                                      &gatts_printer2_notify_base.att_index,
                                      NULL);      //characteristic

    //APP Service
    ret = ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                uuid_app_primay_base.uuid,
                                uuid_app_primay_base.type,
                                NULL);            //PRIMARY

    ret = ble_gatts_characteristic_add(uuid_app_write_base.uuid,
                                       uuid_app_write_base.type,
                                       uuid_app_write_base.props,
                                       &gatts_app_write_base.handle,
                                       &gatts_app_write_base.att_index,
                                       &gatt_callback_app);      //characteristic

    ret = ble_gatts_characteristic_add(uuid_app_notify_base.uuid,
                                       uuid_app_notify_base.type,
                                       uuid_app_notify_base.props,
                                       &gatts_app_notify_base.handle,
                                       &gatts_app_notify_base.att_index,
                                       NULL);      //characteristic

#if LE_FOT_EN
    ret = ble_gatts_characteristic_add(uuid_fota_base.uuid,
                                       uuid_fota_base.type,
                                       uuid_fota_base.props,
                                       &gatts_fota_base.handle,
                                       &gatts_fota_base.att_index,
                                       &gatt_callback_fota);      //characteristic
#endif

#if LE_MASTER_SLAVE_TEST
    ret = ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                uuid_gatt_primay_base.uuid,
                                uuid_gatt_primay_base.type,
                                NULL);            //PRIMARY

    ret = ble_gatts_characteristic_add(uuid_service_change_base.uuid,
                                       uuid_service_change_base.type,
                                       uuid_service_change_base.props,
                                       &gatts_service_change_base.handle,
                                       &gatts_service_change_base.att_index,
                                       NULL);      //characteristic
#endif //LE_MASTER_SLAVE_TEST

    if(ret != BLE_GATTS_SUCCESS){
        printf("gatt err: %d\n", ret);
        return;
    }
}

void ble_app_init(void)
{
    ble_app_gatts_service_init();
}

#if LE_MASTER_SLAVE_TEST
void ble_client_cfg_callback(u16 handle, u16 cfg)
{
    if(handle == gatts_service_change_base.handle){
        if(cfg){
            ble_service_change_indicate();
        }
    }

    if (handle == gatts_printer_notify_base.handle) {
        if (cfg) {
            printf("battery client configure: %x\n", cfg);
            battery_client_config = cfg;
        }
    }
}

void ble_disconnect_event_process(void)
{
    battery_client_config = 0;
}



void ble_slave_process(void)
{
    if (gpio_read_bit(GPIOB_REG, GPIO_PIN_5) == RESET)
    {
        delay_ms(100);
        printf("key is down\n");
        if (battery_client_config & BIT(0))
        {
            if(ble_get_status() == LE_STA_CONNECTION)
            {
                u8 tmp[6] = {'G', 'W', '3', '3', '2', '3'};
                ble_tx_notify(gatts_printer_notify_base.att_index, tmp, 6);
            }
        }
    }
}
#endif // LE_MASTER_SLAVE_TEST
#endif // LE_APP_EN
