/*
 *
 *    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/CHIPBleServiceData.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 advertissement");
        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
