/*
 *
 *    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/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
{
    ChipLogProgress(DeviceLayer, "GetMTU (con %u), returning 247", conId);
    return 247;
}

#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))
    {
        snprintf(gatts_device_name, sizeof(gatts_device_name), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX,
                 (uint32_t) 0);

        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
