/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *
 *    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 Telink platform.
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE

#include <ble/BleUUID.h>
#include <ble/CHIPBleServiceData.h>
#include <platform/internal/BLEManager.h>

#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

/*Includes for ieee802154 switchings */
#define DT_DRV_COMPAT telink_b91_zb
#include <drivers/ieee802154/b91.h>
#include <zephyr/net/ieee802154_radio.h>

/* Telink headers */
#include "drivers.h"
#include "ext_driver/ext_misc.h"
#include "stack/ble/ble.h"
#include "tl_common.h"
#include "types.h"

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

namespace chip {
namespace DeviceLayer {
namespace Internal {

namespace {

typedef enum
{
    ATT_H_START = 0,

    /* GAP service */
    GenericAccess_PS_H,            // UUID: 2800, VALUE: uuid 1800
    GenericAccess_DeviceName_CD_H, // UUID: 2803, VALUE: Prop: Read | Notify
    GenericAccess_DeviceName_DP_H, // UUID: 2A00, VALUE: device name
    GenericAccess_Appearance_CD_H, // UUID: 2803, VALUE: Prop: Read
    GenericAccess_Appearance_DP_H, // UUID: 2A01, VALUE: appearance
    CONN_PARAM_CD_H,               // UUID: 2803, VALUE: Prop: Read
    CONN_PARAM_DP_H,               // UUID: 2A04, VALUE: connParameter

    /* GATT service */
    GenericAttribute_PS_H,                 // UUID: 2800, VALUE: uuid 1801
    GenericAttribute_ServiceChanged_CD_H,  // UUID: 2803, VALUE: Prop: Indicate
    GenericAttribute_ServiceChanged_DP_H,  // UUID: 2A05, VALUE: service change
    GenericAttribute_ServiceChanged_CCB_H, // UUID: 2902, VALUE: serviceChangeCCC

    /* Matter service */
    Matter_PS_H,
    Matter_RX_CD_H,
    Matter_RX_DP_H,
    Matter_TX_CD_H,
    Matter_TX_DP_H,
    Matter_TX_CCC_H,

    ATT_END_H,

} ATT_HANDLE;

typedef struct
{
    /** Minimum value for the connection event (interval. 0x0006 - 0x0C80 * 1.25 ms) */
    u16 intervalMin;
    /** Maximum value for the connection event (interval. 0x0006 - 0x0C80 * 1.25 ms) */
    u16 intervalMax;
    /** Number of LL latency connection events (0x0000 - 0x03e8) */
    u16 latency;
    /** Connection Timeout (0x000A - 0x0C80 * 10 ms) */
    u16 timeout;
} gap_periConnectParams_t;

#define CHIP_MAC_LEN 6
#define CHIP_MTU_SIZE 244
#define CHIP_MAX_ADV_DATA_LEN 31
#define CHIP_MAX_RESPONSE_DATA_LEN 31
#define CHIP_SHORT_UUID_LEN 2

#define CHIP_ADE_DATA_LEN_FLAGS 0x02
#define CHIP_ADV_DATA_TYPE_FLAGS 0x01
#define CHIP_ADV_DATA_FLAGS 0x06
#define CHIP_ADV_DATA_TYPE_UUID 0x03
#define CHIP_ADV_DATA_TYPE_NAME 0x09
#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
#define CHIP_ADV_SERVICE_DATA_LEN (sizeof(ChipBLEDeviceIdentificationInfo) + CHIP_SHORT_UUID_LEN + 1)

#define CHIP_BLE_TX_FIFO_SIZE 48
#define CHIP_BLE_TX_FIFO_NUM 33
#define CHIP_BLE_RX_FIFO_SIZE 48
#define CHIP_BLE_RX_FIFO_NUM 8

#define CHIP_BLE_THREAD_STACK_SIZE 2048
#define CHIP_BLE_THREAD_PRIORITY 2

#define CHIP_BLE_DISCONNECT_REASON 8

#define CHIP_RF_PACKET_HEADER_SIZE 3

#define STIMER_IRQ_NUM 1
#define RF_IRQ_NUM 15

#define CHIP_RX_CHAR_UUID 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18
#define CHIP_TX_CHAR_UUID 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18

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

static const uint8_t matterServiceUUID[CHIP_SHORT_UUID_LEN] = { 0xF6, 0xFF }; // service UUID

} // unnamed namespace

BLEManagerImpl BLEManagerImpl::sInstance;

void rf_irq_handler(const void * paramiter)
{
    irq_blt_sdk_handler();
}

void stimer_irq_handler(const void * paramiter)
{
    irq_blt_sdk_handler();
}

void BLEManagerImpl::BleEntry(void *, void *, void *)
{
    while (true)
    {
        blt_sdk_main_loop();

        k_msleep(10);
    }
}

/* Thread for running BLE main loop */
K_THREAD_DEFINE(chipBleThread, CHIP_BLE_THREAD_STACK_SIZE, BLEManagerImpl::BleEntry, NULL, NULL, NULL, CHIP_BLE_THREAD_PRIORITY, 0,
                0);

CHIP_ERROR BLEManagerImpl::_Init()
{
    ThreadConnectivityReady = false;

    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
    mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
    mFlags.Set(Flags::kFastAdvertisingEnabled, true);
    mGAPConns = 0;

    memset(mSubscribedConns, 0, sizeof(mSubscribedConns));

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

    // Suspend BLE Task
    k_thread_suspend(chipBleThread);

    return CHIP_NO_ERROR;
}

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

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

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

    // If the application has enabled CHIPoBLE and BLE advertising...
    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
        mFlags.Has(Flags::kAdvertisingEnabled)
#if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
        // and no connections are active...
        && (NumConnections() == 0)
#endif
    )
    {
        // Start/re-start advertising if not already advertising, or if the
        // advertising state needs to be refreshed.
        if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
        {
            mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
            err = StartAdvertising();
            SuccessOrExit(err);
        }
    }
    else
    {
        if (mFlags.Has(Flags::kAdvertising))
        {
            err = StopAdvertising();
            SuccessOrExit(err);
        }
    }

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

int BLEManagerImpl::RxWriteCallback(uint16_t connHandle, void * p)
{
    rf_packet_att_t * packet = (rf_packet_att_t *) p;
    size_t dataLen           = packet->l2capLen - CHIP_RF_PACKET_HEADER_SIZE;
    ChipDeviceEvent event;

    PacketBufferHandle packetBuf = PacketBufferHandle::NewWithData(packet->dat, dataLen);

    // If successful...
    if (packetBuf.IsNull())
    {
        ChipLogError(DeviceLayer, "Failed to allocate buffer");

        return 0;
    }

    // Arrange to post a CHIPoBLERXWriteEvent event to the CHIP queue.
    event.Type                                = DeviceEventType::kPlatformTelinkBleRXWrite;
    event.Platform.BleRXWriteEvent.connHandle = connHandle;
    event.Platform.BleRXWriteEvent.Data       = std::move(packetBuf).UnsafeRelease();

    PlatformMgr().PostEventOrDie(&event);

    return 0;
}

void BLEManagerImpl::ConnectCallback(uint8_t bleEvent, uint8_t * data, int len)
{
    ChipDeviceEvent event;
    ble_sts_t status = BLE_SUCCESS;

    event.Type                             = DeviceEventType::kPlatformTelinkBleConnected;
    event.Platform.BleConnEvent.connHandle = BLS_CONN_HANDLE;
    event.Platform.BleConnEvent.HciResult  = BLE_SUCCESS;

    PlatformMgr().PostEventOrDie(&event);
}

void BLEManagerImpl::DisconnectCallback(uint8_t bleEvent, uint8_t * data, int len)
{
    ChipDeviceEvent event;

    event.Type                             = DeviceEventType::kPlatformTelinkBleDisconnected;
    event.Platform.BleConnEvent.connHandle = BLS_CONN_HANDLE;
    event.Platform.BleConnEvent.HciResult  = *data; // Reason of disconnection stored in first data byte

    PlatformMgr().PostEventOrDie(&event);
}

int BLEManagerImpl::TxCccWriteCallback(uint16_t connHandle, void * p)
{
    ChipDeviceEvent event;
    rf_packet_att_t * packet = (rf_packet_att_t *) p;
    int dataLen              = packet->rf_len - CHIP_RF_PACKET_HEADER_SIZE;
    uint16_t value           = *((uint16_t *) packet->dat);

    event.Type                                 = DeviceEventType::kPlatformTelinkBleCCCWrite;
    event.Platform.BleCCCWriteEvent.connHandle = connHandle;
    event.Platform.BleCCCWriteEvent.Value      = value;

    PlatformMgr().PostEventOrDie(&event);

    return 0;
}

int BLEManagerImpl::GapEventHandler(uint32_t gapEvent, uint8_t * data, int size)
{
    ChipDeviceEvent event;

    if ((gapEvent & 0xFF) == GAP_EVT_GATT_HANDLE_VLAUE_CONFIRM)
    {
        /* Send TX complete event if everything is fine */
        event.Type                                   = DeviceEventType::kPlatformTelinkBleTXComplete;
        event.Platform.BleTXCompleteEvent.connHandle = BLS_CONN_HANDLE;

        PlatformMgr().PostEventOrDie(&event);
    }

    return 0;
}

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

    uint8_t macPublic[CHIP_MAC_LEN]       = { 0 };
    uint8_t macRandomStatic[CHIP_MAC_LEN] = { 0 };
    int ret                               = 0;

    if (ConnectivityMgr().IsThreadProvisioned())
    {
        ChipLogProgress(DeviceLayer, "Thread Provisioned. Ignore");

        return CHIP_ERROR_INCORRECT_STATE;
    }

    /* Reset Radio */
    rf_radio_reset();

    /* Reset DMA */
    rf_reset_dma();

    /* Init Radio driver */
    ble_radio_init();

    /* Generate MAC address if it does not exist or read it from flash if it is exist already */
    blc_initMacAddress(CFG_ADR_MAC_1M_FLASH, macPublic, macRandomStatic);

    /* Init interrupts and DMA for BLE module ??? */
    blc_ll_initBasicMCU();

    /* Setup MAC Address */
    blc_ll_initStandby_module(macPublic);

    /* Init advertisement */
    blc_ll_initAdvertising_module();

    /* Init slave role */
    blc_ll_initSlaveRole_module();

    /* Init connection mode */
    blc_ll_initConnection_module();

    /* Init GAP */
    err = _InitGap();
    SuccessOrExit(err);

    /* Resetup stimer interrupt to handle BLE stack */
    ret = irq_connect_dynamic(STIMER_IRQ_NUM + CONFIG_2ND_LVL_ISR_TBL_OFFSET, 2, stimer_irq_handler, NULL, 0);
    ChipLogDetail(DeviceLayer, "Stimer IRQ assigned vector %d", ret);

    /* Resetup rf interrupt to handle BLE stack */
    ret = irq_connect_dynamic(RF_IRQ_NUM + CONFIG_2ND_LVL_ISR_TBL_OFFSET, 2, rf_irq_handler, NULL, 0);
    ChipLogDetail(DeviceLayer, "RF IRQ assigned vector %d", ret);

exit:

    return err;
}

CHIP_ERROR BLEManagerImpl::_InitGap(void)
{
    ble_sts_t status = BLE_SUCCESS;
    /* Fifo buffers */
    static u8 txFifoBuff[CHIP_BLE_TX_FIFO_SIZE * CHIP_BLE_TX_FIFO_NUM] = { 0 };
    static u8 rxFifoBuff[CHIP_BLE_RX_FIFO_SIZE * CHIP_BLE_RX_FIFO_NUM] = { 0 };

    status = blc_ll_initAclConnTxFifo(txFifoBuff, CHIP_BLE_TX_FIFO_SIZE, CHIP_BLE_TX_FIFO_NUM);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to init BLE TX FIFO. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    status = blc_ll_initAclConnRxFifo(rxFifoBuff, CHIP_BLE_RX_FIFO_SIZE, CHIP_BLE_RX_FIFO_NUM);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to init BLE RX FIFO. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    status = blc_controller_check_appBufferInitialization();
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Buffer initialization check failed. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    /* Init GAP */
    blc_gap_peripheral_init();

    /* Set up GATT Services */
    _InitGatt();

    /* L2CAP Initialization */
    blc_l2cap_register_handler((void *) blc_l2cap_packet_receive);

    /* Setup connect/terminate callbacks */
    bls_app_registerEventCallback(BLT_EV_FLAG_CONNECT, BLEManagerImpl::ConnectCallback);
    bls_app_registerEventCallback(BLT_EV_FLAG_TERMINATE, BLEManagerImpl::DisconnectCallback);

    /* Add GAP event handler to handle indication send */
    blc_gap_registerHostEventHandler(BLEManagerImpl::GapEventHandler);
    blc_gap_setEventMask(GAP_EVT_MASK_GATT_HANDLE_VLAUE_CONFIRM);

    /* Set MTU */
    status = blc_att_setRxMtuSize(CHIP_MTU_SIZE);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to set MTU size. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    return CHIP_NO_ERROR;
}

void BLEManagerImpl::_InitGatt(void)
{
    /* UUIDs */
    static const u16 primaryServiceUUID     = GATT_UUID_PRIMARY_SERVICE;
    static const u16 gapServiceUUID         = SERVICE_UUID_GENERIC_ACCESS;
    static const u16 characterUUID          = GATT_UUID_CHARACTER;
    static const u16 devNameUUID            = GATT_UUID_DEVICE_NAME;
    static const u16 gattServiceUUID        = SERVICE_UUID_GENERIC_ATTRIBUTE;
    static const u16 serviceChangeUUID      = GATT_UUID_SERVICE_CHANGE;
    static const u16 clientCharacterCfgUUID = GATT_UUID_CLIENT_CHAR_CFG;
    static const u16 devServiceUUID         = SERVICE_UUID_DEVICE_INFORMATION;
    static const u16 appearanceUUID         = GATT_UUID_APPEARANCE;
    static const u16 periConnParamUUID      = GATT_UUID_PERI_CONN_PARAM;
    static const u8 MatterRxCharUUID[]      = WRAPPING_BRACES(CHIP_RX_CHAR_UUID);
    static const u8 MatterTxCharUUID[]      = WRAPPING_BRACES(CHIP_TX_CHAR_UUID);

    /* Characteristics */
    static const u8 devNameCharVal[] = { CHAR_PROP_READ | CHAR_PROP_NOTIFY, U16_LO(GenericAccess_DeviceName_DP_H),
                                         U16_HI(GenericAccess_DeviceName_DP_H), U16_LO(GATT_UUID_DEVICE_NAME),
                                         U16_HI(GATT_UUID_DEVICE_NAME) };

    static const u8 appearanceCharVal[] = { CHAR_PROP_READ, U16_LO(GenericAccess_Appearance_DP_H),
                                            U16_HI(GenericAccess_Appearance_DP_H), U16_LO(GATT_UUID_APPEARANCE),
                                            U16_HI(GATT_UUID_APPEARANCE) };

    static const u8 periConnParamCharVal[] = { CHAR_PROP_READ, U16_LO(CONN_PARAM_DP_H), U16_HI(CONN_PARAM_DP_H),
                                               U16_LO(GATT_UUID_PERI_CONN_PARAM), U16_HI(GATT_UUID_PERI_CONN_PARAM) };

    static const u8 serviceChangeCharVal[] = { CHAR_PROP_INDICATE, U16_LO(GenericAttribute_ServiceChanged_DP_H),
                                               U16_HI(GenericAttribute_ServiceChanged_DP_H), U16_LO(GATT_UUID_SERVICE_CHANGE),
                                               U16_HI(GATT_UUID_SERVICE_CHANGE) };

    static const u8 MatterRxCharVal[] = { CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RSP, U16_LO(Matter_RX_DP_H),
                                          U16_HI(Matter_RX_DP_H), CHIP_RX_CHAR_UUID };

    static const u8 MatterTxCharVal[] = { CHAR_PROP_INDICATE, U16_LO(Matter_TX_DP_H), U16_HI(Matter_TX_DP_H), CHIP_TX_CHAR_UUID };

    /* Values */
    static const u16 appearance                             = GAP_APPEARE_UNKNOWN;
    static const gap_periConnectParams_t periConnParameters = { 8, 11, 0, 1000 };
    static u16 serviceChangeVal[2]                          = { 0 };
    static u8 serviceChangeCCC[2]                           = { 0 };
    static u8 matterTxCCC[2]                                = { 0 };

    static const attribute_t gattTable[] = {
        /* Total number of attributes */
        { ATT_END_H - 1, 0, 0, 0, 0, 0 },

        /* 0001 - 0007  GAP service */
        { 7, ATT_PERMISSIONS_READ, 2, 2, (u8 *) (&primaryServiceUUID), (u8 *) (&gapServiceUUID), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(devNameCharVal), (u8 *) (&characterUUID), (u8 *) (devNameCharVal), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, (u32) kMaxDeviceNameLength, (u8 *) (&devNameUUID), (u8 *) (mDeviceName), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(appearanceCharVal), (u8 *) (&characterUUID), (u8 *) (appearanceCharVal), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(appearance), (u8 *) (&appearanceUUID), (u8 *) (&appearance), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(periConnParamCharVal), (u8 *) (&characterUUID), (u8 *) (periConnParamCharVal), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(periConnParameters), (u8 *) (&periConnParamUUID), (u8 *) (&periConnParameters), 0 },

        /* 0008 - 000b GATT */
        { 4, ATT_PERMISSIONS_READ, 2, 2, (u8 *) (&primaryServiceUUID), (u8 *) (&gattServiceUUID), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(serviceChangeCharVal), (u8 *) (&characterUUID), (u8 *) (serviceChangeCharVal), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(serviceChangeVal), (u8 *) (&serviceChangeUUID), (u8 *) (&serviceChangeVal), 0 },
        { 0, ATT_PERMISSIONS_RDWR, 2, sizeof(serviceChangeCCC), (u8 *) (&clientCharacterCfgUUID), (u8 *) (serviceChangeCCC), 0 },

        /* 000c - 0011 Matter service */
        { 6, ATT_PERMISSIONS_READ, 2, 2, (u8 *) (&primaryServiceUUID), (u8 *) (&matterServiceUUID), 0 },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(MatterRxCharVal), (u8 *) (&characterUUID), (u8 *) (MatterRxCharVal), 0 },
        { 0, ATT_PERMISSIONS_RDWR, 16, sizeof(mRxDataBuff), (u8 *) (&MatterRxCharUUID), mRxDataBuff, RxWriteCallback, NULL },
        { 0, ATT_PERMISSIONS_READ, 2, sizeof(MatterTxCharVal), (u8 *) (&characterUUID), (u8 *) (MatterTxCharVal), 0 },
        { 0, ATT_PERMISSIONS_RDWR, 16, sizeof(mTxDataBuff), (u8 *) (&MatterTxCharUUID), mTxDataBuff, 0 },
        { 0, ATT_PERMISSIONS_RDWR, 2, sizeof(matterTxCCC), (u8 *) (&clientCharacterCfgUUID), (u8 *) (matterTxCCC),
          TxCccWriteCallback, NULL }
    };

    bls_att_setAttributeTable((u8 *) gattTable);
}

CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
{
    ble_sts_t status   = BLE_SUCCESS;
    CHIP_ERROR err     = CHIP_NO_ERROR;
    uint8_t index      = 0;
    uint8_t devNameLen = 0;
    ChipBLEDeviceIdentificationInfo deviceIdInfo;
    u8 adv[CHIP_MAX_ADV_DATA_LEN]       = { 0 };
    u8 srsp[CHIP_MAX_RESPONSE_DATA_LEN] = { 0 };

    ChipLogProgress(DeviceLayer, "BLEManagerImpl::ConfigureAdvertisingData");

    /* Get BLE device identification info */
    err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
    SuccessOrExit(err);

    /* Check device name */
    if (!mFlags.Has(Flags::kDeviceNameSet))
    {
        err = _SetDeviceName("TelinkMatter");
        SuccessOrExit(err);
    }

    /* Fulfill BLE advertisement data */
    /* Set flags */
    adv[index++] = CHIP_ADE_DATA_LEN_FLAGS;
    adv[index++] = CHIP_ADV_DATA_TYPE_FLAGS;
    adv[index++] = CHIP_ADV_DATA_FLAGS;

    /* Set Service Data */
    adv[index++] = CHIP_ADV_SERVICE_DATA_LEN;
    adv[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA;
    adv[index++] = matterServiceUUID[0];
    adv[index++] = matterServiceUUID[1];
    memcpy(&adv[index], (void *) &deviceIdInfo, sizeof(deviceIdInfo));
    index += sizeof(deviceIdInfo);

    /* Set device name */
    devNameLen   = strlen(mDeviceName);
    adv[index++] = devNameLen + 1;
    adv[index++] = CHIP_ADV_DATA_TYPE_NAME;
    memcpy(&adv[index], mDeviceName, devNameLen);
    index += devNameLen;

    /* Set advetisment data */
    status = bls_ll_setAdvData(adv, index);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to set BLE advertisement data. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    index         = 0;
    srsp[index++] = CHIP_SHORT_UUID_LEN + 1;
    srsp[index++] = CHIP_ADV_DATA_TYPE_UUID;
    srsp[index++] = matterServiceUUID[0];
    srsp[index++] = matterServiceUUID[1];

    /* Set scan response data */
    status = bls_ll_setScanRspData(srsp, sizeof(srsp));
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to set BLE scan response data. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

exit:
    return err;
}

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

    VerifyOrReturnError(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported,
                        CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);

    if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
    {
        ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off");

        mFlags.Set(Flags::kAdvertisingEnabled, val);
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }

    return err;
}

CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
{
    CHIP_ERROR err   = CHIP_NO_ERROR;
    ble_sts_t status = BLE_SUCCESS;

    /* At first run always select fast advertising, on the next attempt slow down interval. */
    u16 intervalMin = mFlags.Has(Flags::kFastAdvertisingEnabled) ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN
                                                                 : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
    u16 intervalMax = mFlags.Has(Flags::kFastAdvertisingEnabled) ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX
                                                                 : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;

    if (ConnectivityMgr().IsThreadProvisioned())
    {
        ChipLogProgress(DeviceLayer, "Thread provisioned. Start advertisement not possible");

        return CHIP_ERROR_INCORRECT_STATE;
    }

    /* Block IEEE802154 */
    /* @todo: move to RadioSwitch module*/
    const struct device * radio_dev = device_get_binding(CONFIG_NET_CONFIG_IEEE802154_DEV_NAME);
    __ASSERT(radio_dev != NULL, "Fail to get radio device");
    b91_deinit(radio_dev);

    /* It is time to init BLE stack */
    err = _InitStack();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Fail to init BLE stack");

        return err;
    }

    /* Configure CHIP BLE advertisement data */
    err = ConfigureAdvertisingData();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Fail to config BLE advertisement data");

        return err;
    }

    /* Setup advertisement parameters */
    status = bls_ll_setAdvParam(intervalMin, intervalMax, ADV_TYPE_CONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, 0, NULL,
                                BLT_ENABLE_ADV_ALL, ADV_FP_NONE);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to set BLE advertisement parameters. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    /* Enable advertisement */
    status = bls_ll_setAdvEnable(BLC_ADV_ENABLE);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to start BLE advertisement. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Transition to the Advertising state...
    if (!mFlags.Has(Flags::kAdvertising))
    {
        ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");

        mFlags.Set(Flags::kAdvertising);

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

        if (mFlags.Has(Flags::kFastAdvertisingEnabled))
        {
            // Start timer to change advertising interval.
            DeviceLayer::SystemLayer().StartTimer(
                System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME),
                HandleBLEAdvertisementIntervalChange, this);
        }
    }

    /* Start BLE Task */
    k_thread_resume(chipBleThread);

    return err;
}

CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
{
    ble_sts_t status = BLE_SUCCESS;

    if (ConnectivityMgr().IsThreadProvisioned())
    {
        ChipLogProgress(DeviceLayer, "Thread provisioned. Advertisement already stopped at this stage");

        return CHIP_ERROR_INCORRECT_STATE;
    }

    /* Disable advertisement */
    status = bls_ll_setAdvEnable(BLC_ADV_DISABLE);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to stop BLE advertisement. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Transition to the not Advertising state...
    if (mFlags.Has(Flags::kAdvertising))
    {
        mFlags.Clear(Flags::kAdvertising);
        mFlags.Set(Flags::kFastAdvertisingEnabled, true);

        ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");

        // Post a CHIPoBLEAdvertisingChange(Stopped) event.
        {
            ChipDeviceEvent advChange;
            advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
            advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
            ReturnErrorOnFailure(PlatformMgr().PostEvent(&advChange));
        }

        // Cancel timer event changing CHIPoBLE advertisement interval
        DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this);
    }

    return CHIP_NO_ERROR;
}

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::kAdvertisingRefreshNeeded);
    PlatformMgr().ScheduleWork(DriveBLEState, 0);
    return CHIP_NO_ERROR;
}

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

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
{

    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
    {
        ChipLogError(DeviceLayer, "Unsupported");

        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
    }

    if (devName == NULL || devName[0] == 0)
    {
        ChipLogError(DeviceLayer, "Invalid name");

        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (strlen(devName) >= kMaxDeviceNameLength)
    {
        ChipLogError(DeviceLayer, "BLE device name is to long");

        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    strcpy(mDeviceName, devName);
    mFlags.Set(Flags::kDeviceNameSet);

    ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", devName);

    return CHIP_NO_ERROR;
}

void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param)
{
    BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
    ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow");
}

void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    switch (event->Type)
    {
    case DeviceEventType::kPlatformTelinkBleConnected:
        err = HandleGAPConnect(event);
        break;

    case DeviceEventType::kPlatformTelinkBleDisconnected:
        err = HandleGAPDisconnect(event);
        break;

    case DeviceEventType::kPlatformTelinkBleDisconnectRequest:
        err = HandleDisconnectRequest(event);
        break;

    case DeviceEventType::kPlatformTelinkBleRXWrite:
        err = HandleRXCharWrite(event);
        break;

    case DeviceEventType::kPlatformTelinkBleCCCWrite:
        err = HandleTXCharCCCDWrite(event);
        break;

    case DeviceEventType::kPlatformTelinkBleTXComplete:
        err = HandleTXCharComplete(event);
        break;

    case DeviceEventType::kThreadStateChange:
        err = HandleThreadStateChange(event);
        break;

    case DeviceEventType::kCHIPoBLEConnectionClosed:
        err = HandleBleConnectionClosed(event);
        break;

    case DeviceEventType::kOperationalNetworkEnabled:
        err = HandleOperationalNetworkEnabled(event);
        break;

    default:
        ChipLogDetail(DeviceLayer, "Event: Unknown (0x%04x)", event->Type);
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Fail to handle 0x%04x event. Error: %s", event->Type, ErrorStr(err));
        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
        PlatformMgr().ScheduleWork(DriveBLEState, 0);
    }
}

bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    return false;
}

bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
    return false;
}

bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
{
    return false;
}

uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
{
    return blc_att_getEffectiveMtuSize(conId);
}

bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                    PacketBufferHandle pBuf)
{
    ble_sts_t status = BLE_SUCCESS;

    do
    {
        if (status != BLE_SUCCESS)
        {
            k_msleep(1);
        }
        status = blc_gatt_pushHandleValueIndicate(conId, Matter_TX_DP_H, pBuf->Start(), pBuf->DataLength());
    } while (status == GATT_ERR_DATA_PENDING_DUE_TO_SERVICE_DISCOVERY_BUSY);
    if (status != BLE_SUCCESS)
    {
        ChipLogError(DeviceLayer, "Fail to send indication. Error %d", status);

        return false;
    }

    return true;
}

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

/* @todo: move to RadioSwitch module */
void BLEManagerImpl::SwitchToIeee802154(void)
{
    int result = 0;

    ChipLogProgress(DeviceLayer, "BLEManagerImpl::Switch to IEEE802154");

    /* Stop BLE */
    _SetAdvertisingEnabled(false);

    /* Stop BLE task */
    k_thread_suspend(chipBleThread);

    /* Reset Radio */
    rf_radio_reset();

    /* Reset DMA */
    rf_reset_dma();

    const struct device * radio_dev = device_get_binding(CONFIG_NET_CONFIG_IEEE802154_DEV_NAME);
    __ASSERT(radio_dev != NULL, "Fail to get radio device");

    /* Init IEEE802154 */
    result = b91_init(radio_dev);
    __ASSERT(result == 0, "Fail to init IEEE802154 radio. Error: %d", result);
}

void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}

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

/// @todo implement multicinnection subscription
CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
{

    mSubscribedConns[0] = true;

    return CHIP_NO_ERROR;
}

/// @todo implement multicinnection subscription
bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
{

    mSubscribedConns[0] = false;

    return true;
}

/// @todo implement multicinnection subscription
bool BLEManagerImpl::IsSubscribed(uint16_t conId)
{
    return mSubscribedConns[0];
}

CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event)
{
    const BleConnEventType * connEvent = &event->Platform.BleConnEvent;

    ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02x)", connEvent->connHandle);
    mGAPConns++;
    ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), kMaxConnections);

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

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event)
{
    const BleConnEventType * connEvent = &event->Platform.BleConnEvent;

    ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02x)", connEvent->HciResult);

    mGAPConns--;

    ChipLogProgress(DeviceLayer, "Current number of connections: %u/%u", NumConnections(), kMaxConnections);

    // Unsubscribe
    if (UnsetSubscribed(connEvent->connHandle))
    {
        HandleUnsubscribeReceived(connEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
    }

    ChipDeviceEvent disconnectEvent;
    disconnectEvent.Type = DeviceEventType::kCHIPoBLEConnectionClosed;
    ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent));

    // Force a reconfiguration of advertising in case we switched to non-connectable mode when
    // the BLE connection was established.
    mFlags.Set(Flags::kAdvertisingRefreshNeeded);
    PlatformMgr().ScheduleWork(DriveBLEState, 0);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleDisconnectRequest(const ChipDeviceEvent * event)
{
    ble_sts_t status = BLE_SUCCESS;
    uint16_t handle  = event->Platform.BleConnEvent.connHandle;
    uint8_t reason   = event->Platform.BleConnEvent.HciResult;

    ChipLogDetail(DeviceLayer, "HandleDisconnectRequest");

    /* Trigger disconnect. DisconnectCallback call occures on completion */
    status = blc_ll_disconnect(handle, reason);
    if (status != BLE_SUCCESS && status != LL_ERR_CONNECTION_NOT_ESTABLISH)
    {
        ChipLogError(DeviceLayer, "Fail to disconnect. Error %d", status);

        return CHIP_ERROR_INCORRECT_STATE;
    }

    // Force a reconfiguration of advertising in case we switched to non-connectable mode when
    // the BLE connection was established.
    mFlags.Set(Flags::kAdvertisingRefreshNeeded);
    PlatformMgr().ScheduleWork(DriveBLEState, 0);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleOperationalNetworkEnabled(const ChipDeviceEvent * event)
{
    ChipDeviceEvent disconnectEvent;

    ChipLogDetail(DeviceLayer, "HandleOperationalNetworkEnabled");

    disconnectEvent.Type                             = DeviceEventType::kPlatformTelinkBleDisconnectRequest;
    disconnectEvent.Platform.BleConnEvent.connHandle = BLS_CONN_HANDLE;
    disconnectEvent.Platform.BleConnEvent.HciResult  = CHIP_BLE_DISCONNECT_REASON;
    ReturnErrorOnFailure(PlatformMgr().PostEvent(&disconnectEvent));

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleThreadStateChange(const ChipDeviceEvent * event)
{
    CHIP_ERROR error = CHIP_NO_ERROR;

    ChipLogDetail(DeviceLayer, "HandleThreadStateChange");

    if (event->Type == DeviceEventType::kThreadStateChange && event->ThreadStateChange.RoleChanged)
    {
        ChipDeviceEvent attachEvent;
        attachEvent.Type                            = DeviceEventType::kThreadConnectivityChange;
        attachEvent.ThreadConnectivityChange.Result = kConnectivity_Established;

        error = PlatformMgr().PostEvent(&attachEvent);
        VerifyOrExit(error == CHIP_NO_ERROR,
                     ChipLogError(DeviceLayer, "Failed to post Thread connectivity change: %" CHIP_ERROR_FORMAT, error.Format()));

        ChipLogDetail(DeviceLayer, "Thread Connectivity Ready");
        ThreadConnectivityReady = true;
    }

exit:
    return error;
}

CHIP_ERROR BLEManagerImpl::HandleBleConnectionClosed(const ChipDeviceEvent * event)
{
    /* It is time to swich to IEEE802154 radio if it is provisioned */
    if (ThreadConnectivityReady)
    {
        SwitchToIeee802154();
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event)
{
    const BleRXWriteEventType * writeEvent = &event->Platform.BleRXWriteEvent;

    ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX (ConnId 0x%02x)", writeEvent->connHandle);

    HandleWriteReceived(writeEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
                        PacketBufferHandle::Adopt(writeEvent->Data));

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleTXCharComplete(const ChipDeviceEvent * event)
{
    const BleTXCompleteEventType * completeEvent = &event->Platform.BleTXCompleteEvent;

    ChipLogDetail(DeviceLayer, "Notification for CHIPoBLE TX done (ConnId 0x%02x)", completeEvent->connHandle);

    // Signal the BLE Layer that the outstanding notification is complete.
    HandleIndicationConfirmation(completeEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event)
{
    const BleCCCWriteEventType * writeEvent = &event->Platform.BleCCCWriteEvent;

    ChipLogDetail(DeviceLayer, "ConnId: 0x%02x, New CCCD value: 0x%04x", writeEvent->connHandle, writeEvent->Value);

    /* If the client has requested to enable notifications and if it is not yet subscribed */
    if (writeEvent->Value != 0 && SetSubscribed(writeEvent->connHandle) == CHIP_NO_ERROR)
    {
        /* Alert the BLE layer that CHIPoBLE "subscribe" has been received and increment the bt_conn reference counter. */
        HandleSubscribeReceived(writeEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);

        ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02x, GATT MTU: %d)", writeEvent->connHandle,
                        GetMTU(writeEvent->connHandle));

        /* Post a CHIPoBLEConnectionEstablished event to the DeviceLayer and the application. */
        {
            ChipDeviceEvent conEstEvent;
            conEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
            ReturnErrorOnFailure(PlatformMgr().PostEvent(&conEstEvent));
        }
    }
    else
    {
        if (UnsetSubscribed(writeEvent->connHandle))
        {
            HandleUnsubscribeReceived(writeEvent->connHandle, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
        }
    }

    return CHIP_NO_ERROR;
}

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

#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
