/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    Copyright (c) 2020 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *          Provides an implementation of the BLEManager singleton object
 *          for the PSoC6 platform.
 */

/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE

#include <ble/Ble.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/internal/BLEManager.h>

extern "C" {
#include "app_platform_cfg.h"
#include "cycfg_bt_settings.h"
#include "cycfg_gatt_db.h"
}

#include "cy_utils.h"
#include "wiced_bt_stack.h"

#include "wiced_memory.h"
#include <wiced_bt_ble.h>
#include <wiced_bt_gatt.h>

using namespace ::chip;
using namespace ::chip::Ble;

#define BLE_SERVICE_DATA_SIZE 10
#define BT_STACK_HEAP_SIZE (1024 * 6)
typedef void (*pfn_free_buffer_t)(uint8_t *);
wiced_bt_heap_t * p_heap   = NULL;
static bool heap_allocated = false;

namespace chip {
namespace DeviceLayer {
namespace Internal {

namespace {
const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                 0x9D, 0x11 } };

const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
                                                 0x9D, 0x12 } };

} // unnamed namespace

BLEManagerImpl BLEManagerImpl::sInstance;

wiced_bt_gatt_status_t app_gatts_callback(wiced_bt_gatt_evt_t event, wiced_bt_gatt_event_data_t * p_data);

wiced_result_t BLEManagerImpl::BLEManagerCallback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t * p_event_data)
{
    switch (event)
    {
    case BTM_ENABLED_EVT:
        // Post a event to _OnPlatformEvent.
        {
            // Register with stack to receive GATT callback
            wiced_bt_gatt_register(app_gatts_callback);

            // Inform the stack to use this app GATT database
            wiced_bt_gatt_db_init(gatt_database, gatt_database_len, NULL);

            ChipDeviceEvent bleEvent;
            bleEvent.Type = DeviceEventType::kP6BLEEnabledEvt;
            if (PlatformMgr().PostEvent(&bleEvent) != CHIP_NO_ERROR)
            {
                return WICED_BT_ERROR;
            }
        }
        break;
    }

    return WICED_BT_SUCCESS;
}

uint8_t * BLEManagerImpl::gatt_alloc_buffer(uint16_t len)
{
    uint8_t * p = (uint8_t *) wiced_bt_get_buffer(len);
    return p;
}

void BLEManagerImpl::gatt_free_buffer(uint8_t * p_data)
{
    wiced_bt_free_buffer(p_data);
}

static void gatt_free_buffer_cb(uint8_t * p_data)
{
    BLEManagerImpl::sInstance.gatt_free_buffer(p_data);
}

CHIP_ERROR BLEManagerImpl::_Init()
{
    CHIP_ERROR err;

    // Initialize the CHIP BleLayer.
    err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
    SuccessOrExit(err);

    // Configure platform specific settings for Bluetooth
    cybt_platform_config_init(&bt_platform_cfg_settings);

    // Initialize the Bluetooth stack with a callback function and stack
    // configuration structure */
    if (WICED_SUCCESS != wiced_bt_stack_init(BLEManagerCallback, &wiced_bt_cfg_settings))
    {
        ChipLogError(DeviceLayer, "Error initializing BT stack\n");
        CY_ASSERT(0);
    }

    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
    if (CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART)
    {
        mFlags.Set(Flags::kFlag_AdvertisingEnabled, true);
    }
    else
    {
        mFlags.Set(Flags::kFlag_AdvertisingEnabled, false);
    }
    mNumCons = 0;
    memset(mCons, 0, sizeof(mCons));
    memset(mDeviceName, 0, sizeof(mDeviceName));

    ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete");

    PlatformMgr().ScheduleWork(DriveBLEState, 0);

exit:
    return err;
}

bool BLEManagerImpl::_IsAdvertisingEnabled(void)
{
    return mFlags.Has(Flags::kFlag_AdvertisingEnabled);
}

CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    if (mFlags.Has(Flags::kFlag_AdvertisingEnabled) != val)
    {
        mFlags.Set(Flags::kFlag_AdvertisingEnabled, val);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
{
    (void) (mode);

    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
{
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
    {
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }
    if (strlen(mDeviceName) >= bufSize)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    strcpy(buf, mDeviceName);
    ChipLogProgress(DeviceLayer, "Getting device name to : \"%s\"", mDeviceName);
    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
{
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
    {
        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }
    if (deviceName != NULL && deviceName[0] != 0)
    {
        if (strlen(deviceName) >= kMaxDeviceNameLength)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        Platform::CopyString(mDeviceName, deviceName);
        mFlags.Set(Flags::kFlag_DeviceNameSet, true);
        ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName);
    }
    else
    {
        wiced_bt_cfg_settings.device_name[0] = 0;
        mDeviceName[0]                       = 0;
        mFlags.Set(Flags::kFlag_DeviceNameSet, false);
    }

    return CHIP_NO_ERROR;
}

uint16_t BLEManagerImpl::_NumConnections(void)
{
    return mNumCons;
}

void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    switch (event->Type)
    {

    case DeviceEventType::kP6BLEEnabledEvt:
        mFlags.Set(Flags::kFlag_StackInitialized, true);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;

    case DeviceEventType::kCHIPoBLESubscribe:
        HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
        {
            ChipDeviceEvent _event;
            _event.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
            PlatformMgr().PostEventOrDie(&_event);
        }
        break;

    case DeviceEventType::kCHIPoBLEUnsubscribe:
        HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
        break;

    case DeviceEventType::kCHIPoBLEWriteReceived:
        HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
                            PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
        break;

    case DeviceEventType::kCHIPoBLEIndicateConfirm:
        HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
        break;

    case DeviceEventType::kCHIPoBLEConnectionError:
        HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
        break;

    case DeviceEventType::kServiceProvisioningChange:
        // Force the advertising state to be refreshed to reflect new provisioning state.
        mFlags.Set(Flags::kFlag_AdvertisingRefreshNeeded, true);

        DriveBLEState();
        break;

    default:
        break;
    }
}

bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
    return false;
}

bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
    return false;
}

bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
{
    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);

    // Initiate a GAP disconnect.
    wiced_bt_gatt_status_t gatt_err = wiced_bt_gatt_disconnect((uint16_t) conId);
    if (gatt_err != WICED_BT_GATT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "wiced_bt_gatt_disconnect() failed: %d", gatt_err);
    }

    return (gatt_err == WICED_BT_GATT_SUCCESS);
}

uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
{
    CHIPoBLEConState * p_conn;

    /* Check if target connection state exists. */
    p_conn = BLEManagerImpl::sInstance.GetConnectionState(conId);

    if (!p_conn)
    {
        return wiced_bt_cfg_settings.p_ble_cfg->ble_max_rx_pdu_size;
    }
    else
    {
        return p_conn->Mtu;
    }
}

bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                    PacketBufferHandle data)
{
    CHIP_ERROR err                  = CHIP_NO_ERROR;
    uint16_t dataLen                = data->DataLength();
    wiced_bt_gatt_status_t gatt_err = WICED_BT_GATT_SUCCESS;
    CHIPoBLEConState * conState     = GetConnectionState(conId);

    VerifyOrExit(conState != NULL, err = CHIP_ERROR_INVALID_ARGUMENT);

#ifdef BLE_DEBUG
    ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE TX characteristic (con %u, len %u)", conId, dataLen);
#endif

    // Send a indication for the CHIPoBLE TX characteristic to the client containing the supplied data.
    gatt_err =
        wiced_bt_gatt_server_send_indication((uint16_t) conId, HDLC_CHIP_SERVICE_CHAR_C2_VALUE, dataLen, data->Start(), NULL);

exit:
    if (gatt_err != WICED_BT_GATT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %d", gatt_err);
        return false;
    }
    return err == CHIP_NO_ERROR;
}

bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                      PacketBufferHandle data)

{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
    return false;
}

bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                     PacketBufferHandle data)
{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
    return false;
}

bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
                                      const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
    return false;
}

void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}

void BLEManagerImpl::DriveBLEState(void)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Exit if Stack not initialized
    VerifyOrExit(mFlags.Has(Flags::kFlag_StackInitialized), /* */);

    // Perform any initialization actions that must occur after the CHIP task is running.
    if (!mFlags.Has(Flags::kFlag_AsyncInitCompleted))
    {
        mFlags.Set(Flags::kFlag_AsyncInitCompleted, true);
    }

    // If the application has enabled CHIPoBLE and BLE advertising...
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
        mFlags.Has(Flags::kFlag_AdvertisingEnabled)
#if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
        // and no connections are active...
        && (mNumCons == 0)
#endif
    )
    {
        // Start/re-start SoftDevice advertising if not already advertising, or if the
        // advertising state of the SoftDevice needs to be refreshed.
        if (!mFlags.Has(Flags::kFlag_Advertising) || mFlags.Has(Flags::kFlag_AdvertisingRefreshNeeded))
        {
            ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");

            mFlags.Set(Flags::kFlag_Advertising, true);
            mFlags.Set(Flags::kFlag_AdvertisingRefreshNeeded, false);

            SetAdvertisingData();

            wiced_bt_start_advertisements(BTM_BLE_ADVERT_UNDIRECTED_HIGH, BLE_ADDR_PUBLIC, NULL);

            // Post a CHIPoBLEAdvertisingChange(Started) event.
            {
                ChipDeviceEvent advChange;
                advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
                advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
                err                                        = PlatformMgr().PostEvent(&advChange);
            }
        }
    }

    // Otherwise, stop advertising if currently active.
    else
    {
        if (mFlags.Has(Flags::kFlag_Advertising))
        {
            mFlags.Set(Flags::kFlag_Advertising, false);

            ChipLogProgress(DeviceLayer, "CHIPoBLE stop advertising");
            wiced_bt_start_advertisements(BTM_BLE_ADVERT_OFF, BLE_ADDR_PUBLIC, NULL);

            /* Delete the heap allocated during BLE Advertisement Stop */
            if (p_heap)
            {
                wiced_bt_delete_heap(p_heap);
                heap_allocated = false;
            }
        }
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
    }
}

/*
 * This function searches through the GATT DB to point to the attribute
 * corresponding to the given handle
 */
gatt_db_lookup_table_t * BLEManagerImpl::GetGattAttr(uint16_t handle)
{
    /* Search for the given handle in the GATT DB and return the pointer to the
    correct attribute */
    uint8_t array_index = 0;

    for (array_index = 0; array_index < app_gatt_db_ext_attr_tbl_size; array_index++)
    {
        if (app_gatt_db_ext_attr_tbl[array_index].handle == handle)
        {
            return (&app_gatt_db_ext_attr_tbl[array_index]);
        }
    }
    return NULL;
}

wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceRead(uint16_t conn_id, wiced_bt_gatt_opcode_t opcode,
                                                             wiced_bt_gatt_read_t * p_read_req, uint16_t len_requested)
{
    gatt_db_lookup_table_t * p_attribute;
    uint8_t * from;

    if ((p_attribute = GetGattAttr(p_read_req->handle)) == NULL)
    {
        ChipLogError(DeviceLayer, "[%s]  attr not found handle: 0x%04x\n", __FUNCTION__, p_read_req->handle);
        wiced_bt_gatt_server_send_error_rsp(conn_id, opcode, p_read_req->handle, WICED_BT_GATT_INVALID_HANDLE);
        return WICED_BT_GATT_INVALID_HANDLE;
    }

    if (p_read_req->offset >= p_attribute->cur_len)
    {
        ChipLogError(DeviceLayer, "[%s] offset:%d larger than attribute length:%d\n", __FUNCTION__, p_read_req->offset,
                     p_attribute->cur_len);

        wiced_bt_gatt_server_send_error_rsp(conn_id, opcode, p_read_req->handle, WICED_BT_GATT_INVALID_OFFSET);
        return (WICED_BT_GATT_INVALID_OFFSET);
    }
    else if (len_requested + p_read_req->offset > p_attribute->cur_len)
    {
        len_requested = p_attribute->cur_len - p_read_req->offset;
    }

    from = ((uint8_t *) p_attribute->p_data) + p_read_req->offset;

    wiced_bt_gatt_server_send_read_handle_rsp(conn_id, opcode, len_requested, from, NULL);

    return WICED_BT_GATT_SUCCESS;
}
/*
 * Currently there is no reason to pass Read Req by type handler to CHIP. Only process request for
 * attributes in the GATT DB attribute table
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceReadByTypeHandler(uint16_t conn_id, wiced_bt_gatt_opcode_t opcode,
                                                                          wiced_bt_gatt_read_by_type_t * p_read_req,
                                                                          uint16_t len_requested)
{
    gatt_db_lookup_table_t * puAttribute;
    uint16_t attr_handle = p_read_req->s_handle;
    uint8_t * p_rsp      = NULL;
    uint8_t pair_len     = 0;
    int used             = 0;

    if (heap_allocated == false)
    {
        p_heap         = wiced_bt_create_heap("default_heap", NULL, BT_STACK_HEAP_SIZE, NULL, WICED_TRUE);
        heap_allocated = true;
    }

    /* Allocate buffer for GATT Read */
    p_rsp = gatt_alloc_buffer(len_requested);
    if (p_rsp == NULL)
    {
        ChipLogError(DeviceLayer, "[%s]  no memory len_requested: %d!!\n", __FUNCTION__, len_requested);
        wiced_bt_gatt_server_send_error_rsp(conn_id, opcode, attr_handle, WICED_BT_GATT_INSUF_RESOURCE);
        return WICED_BT_GATT_INSUF_RESOURCE;
    }

    /* Read by type returns all attributes of the specified type, between the start and end handles */
    while (WICED_TRUE)
    {
        attr_handle = wiced_bt_gatt_find_handle_by_type(attr_handle, p_read_req->e_handle, &p_read_req->uuid);

        if (attr_handle == 0)
            break;

        if ((puAttribute = GetGattAttr(attr_handle)) == NULL)
        {
            ChipLogError(DeviceLayer, "[%s]  found type but no attribute ??\n", __FUNCTION__);
            wiced_bt_gatt_server_send_error_rsp(conn_id, opcode, p_read_req->s_handle, WICED_BT_GATT_ERR_UNLIKELY);
            gatt_free_buffer(p_rsp);
            return WICED_BT_GATT_INVALID_HANDLE;
        }

        {
            int filled = wiced_bt_gatt_put_read_by_type_rsp_in_stream(p_rsp + used, len_requested - used, &pair_len, attr_handle,
                                                                      puAttribute->cur_len, puAttribute->p_data);
            if (filled == 0)
            {
                break;
            }
            used += filled;
        }

        /* Increment starting handle for next search to one past current */
        attr_handle++;
    }

    if (used == 0)
    {
        ChipLogError(DeviceLayer, "[%s]  attr not found  start_handle: 0x%04x  end_handle: 0x%04x  Type: 0x%04x\n", __FUNCTION__,
                     p_read_req->s_handle, p_read_req->e_handle, p_read_req->uuid.uu.uuid16);
        wiced_bt_gatt_server_send_error_rsp(conn_id, opcode, p_read_req->s_handle, WICED_BT_GATT_INVALID_HANDLE);
        gatt_free_buffer(p_rsp);
        return WICED_BT_GATT_INVALID_HANDLE;
    }

    /* Send the response */
    wiced_bt_gatt_server_send_read_by_type_rsp(conn_id, opcode, pair_len, used, p_rsp,
                                               (wiced_bt_gatt_app_context_t) gatt_free_buffer_cb);

    return WICED_BT_GATT_SUCCESS;
}

/*
 * If Attribute is for CHIP, pass it through. Otherwise process request for
 * attributes in the GATT DB attribute table.
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceWrite(uint16_t conn_id, wiced_bt_gatt_write_req_t * p_data)
{
    wiced_bt_gatt_status_t result = WICED_BT_GATT_SUCCESS;
    gatt_db_lookup_table_t * puAttribute;
    const uint16_t valLen = p_data->val_len;
    // special handling for CHIP RX path
    if (p_data->handle == HDLC_CHIP_SERVICE_CHAR_C1_VALUE)
    {
        System::PacketBufferHandle buf;

        buf = System::PacketBufferHandle::NewWithData(p_data->p_val, valLen, 0, 0);
        if (!buf.IsNull())
        {
#ifdef BLE_DEBUG
            ChipLogDetail(DeviceLayer, "Write received for CHIPoBLE RX characteristic con %04x len %d", conn_id, valLen);
#endif
            // Post an event to the CHIP queue to deliver the data into the CHIP stack.
            {
                ChipDeviceEvent event;
                event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
                event.CHIPoBLEWriteReceived.ConId = conn_id;
                event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
                CHIP_ERROR status                 = PlatformMgr().PostEvent(&event);
                if (status != CHIP_NO_ERROR)
                {
                    result = WICED_BT_GATT_INTERNAL_ERROR;
                }
                buf = NULL;
            }
        }
        else
        {
            ChipLogError(DeviceLayer, "BLEManagerImpl: Out of buffers during CHIPoBLE RX");
            result = WICED_BT_GATT_NO_RESOURCES;
        }
    }
    else
    {
        ChipLogDetail(DeviceLayer, "Write received for CHIPoBLE RX characteristic con:%04x handle:%04x len:%d", conn_id,
                      p_data->handle, valLen);

        /* Get the right address for the handle in Gatt DB */
        if (NULL == (puAttribute = GetGattAttr(p_data->handle)))
        {
            ChipLogError(DeviceLayer, "BLEManagerImpl: Write wrong handle:%04x", p_data->handle);
            return WICED_BT_GATT_INVALID_HANDLE;
        }
        puAttribute->cur_len = valLen > puAttribute->max_len ? puAttribute->max_len : valLen;
        memcpy(puAttribute->p_data, p_data->p_val, puAttribute->cur_len);

        // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
        // whether the client is enabling or disabling indications.
        if (p_data->handle == HDLD_CHIP_SERVICE_RX_CLIENT_CHAR_CONFIG)
        {
            ChipDeviceEvent event;
            event.Type = (app_chip_service_char_tx_client_char_config[0] != 0) ? DeviceEventType::kCHIPoBLESubscribe
                                                                               : DeviceEventType::kCHIPoBLEUnsubscribe;
            event.CHIPoBLESubscribe.ConId = conn_id;
            if (PlatformMgr().PostEvent(&event) != CHIP_NO_ERROR)
            {
                return WICED_BT_GATT_INTERNAL_ERROR;
            }
        }

        ChipLogProgress(DeviceLayer, "CHIPoBLE %s received",
                        app_chip_service_char_tx_client_char_config[0] != 0 ? "subscribe" : "unsubscribe");
    }
    return result;
}

/*
 * Process MTU request received from the GATT client
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceMtuReq(uint16_t conn_id, uint16_t mtu)
{
    wiced_bt_gatt_server_send_mtu_rsp(conn_id, mtu, wiced_bt_cfg_settings.p_ble_cfg->ble_max_rx_pdu_size);
    return WICED_BT_GATT_SUCCESS;
}

/*
 * Process GATT Indication Confirm from the client
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceIndCfm(uint16_t conn_id, uint16_t handle)
{
#ifdef BLE_DEBUG
    ChipLogDetail(DeviceLayer, "GATT Ind Cfm received con:%04x handle:%d", conn_id, handle);
#endif
    if (handle == HDLC_CHIP_SERVICE_CHAR_C2_VALUE)
    {
        ChipDeviceEvent event;
        event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
        event.CHIPoBLEIndicateConfirm.ConId = conn_id;
        if (PlatformMgr().PostEvent(&event) != CHIP_NO_ERROR)
        {
            return WICED_BT_GATT_INTERNAL_ERROR;
        }
    }
    return WICED_BT_GATT_SUCCESS;
}

/*
 * Process GATT attribute requests
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattServiceRequestEvent(wiced_bt_gatt_attribute_request_t * p_request,
                                                                     CHIPoBLEConState * p_conn)
{
    wiced_bt_gatt_status_t result = WICED_BT_GATT_INVALID_PDU;
    switch (p_request->opcode)
    {
    case GATT_REQ_READ:
    case GATT_REQ_READ_BLOB:
        result =
            HandleGattServiceRead(p_request->conn_id, p_request->opcode, &(p_request->data.read_req), p_request->len_requested);
        break;
    case GATT_REQ_READ_BY_TYPE:
        result = HandleGattServiceReadByTypeHandler(p_request->conn_id, p_request->opcode, &p_request->data.read_by_type,
                                                    p_request->len_requested);
        break;
    case GATT_REQ_WRITE:
    case GATT_CMD_WRITE:
        result = HandleGattServiceWrite(p_request->conn_id, &(p_request->data.write_req));
        if ((p_request->opcode == GATT_REQ_WRITE) && (result == WICED_BT_GATT_SUCCESS))
        {
            wiced_bt_gatt_write_req_t * p_write_request = &p_request->data.write_req;
            wiced_bt_gatt_server_send_write_rsp(p_request->conn_id, p_request->opcode, p_write_request->handle);
        }
        break;

    case GATT_REQ_MTU:
        result = HandleGattServiceMtuReq(p_request->conn_id, p_request->data.remote_mtu);
        break;

    case GATT_HANDLE_VALUE_CONF:
        result = HandleGattServiceIndCfm(p_request->conn_id, p_request->data.confirm.handle);
        break;

    default:
        break;
    }

    return result;
}

/*
 * Handle GATT connection events from the stack
 */
wiced_bt_gatt_status_t BLEManagerImpl::HandleGattConnectEvent(wiced_bt_gatt_connection_status_t * p_conn_status,
                                                              CHIPoBLEConState * p_conn)
{
    if (p_conn_status->connected)
    {
        /* Device got connected */
        p_conn->connected = true;
        ChipLogProgress(DeviceLayer, "BLE GATT connection up (con %u)", p_conn_status->conn_id);
    }
    else /* Device got disconnected */
    {
        ChipDeviceEvent event;
        event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
        event.CHIPoBLEConnectionError.ConId = p_conn_status->conn_id;

        switch (p_conn_status->reason)
        {
        case GATT_CONN_TERMINATE_PEER_USER:
            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
            break;

        case GATT_CONN_TERMINATE_LOCAL_HOST:
            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
            break;

        default:
            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
            break;
        }

        ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", p_conn_status->conn_id,
                        p_conn_status->reason);

        if (PlatformMgr().PostEvent(&event) != CHIP_NO_ERROR)
        {
            return WICED_BT_GATT_INTERNAL_ERROR;
        }

        // Arrange to re-enable connectable advertising in case it was disabled due to the
        // maximum connection limit being reached.
        mFlags.Set(Flags::kFlag_Advertising, false);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);

        ReleaseConnectionState(p_conn->ConId);
    }
    return WICED_BT_GATT_SUCCESS;
}

/*
 * Process GATT requests. Callback is received in the BT stack thread context.
 *
 */
wiced_bt_gatt_status_t app_gatts_callback(wiced_bt_gatt_evt_t event, wiced_bt_gatt_event_data_t * p_data)
{
    uint16_t conn_id;
    BLEManagerImpl::CHIPoBLEConState * p_conn;

    /* Check parameter. */
    if (!p_data)
    {
        return WICED_BT_GATT_ILLEGAL_PARAMETER;
    }

    /* Check if target connection state exists. */
    switch (event)
    {
    case GATT_CONNECTION_STATUS_EVT:
        conn_id = p_data->connection_status.conn_id;
        break;

    case GATT_OPERATION_CPLT_EVT:
        conn_id = p_data->operation_complete.conn_id;
        break;

    case GATT_DISCOVERY_RESULT_EVT:
        conn_id = p_data->discovery_result.conn_id;
        break;

    case GATT_DISCOVERY_CPLT_EVT:
        conn_id = p_data->discovery_complete.conn_id;
        break;

    case GATT_ATTRIBUTE_REQUEST_EVT:
        conn_id = p_data->attribute_request.conn_id;
        break;

    case GATT_CONGESTION_EVT:
        conn_id = p_data->congestion.conn_id;
        break;

    case GATT_GET_RESPONSE_BUFFER_EVT:
        if (heap_allocated == false)
        {
            p_heap         = wiced_bt_create_heap("default_heap", NULL, BT_STACK_HEAP_SIZE, NULL, WICED_TRUE);
            heap_allocated = true;
        }
        p_data->buffer_request.buffer.p_app_rsp_buffer =
            BLEManagerImpl::sInstance.gatt_alloc_buffer(p_data->buffer_request.len_requested);
        p_data->buffer_request.buffer.p_app_ctxt = (wiced_bt_gatt_app_context_t) gatt_free_buffer_cb;
        return WICED_BT_GATT_SUCCESS;
        break;

    case GATT_APP_BUFFER_TRANSMITTED_EVT: {
        pfn_free_buffer_t pfn_free = (pfn_free_buffer_t) p_data->buffer_xmitted.p_app_ctxt;
        if (pfn_free)
        {
            pfn_free(p_data->buffer_xmitted.p_app_data);
        }
    }
        return WICED_BT_GATT_SUCCESS;
        break;

    default:
        return WICED_BT_GATT_ILLEGAL_PARAMETER;
    }

    p_conn = BLEManagerImpl::sInstance.GetConnectionState(conn_id);

    /* Allocate connection state if no exist. */
    if (!p_conn)
    {
        p_conn = BLEManagerImpl::sInstance.AllocConnectionState(conn_id);

        if (!p_conn)
        {
            return WICED_BT_GATT_INSUF_RESOURCE;
        }
    }

    switch (event)
    {
    case GATT_CONNECTION_STATUS_EVT:
        return BLEManagerImpl::sInstance.HandleGattConnectEvent(&p_data->connection_status, p_conn);

    case GATT_ATTRIBUTE_REQUEST_EVT:
        return BLEManagerImpl::sInstance.HandleGattServiceRequestEvent(&p_data->attribute_request, p_conn);

    default:
        break;
    }

    return WICED_BT_GATT_ILLEGAL_PARAMETER;
}

void BLEManagerImpl::SetAdvertisingData(void)
{
    CHIP_ERROR err;
    wiced_bt_ble_advert_elem_t adv_elem[4];
    uint8_t num_elem             = 0;
    uint8_t flag                 = BTM_BLE_GENERAL_DISCOVERABLE_FLAG | BTM_BLE_BREDR_NOT_SUPPORTED;
    uint8_t chip_service_uuid[2] = { BIT16_TO_8(__UUID16_CHIPoBLEService) };
    ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
    uint16_t deviceDiscriminator = 0;
    uint8_t localDeviceNameLen;
    uint8_t service_data[BLE_SERVICE_DATA_SIZE];
    uint8_t * p = service_data;

    static_assert(BLE_SERVICE_DATA_SIZE == sizeof(ChipBLEDeviceIdentificationInfo) + 2, "BLE Service Data Size is incorrect");

    // Initialize the CHIP BLE Device Identification Information block that will be sent as payload
    // within the BLE service advertisement data.
    err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
    SuccessOrExit(err);

    // Get device discriminator
    deviceDiscriminator = mDeviceIdInfo.GetDeviceDiscriminator();

    // Verify device name was not already set
    if (!sInstance.mFlags.Has(sInstance.Flags::kFlag_DeviceNameSet))
    {
        /* Default device name is CHIP-<DISCRIMINATOR> */
        memset(sInstance.mDeviceName, 0, kMaxDeviceNameLength);
        snprintf(sInstance.mDeviceName, kMaxDeviceNameLength, "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX,
                 deviceDiscriminator);
        localDeviceNameLen = strlen(sInstance.mDeviceName);

        Platform::CopyString((char *) app_gap_device_name, sizeof(app_gap_device_name), sInstance.mDeviceName);
        app_gatt_db_ext_attr_tbl[0].cur_len = app_gatt_db_ext_attr_tbl[0].max_len < strlen(sInstance.mDeviceName)
            ? app_gatt_db_ext_attr_tbl[0].max_len
            : strlen(sInstance.mDeviceName);

        ChipLogProgress(DeviceLayer, "SetAdvertisingData: device name set: %s", sInstance.mDeviceName);
    }
    else
    {
        localDeviceNameLen = strlen(sInstance.mDeviceName);
    }

    /* First element is the advertisement flags */
    adv_elem[num_elem].advert_type = BTM_BLE_ADVERT_TYPE_FLAG;
    adv_elem[num_elem].len         = sizeof(uint8_t);
    adv_elem[num_elem].p_data      = &flag;
    num_elem++;

    /* Second element is the service data for CHIP service */
    adv_elem[num_elem].advert_type = BTM_BLE_ADVERT_TYPE_SERVICE_DATA;
    adv_elem[num_elem].len         = sizeof(service_data);
    adv_elem[num_elem].p_data      = service_data;
    num_elem++;
    UINT8_TO_STREAM(p, chip_service_uuid[0]);
    UINT8_TO_STREAM(p, chip_service_uuid[1]);
    UINT8_TO_STREAM(p, 0); // CHIP BLE Opcode == 0x00 (Uncommissioned)
    UINT16_TO_STREAM(p, deviceDiscriminator);
    UINT8_TO_STREAM(p, mDeviceIdInfo.DeviceVendorId[0]);
    UINT8_TO_STREAM(p, mDeviceIdInfo.DeviceVendorId[1]);
    UINT8_TO_STREAM(p, mDeviceIdInfo.DeviceProductId[0]);
    UINT8_TO_STREAM(p, mDeviceIdInfo.DeviceProductId[1]);
    UINT8_TO_STREAM(p, 0); // Additional Data Flag

    adv_elem[num_elem].advert_type = BTM_BLE_ADVERT_TYPE_NAME_COMPLETE;
    adv_elem[num_elem].len         = localDeviceNameLen;
    adv_elem[num_elem].p_data      = (uint8_t *) sInstance.mDeviceName;
    num_elem++;

    wiced_bt_ble_set_raw_advertisement_data(num_elem, adv_elem);

    /* Configure Scan Response data */
    num_elem                       = 0;
    adv_elem[num_elem].advert_type = BTM_BLE_ADVERT_TYPE_NAME_COMPLETE;
    adv_elem[num_elem].len         = localDeviceNameLen;
    adv_elem[num_elem].p_data      = (uint8_t *) sInstance.mDeviceName;
    num_elem++;

    wiced_bt_ble_set_raw_scan_response_data(num_elem, adv_elem);

exit:
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SetAdvertisingData err:%s", ErrorStr(err));
}

BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::AllocConnectionState(uint16_t conId)
{
    for (uint16_t i = 0; i < kMaxConnections; i++)
    {
        if (mCons[i].connected == false)
        {
            mCons[i].ConId     = conId;
            mCons[i].Mtu       = wiced_bt_cfg_settings.p_ble_cfg->ble_max_rx_pdu_size;
            mCons[i].connected = false;

            mNumCons++;

            return &mCons[i];
        }
    }
    ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
    return NULL;
}

BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint16_t conId)
{
    for (uint16_t i = 0; i < kMaxConnections; i++)
    {
        if (mCons[i].ConId == conId)
        {
            return &mCons[i];
        }
    }
    ChipLogError(DeviceLayer, "Failed to find CHIPoBLEConState");
    return NULL;
}

bool BLEManagerImpl::ReleaseConnectionState(uint16_t conId)
{
    for (uint16_t i = 0; i < kMaxConnections; i++)
    {
        if (mCons[i].ConId == conId)
        {
            memset(&mCons[i], 0, sizeof(CHIPoBLEConState));
            mNumCons--;
            return true;
        }
    }
    ChipLogError(DeviceLayer, "Failed to delete CHIPoBLEConState");
    return false;
}

void BLEManagerImpl::DriveBLEState(intptr_t arg)
{
    sInstance.DriveBLEState();
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip

#endif
