/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    Copyright (c) 2019 Nest Labs, Inc.
 *
 *    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 MediaTek Genio platforms.
 */

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

#undef BT_ENABLE_HCI_SNOOP_LOG

#include <platform/CommissionableDataProvider.h>
#include <platform/internal/BLEManager.h>

#include "FreeRTOS.h"
#include "event_groups.h"
#include "timers.h"
#include <ble/Ble.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

#include "bt_callback_manager.h"
#include "bt_gap_le.h"
#include "bt_gatts.h"
#include "bt_init.h"
#include "bt_platform.h"
#include "bt_uuid.h"
#include "connection_info.h"
#ifdef BT_ENABLE_HCI_SNOOP_LOG
#include "bt_driver_btsnoop.h"
#endif
#include "gatt_service.h"

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

extern void (*CHIPoBLEProfile_read_callback)(uint16_t handle, void * data, uint16_t size);
extern void (*CHIPoBLEProfile_write_callback)(uint16_t handle, void * data, uint16_t size);
extern void (*CHIPoBLEProfile_ccc_callback)(uint16_t handle, void * data, uint16_t size);

namespace chip {
namespace DeviceLayer {
namespace Internal {

namespace {
#define CHIP_ADV_DATA_TYPE_FLAGS 0x01
#define CHIP_ADV_DATA_FLAGS 0x06
#define CHIP_ADV_DATA_TYPE_NAME 0x09
#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
#define CHIP_ADV_SHORT_UUID_LEN 2

#define MAX_ADV_DATA_LEN (31)
#define BLE_ADV_OTHER_LEN (9)

const uint8_t ShortUUID_CHIPoBLEService[] = { 0xF6, 0xFF };

#define EG_EVENT_BLE_POWER_ON_CNF (0x01)
#define EG_EVENT_BLE_ADV_CNF (0x02)

TimerHandle_t sbleAdvTimeoutTimer; // FreeRTOS sw timer.
EventGroupHandle_t xBleEventGroup;

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 } };

} // namespace

BLEManagerImpl BLEManagerImpl::sInstance;

/***************************************************************************/
/**
 * Setup the bluetooth init function.
 *
 * @return none
 *
 * All bluetooth specific initialization
 ******************************************************************************/

CHIP_ERROR BLEManagerImpl::_Init()
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Initialize the CHIP BleLayer.
    ChipLogError(DeviceLayer, "BLE init start");
    err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
    ChipLogError(DeviceLayer, "BleLayer init complete");
    SuccessOrExit(err);

    mServiceMode                   = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
    CHIPoBLEProfile_write_callback = BLEManagerImpl::HandleRXCharWrite;
    CHIPoBLEProfile_ccc_callback   = BLEManagerImpl::HandleTXCharCCCDWrite;

    xBleEventGroup = xEventGroupCreate();
    if (xBleEventGroup == NULL)
    {
        ChipLogError(DeviceLayer, "Cannot create xBleEventGroup");
        err = CHIP_ERROR_NO_MEMORY;
    }
    SuccessOrExit(err);

    init_connection_info();
    bt_create_task();

    bt_callback_manager_register_callback(bt_callback_type_app_event,
                                          (uint32_t) (MODULE_MASK_GAP | MODULE_MASK_GATT | MODULE_MASK_SYSTEM),
                                          (void *) BleMatterAppEventCallback);
#ifdef BT_ENABLE_HCI_SNOOP_LOG
    bt_driver_btsnoop_ctrl(1);
#endif
    // Create FreeRTOS sw timer for BLE timeouts and interval change.
    sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer",       // Just a text name, not used by the RTOS kernel
                                       1,                   // == default timer period (mS)
                                       false,               // no timer reload (==one-shot)
                                       (void *) this,       // init timer id = ble obj context
                                       BleAdvTimeoutHandler // timer callback handler
    );

    mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
    mFlags.Set(Flags::kFastAdvertisingEnabled, true);
    PlatformMgr().ScheduleWork(DriveBLEState, 0);

exit:
    return err;
}

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

#if 0
CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

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

    if (val != mServiceMode)
    {
        mServiceMode = val;
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

exit:
    return err;
}
#endif

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::kAdvertisingEnabled) != val)
    {
        mFlags.Set(Flags::kAdvertisingEnabled, val);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
{
    switch (mode)
    {
    case BLEAdvertisingMode::kFastAdvertising:
        mFlags.Set(Flags::kFastAdvertisingEnabled, true);
        break;
    case BLEAdvertisingMode::kSlowAdvertising:
        mFlags.Set(Flags::kFastAdvertisingEnabled, false);
        break;
    default:
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    mFlags.Set(Flags::kRestartAdvertising);
    PlatformMgr().ScheduleWork(DriveBLEState, 0);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
{
    if (strlen(gatts_device_name) >= bufSize)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    strcpy(buf, gatts_device_name);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    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;
        }
        strcpy(gatts_device_name, deviceName);
    }
    else
    {
        gatts_device_name[0] = 0;
    }

    return CHIP_NO_ERROR;
}

void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    switch (event->Type)
    {
    case DeviceEventType::kCHIPoBLESubscribe: {
        ChipDeviceEvent connEstEvent;

        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLESubscribe");
        HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
        connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
        PlatformMgr().PostEventOrDie(&connEstEvent);
    }
    break;

    case DeviceEventType::kCHIPoBLEUnsubscribe: {
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLEUnsubscribe");
        HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
    }
    break;

    case DeviceEventType::kCHIPoBLEWriteReceived: {
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLEWriteReceived");
        HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
                            PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
    }
    break;

    case DeviceEventType::kCHIPoBLEConnectionError: {
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLEConnectionError");
        HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
    }
    break;

    case DeviceEventType::kCHIPoBLEIndicateConfirm: {
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLEIndicateConfirm, ConId %04x",
                        event->CHIPoBLEIndicateConfirm.ConId);
        HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
    }
    break;

    case DeviceEventType::kCHIPoBLENotifyConfirm: {
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent kCHIPoBLENotifyConfirm");
        HandleTxConfirmationEvent(event->CHIPoBLENotifyConfirm.ConId);
    }
    break;

    default:
        ChipLogProgress(DeviceLayer, "_OnBlePlatformEvent default:  event->Type = %d", event->Type);
        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)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    bt_hci_cmd_disconnect_t disconnect_para;
    bt_status_t ret;

    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);

    disconnect_para.connection_handle = conId;
    disconnect_para.reason            = BT_HCI_STATUS_REMOTE_USER_TERMINATED_CONNECTION;

    ret = bt_gap_le_disconnect(&disconnect_para);
    err = MapBLEError(ret);

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "bt_gap_le_disconnect() failed: %s", ErrorStr(err));
    }

    return (err == CHIP_NO_ERROR);
}

uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
{
    uint16_t mtu = (uint16_t) bt_gattc_get_mtu(conId);

    ChipLogProgress(DeviceLayer, "GetMTU (con %u), returning %u", conId, mtu);

    return mtu;
}

#define INDICATION_BUFFER_LENGTH (300)
bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                    PacketBufferHandle data)
{
    uint8_t buf[INDICATION_BUFFER_LENGTH + 3] = { 0 };
    bt_gattc_charc_value_notification_indication_t * req;
    CHIP_ERROR err = CHIP_NO_ERROR;
    ChipDeviceEvent event;
    bt_status_t ret;

    VerifyOrExit(UUIDsMatch(&ChipUUID_CHIPoBLEChar_TX, charId), err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
    VerifyOrExit(UUIDsMatch(&ChipUUID_CHIPoBLEChar_TX, charId), err = CHIP_ERROR_INVALID_MESSAGE_TYPE);

    ChipLogProgress(DeviceLayer, "SendIndication(): conId %d, len %d", conId, data->DataLength());

    if (data->DataLength() > INDICATION_BUFFER_LENGTH)
    {
        ChipLogError(DeviceLayer, "SendIndication(): Exceed buffer length! conId %d, len %d", conId, data->DataLength());
        err = CHIP_ERROR_NO_MEMORY;
        goto exit;
    }

    req                         = (bt_gattc_charc_value_notification_indication_t *) buf;
    req->attribute_value_length = 3 + data->DataLength();
    req->att_req.opcode         = BT_ATT_OPCODE_HANDLE_VALUE_INDICATION;
    req->att_req.handle         = 24;
    memcpy(&req->att_req.attribute_value[0], data->Start(), data->DataLength());
    ret = bt_gatts_send_charc_value_notification_indication(conId, req);
    err = MapBLEError(ret);
    SuccessOrExit(err);

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

    return true;
}

void BLEManagerImpl::HandleRXCharWrite(uint16_t handle, void * data, uint16_t size)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    System::PacketBufferHandle buf;
    uint16_t writeLen = size;

    // Copy the data to a packet buffer.
    buf = System::PacketBufferHandle::NewWithData(data, writeLen, 0, 0);
    VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);

    ChipLogDetail(DeviceLayer, "Write request/command received for CHIPoBLE RX characteristic (con %u, len %u)", handle,
                  buf->DataLength());

    // Post an event to the CHIP queue to deliver the data into the CHIP stack.
    {
        ChipDeviceEvent event;
        event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
        event.CHIPoBLEWriteReceived.ConId = handle;
        event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
        err                               = PlatformMgr().PostEvent(&event);
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
    }
}

void BLEManagerImpl::HandleTXCharCCCDWrite(uint16_t handle, void * data, uint16_t size)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    app_bt_connection_cb_t * bleConnState;
    bool isDisabled;
    ChipDeviceEvent event;
    bleConnState = find_connection_info_by_handle(handle);
    VerifyOrExit(bleConnState != NULL, err = CHIP_ERROR_NO_MEMORY);

    VerifyOrExit(size == sizeof(uint16_t), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

    // Determine if the client is enabling or disabling notification/indication.
    isDisabled = (*(uint16_t *) data != 0x0002);

    ChipLogProgress(DeviceLayer, "HandleTXcharCCCDWrite - Config Flags value : %d", *(uint16_t *) data);
    ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", isDisabled ? "unsubscribe" : "subscribe");

    if (!isDisabled)
    {
        // If indications are not already enabled for the connection...
        if (!bleConnState->subscribed)
        {
            bleConnState->subscribed = 1;
            // 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.
            {
                event.Type                    = DeviceEventType::kCHIPoBLESubscribe;
                event.CHIPoBLESubscribe.ConId = handle;
                err                           = PlatformMgr().PostEvent(&event);
            }
        }
    }
    else
    {
        bleConnState->subscribed      = 0;
        event.Type                    = DeviceEventType::kCHIPoBLEUnsubscribe;
        event.CHIPoBLESubscribe.ConId = handle;
        err                           = PlatformMgr().PostEvent(&event);
    }

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
    }
}

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

bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                     PacketBufferHandle pBuf)
{
    ChipLogProgress(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)
{
    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
    return false;
}

void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
{
    // Nothing to do
}

void BLEManagerImpl::HandleTxConfirmationEvent(BLE_CONNECTION_OBJECT conId)
{
    ChipDeviceEvent event;
    ChipLogProgress(DeviceLayer, "Tx Confirmation received!!!");

    event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
    event.CHIPoBLEIndicateConfirm.ConId = conId;
    PlatformMgr().PostEventOrDie(&event);
}

CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
{
    switch (bleErr)
    {
    case BT_STATUS_SUCCESS:
        return CHIP_NO_ERROR;
    default:
        return CHIP_ERROR(ChipError::Range::kPlatform, bleErr + CHIP_DEVICE_CONFIG_BLE_ERROR_MIN);
    }
}

CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
{
    bt_hci_cmd_le_set_advertising_enable_t enable;
    uint32_t deviceNameLength = 0;
    ChipBLEDeviceIdentificationInfo deviceIdInfo;
    uint8_t deviceIdInfoLength = sizeof(deviceIdInfo);
    CHIP_ERROR err             = CHIP_NO_ERROR;
    int adv_name_len;
    uint32_t index = 0;
    bt_status_t ret;

    bt_hci_cmd_le_set_advertising_parameters_t adv_param = { .advertising_interval_min =
                                                                 CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN,
                                                             .advertising_interval_max =
                                                                 CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX,
                                                             .advertising_type          = BT_HCI_ADV_TYPE_CONNECTABLE_UNDIRECTED,
                                                             .own_address_type          = BT_ADDR_PUBLIC,
                                                             .advertising_channel_map   = 7,
                                                             .advertising_filter_policy = 0 };

    bt_hci_cmd_le_set_advertising_data_t adv_data = {
        .advertising_data_length = MAX_ADV_DATA_LEN,
    };

    if (mFlags.Has(Flags::kRestartAdvertising))
    {
        ChipLogProgress(DeviceLayer, "Stop advertising..");
        enable.advertising_enable = BT_HCI_DISABLE;
        ret                       = bt_gap_le_set_advertising(&enable, NULL, NULL, NULL);

        if (BT_STATUS_SUCCESS == ret)
        {
            xEventGroupWaitBits(xBleEventGroup, EG_EVENT_BLE_ADV_CNF, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000));
            ChipLogProgress(DeviceLayer, "Advertising stopped.");
        }

        mFlags.Clear(Flags::kRestartAdvertising);
    }

    if (mFlags.Has(Flags::kFastAdvertisingEnabled))
    {
        adv_param.advertising_interval_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
        adv_param.advertising_interval_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
    }

    if (!mFlags.Has(Flags::kDeviceNameSet))
    {
        uint16_t discriminator = 0;
        err                    = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator);

        snprintf(gatts_device_name, sizeof(gatts_device_name), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX,
                 static_cast<uint32_t>(discriminator));

        gatts_device_name[kMaxDeviceNameLength] = 0;
    }

    deviceNameLength = strlen(gatts_device_name);

    VerifyOrExit(deviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
    deviceNameLength =
        deviceNameLength > MAX_ADV_DATA_LEN - BLE_ADV_OTHER_LEN - 1 ? MAX_ADV_DATA_LEN - BLE_ADV_OTHER_LEN - 1 : deviceNameLength;

    ChipLogProgress(DeviceLayer, "Beginning advertising, interval(min,max)=(%d, %d), devName=%s, len=%lu",
                    adv_param.advertising_interval_min, adv_param.advertising_interval_max, gatts_device_name, deviceNameLength);

    err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
    SuccessOrExit(err);

    static_assert(sizeof(deviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
    static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(deviceIdInfo) + 1 <= MAX_ADV_DATA_LEN, "Our buffer is not big enough");

    adv_data.advertising_data[index++] = 0x02;                     // AD length
    adv_data.advertising_data[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
    adv_data.advertising_data[index++] = CHIP_ADV_DATA_FLAGS;      // AD value

    adv_data.advertising_data[index++] = static_cast<uint8_t>(deviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
    adv_data.advertising_data[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data
    adv_data.advertising_data[index++] = ShortUUID_CHIPoBLEService[0];    // AD value
    adv_data.advertising_data[index++] = ShortUUID_CHIPoBLEService[1];

    memcpy(&adv_data.advertising_data[index], (void *) &deviceIdInfo, deviceIdInfoLength); // AD value
    index += deviceIdInfoLength;

    adv_data.advertising_data[index++] = static_cast<uint8_t>(deviceNameLength + 1); // AD length
    adv_data.advertising_data[index++] = CHIP_ADV_DATA_TYPE_NAME;                    // AD type : name
    memcpy(&adv_data.advertising_data[index], gatts_device_name, deviceNameLength);  // AD value
    index += deviceNameLength;

    enable.advertising_enable = BT_HCI_ENABLE;
    ret                       = bt_gap_le_set_advertising(&enable, &adv_param, &adv_data, NULL);

    err = MapBLEError(ret);
    SuccessOrExit(err);

    if ((xEventGroupWaitBits(xBleEventGroup, EG_EVENT_BLE_ADV_CNF, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000)) & EG_EVENT_BLE_ADV_CNF) ==
        EG_EVENT_BLE_ADV_CNF)
    {
        ChipLogProgress(DeviceLayer, "Advertising started.");
        if (mFlags.Has(Flags::kFastAdvertisingEnabled))
        {
            StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME);
        }
        mFlags.Set(Flags::kAdvertising);
    }
    else
    {
        err = CHIP_ERROR_TIMEOUT;
    }

exit:
    return err;
}

CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    bt_status_t ret;

    if (mFlags.Has(Flags::kAdvertising))
    {
        mFlags.Clear(Flags::kAdvertising).Clear(Flags::kRestartAdvertising);
        mFlags.Set(Flags::kFastAdvertisingEnabled, true);

        ChipLogProgress(DeviceLayer, "Stop advertising..");
        bt_hci_cmd_le_set_advertising_enable_t enable = { BT_HCI_DISABLE };
        ret                                           = bt_gap_le_set_advertising(&enable, NULL, NULL, NULL);

        err = MapBLEError(ret);
        SuccessOrExit(err);

        if ((xEventGroupWaitBits(xBleEventGroup, EG_EVENT_BLE_ADV_CNF, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000)) &
             EG_EVENT_BLE_ADV_CNF) != EG_EVENT_BLE_ADV_CNF)
        {
            err = CHIP_ERROR_TIMEOUT;
        }
        SuccessOrExit(err);

        ChipLogProgress(DeviceLayer, "Advertising stopped.");

        CancelBleAdvTimeoutTimer();
    }

exit:
    return err;
}

void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer)
{
    if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled))
    {
        ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement");
        BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
    }
    else if (BLEMgrImpl().mFlags.Has(Flags::kAdvertising))
    {
        // Advertisement time expired. Stop advertising
        ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertisement");
        BLEMgr().SetAdvertisingEnabled(false);
    }
}

void BLEManagerImpl::CancelBleAdvTimeoutTimer(void)
{
    if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL)
    {
        ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
    }
}

void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs)
{
    if (xTimerIsTimerActive(sbleAdvTimeoutTimer))
    {
        CancelBleAdvTimeoutTimer();
    }

    // timer is not active, change its period to required value (== restart).
    // FreeRTOS- Block for a maximum of 100 ticks if the change period command
    // cannot immediately be sent to the timer command queue.
    if (xTimerChangePeriod(sbleAdvTimeoutTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
    {
        ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer");
    }
}

bt_status_t BLEManagerImpl::BleMatterAppEventCallback(bt_msg_type_t msg, bt_status_t status, void * buff)
{
    ChipLogProgress(DeviceLayer, "BleMatterAppEventCallback: msg %08x, status %08x", (unsigned int) msg, (unsigned int) status);

    // PlatformMgr().LockChipStack();

    switch (msg)
    {
    case BT_POWER_ON_CNF:
        if (BT_STATUS_SUCCESS != bt_gatts_set_max_mtu(247))
        {
            ChipLogError(DeviceLayer, "Unable to set BT GATTS maximum mtu size!");
        }

        sInstance.mFlags.Set(Flags::kBLEStackInitialized);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;

    case BT_GAP_LE_SET_ADVERTISING_CNF:
        ChipLogProgress(DeviceLayer, "BT_GAP_LE_SET_ADVERTISING_CNF: Raise EG_EVENT_BLE_ADV_CNF");
        xEventGroupSetBits(xBleEventGroup, EG_EVENT_BLE_ADV_CNF);
        break;

    case BT_GAP_LE_CONNECT_IND:
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
        break;

    case BT_GAP_LE_DISCONNECT_IND: {
        bt_hci_evt_disconnect_complete_t * conn_evt = (bt_hci_evt_disconnect_complete_t *) buff;
        ChipDeviceEvent event;
        event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
        event.CHIPoBLEConnectionError.ConId = conn_evt->connection_handle;

        switch (conn_evt->reason)
        {
        case BT_HCI_STATUS_REMOTE_USER_TERMINATED_CONNECTION:
        case BT_HCI_STATUS_REMOTE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES:
        case BT_HCI_STATUS_REMOTE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF:
            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
            break;

        case BT_HCI_STATUS_CONNECTION_TERMINATED_BY_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)", conn_evt->connection_handle,
                        conn_evt->reason);

        PlatformMgr().PostEventOrDie(&event);

        // Arrange to re-enable connectable advertising in case it was disabled due to the
        // maximum connection limit being reached.

        sInstance.mFlags.Set(Flags::kRestartAdvertising);
        sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }
    break;
    case BT_GATTC_CHARC_VALUE_CONFIRMATION: {
        bt_handle_t * connection_handle_p = (bt_handle_t *) buff;
        ChipDeviceEvent event;

        ChipLogProgress(DeviceLayer, "Tx Confirmation received");

        event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
        event.CHIPoBLEIndicateConfirm.ConId = *connection_handle_p;
        PlatformMgr().PostEventOrDie(&event);
    }
    break;

    default:
        break;
    }

    // PlatformMgr().UnlockChipStack();

    return BT_STATUS_SUCCESS;
}

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

    // Check if BLE stack is initialized
    VerifyOrExit(mFlags.Has(Flags::kBLEStackInitialized), /* */);

    // Start advertising if needed...
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled) &&
        NumConnections() < kMaxConnections)
    {
        // Start/re-start advertising if not already started, or if there is a pending change
        // to the advertising configuration.
        if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kRestartAdvertising))
        {
            err = StartAdvertising();
            SuccessOrExit(err);
        }
    }

    // Otherwise, stop advertising if it is enabled.
    else if (mFlags.Has(Flags::kAdvertising))
    {
        err = StopAdvertising();
        SuccessOrExit(err);
    }

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

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

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

#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
