/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    Copyright (c) 2014-2017 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
 *      This file defines objects that provide an abstraction layer between a
 *      platform's Bluetooth Low Energy (BLE) implementation and the CHIP
 *      stack.
 *
 *      The BleLayer object accepts BLE data and control input from the
 *      application via a functional interface. It performs the fragmentation
 *      and reassembly required to transmit CHIP message via a BLE GATT
 *      characteristic interface, and drives incoming messages up the CHIP
 *      stack.
 *
 *      During initialization, the BleLayer object requires a pointer to the
 *      platform's implementation of the BleAdapter object. This object is
 *      defined but not implemented by the CHIP stack, and provides the
 *      BleLayer with a functional interface to drive outgoing GATT
 *      characteristic writes and indications. It also provides a mechanism
 *      for CHIP to inform the application when it has finished using a given
 *      BLE connection, i.e., when the chipConnection object wrapping this
 *      connection has closed.
 *
 *      To enable CHIP over BLE for a new platform, the application developer
 *      must implement the BleAdapter class for their platform, pass it to the
 *      BleLayer on startup, pass a pointer to this BleLayer to their instance
 *      of chipMessageLayer, and ensure that the application calls the
 *      necessary BleLayer functions to drive BLE data and control input up the
 *      stack.
 */

#pragma once

#ifndef _CHIP_BLE_BLE_H
#error "Please include <ble/Ble.h> instead!"
#endif

#include <cstddef>
#include <cstdint>

#include <lib/core/CHIPError.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/SetupDiscriminator.h>
#include <system/SystemLayer.h>
#include <system/SystemPacketBuffer.h>

#include "BleApplicationDelegate.h"
#include "BleConfig.h"
#include "BleConnectionDelegate.h"
#include "BleLayerDelegate.h"
#include "BlePlatformDelegate.h"
#include "BleRole.h"
#include "BleUUID.h"

namespace chip {
namespace Ble {

/**
 *  @def NUM_SUPPORTED_PROTOCOL_VERSIONS
 *
 *  Number of unsigned 4-bit representations of supported transport protocol
 *  versions encapsulated in a BleTransportCapabilitiesRequest. Defined by CHIP
 *  over BLE protocol specification.
 */
#define NUM_SUPPORTED_PROTOCOL_VERSIONS 8
/// Version(s) of the CHIP BLE Transport Protocol that this stack supports.
#define CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION kBleTransportProtocolVersion_V4
#define CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION kBleTransportProtocolVersion_V4

/// Enum defining versions of CHIP over BLE transport protocol.
typedef enum
{
    kBleTransportProtocolVersion_None = 0,
    kBleTransportProtocolVersion_V4   = 4 // BTP as defined by CHIP v1.0
} BleTransportProtocolVersion;

inline constexpr size_t kCapabilitiesRequestMagicnumLength          = 2;
inline constexpr size_t kCapabilitiesRequestL2capMtuLength          = 2;
inline constexpr size_t kCapabilitiesRequestSupportedVersionsLength = 4;
inline constexpr size_t kCapabilitiesRequestWindowSizeLength        = 1;
constexpr size_t kCapabilitiesRequestLength = (kCapabilitiesRequestMagicnumLength + kCapabilitiesRequestL2capMtuLength +
                                               kCapabilitiesRequestSupportedVersionsLength + kCapabilitiesRequestWindowSizeLength);

inline constexpr size_t kCapabilitiesResponseMagicnumLength                = 2;
inline constexpr size_t kCapabilitiesResponseL2capMtuLength                = 2;
inline constexpr size_t kCapabilitiesResponseSelectedProtocolVersionLength = 1;
inline constexpr size_t kCapabilitiesResponseWindowSizeLength              = 1;
constexpr size_t kCapabilitiesResponseLength(kCapabilitiesResponseMagicnumLength + kCapabilitiesResponseL2capMtuLength +
                                             kCapabilitiesResponseSelectedProtocolVersionLength +
                                             kCapabilitiesResponseWindowSizeLength);

class BleTransportCapabilitiesRequestMessage
{
public:
    /**
     * An array of size NUM_SUPPORTED_PROTOCOL_VERSIONS listing versions of the
     * BLE transport protocol that this node supports. Each protocol version is
     * specified as a 4-bit unsigned integer. A zero-value represents unused
     * array elements. Counting up from the zero-index, the first zero-value
     * specifies the end of the list of supported protocol versions.
     */
    uint8_t mSupportedProtocolVersions[(NUM_SUPPORTED_PROTOCOL_VERSIONS / 2) + (NUM_SUPPORTED_PROTOCOL_VERSIONS % 2)];

    /**
     *  The MTU that has been negotiated for this BLE connection. Specified in
     *  the BleTransportCapabilitiesRequestMessage because the remote node may
     *  be unable to glean this info from its own BLE hardware/software stack,
     *  such as on older Android platforms.
     *
     *  A value of 0 means that the central could not determine the negotiated
     *  BLE connection MTU.
     */
    uint16_t mMtu;

    /**
     *  The initial and maximum receive window size offered by the central,
     *  defined in terms of GATT indication payloads.
     */
    uint8_t mWindowSize;

    /**
     *  Set supported version value at given index in
     *  SupportedProtocolVersions. uint8_t version argument is truncated to 4
     *  least-significant bits. Index shall be 0 through number of
     *  SupportedProtocolVersions elements - 1.
     */
    void SetSupportedProtocolVersion(uint8_t index, uint8_t version);

    /// Must be able to reserve 20 byte data length in msgBuf.
    CHIP_ERROR Encode(const System::PacketBufferHandle & msgBuf) const;

    static CHIP_ERROR Decode(const System::PacketBufferHandle & msgBuf, BleTransportCapabilitiesRequestMessage & msg);
};

class BleTransportCapabilitiesResponseMessage
{
public:
    /**
     *  The lower 4 bits specify the BLE transport protocol version that the BLE
     *  peripheral has selected for this connection.
     *
     *  A value of kBleTransportProtocolVersion_None means that no supported
     *  protocol version was found in the central's capabilities request. The
     *  central should unsubscribe after such a response has been sent to free
     *  up the peripheral for connections from devices with supported protocol
     *  versions.
     */
    uint8_t mSelectedProtocolVersion;

    /**
     *  BLE transport fragment size selected by peripheral in response to MTU
     *  value in BleTransportCapabilitiesRequestMessage and its local
     *  observation of the BLE connection MTU.
     */
    uint16_t mFragmentSize;

    /**
     *  The initial and maximum receive window size offered by the peripheral,
     *  defined in terms of GATT write payloads.
     */
    uint8_t mWindowSize;

    /// Must be able to reserve 20 byte data length in msgBuf.
    CHIP_ERROR Encode(const System::PacketBufferHandle & msgBuf) const;

    static CHIP_ERROR Decode(const System::PacketBufferHandle & msgBuf, BleTransportCapabilitiesResponseMessage & msg);
};

/**
 *  @class BleLayer
 *
 *  @brief
 *    This class provides an interface for a single thread to drive data
 *    either up the stack via the BleLayer platform interface functions,
 *    or down the stack via a chipConnection object associated with a
 *    BLEEndPoint.
 *
 *    There are two ways to associate a chipConnection (defined by the
 *    chipMessageLayer) with a BLE connection:
 *
 *    First, the application can passively receive an incoming BLE connection
 *    and hand the platform-specific BLE_CONNECTION_OBJECT that this receipt
 *    generates to BleLayer via the corresponding platform interface function.
 *    This causes BleLayer to wrap the BLE_CONNECTION_OBJECT in a BLEEndPoint,
 *    and notify chipMessageLayer that a new BLE connection has been received.
 *    The message layer then wraps the new BLEEndPoint object in a
 *    chipConnection, and hands this object to the application via the message
 *    layer's OnConnectionReceived callback.
 *
 *    Second, the application can actively form an outgoing BLE connection, e.g.,
 *    by connecting to a BLE peripheral. It then creates a new chipConnection
 *    via the chipMessageLayer, assigns an authentication type to this
 *    connection, and binds it to the BLE_CONNECTION_OBJECT for the new BLE
 *    connection via chipConnection::ConnectBle. This function then
 *    establishes the secure session type specified by the chipConnection's
 *    authentication type member variable.
 *
 */
class DLL_EXPORT BleLayer
{
    friend class BLEEndPoint;

public:
    // Public data members:
    enum
    {
        kState_NotInitialized = 0,
        kState_Initialized    = 1,
        kState_Disconnecting  = 2
    } mState; ///< [READ-ONLY] Current state

    // This app state is not used by ble transport etc, it will be used by external ble implementation like Android
    void * mAppState                 = nullptr;
    BleLayerDelegate * mBleTransport = nullptr;

    // Public functions:
    BleLayer();

    CHIP_ERROR Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate,
                    chip::System::Layer * systemLayer);
    CHIP_ERROR Init(BlePlatformDelegate * platformDelegate, BleConnectionDelegate * connDelegate,
                    BleApplicationDelegate * appDelegate, chip::System::Layer * systemLayer);
    void IndicateBleClosing();
    void Shutdown();

    CHIP_ERROR CancelBleIncompleteConnection();
    CHIP_ERROR NewBleConnectionByDiscriminator(const SetupDiscriminator & connDiscriminator, void * appState = nullptr,
                                               BleConnectionDelegate::OnConnectionCompleteFunct onSuccess = OnConnectionComplete,
                                               BleConnectionDelegate::OnConnectionErrorFunct onError      = OnConnectionError);
    CHIP_ERROR NewBleConnectionByObject(BLE_CONNECTION_OBJECT connObj, void * appState,
                                        BleConnectionDelegate::OnConnectionCompleteFunct onSuccess = OnConnectionComplete,
                                        BleConnectionDelegate::OnConnectionErrorFunct onError      = OnConnectionError);
    CHIP_ERROR NewBleConnectionByObject(BLE_CONNECTION_OBJECT connObj);
    CHIP_ERROR NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose);

    void CloseAllBleConnections();
    void CloseBleConnection(BLE_CONNECTION_OBJECT connObj);

    /**< Platform interface functions:

     *   Calling conventions:
     *     CHIP takes ownership of PacketBuffers received through these functions,
     *     and will free them or pass ownership up the stack.
     *
     *     Beyond each call, no guarantees are provided as to the lifetime of UUID arguments.
     *
     *     A 'true' return value means the CHIP stack successfully handled the corresponding message
     *     or state indication. 'false' means the CHIP stack either failed or chose not to handle this.
     *     This contract allows the platform to pass BLE events to CHIP without needing to know which
     *     characteristics CHIP cares about.

     *     Platform must call this function when a GATT subscription has been established to any CHIP service
     *     characteristic.
     *
     *     If this function returns true, CHIP has accepted the BLE connection and wrapped it
     *     in a chipConnection object. If CHIP accepts a BLE connection, the platform MUST
     *     notify CHIP if the subscription is canceled or the underlying BLE connection is
     *     closed, or the associated chipConnection will never be closed or freed. */
    bool HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /// Call when a GATT subscribe request succeeds.
    bool HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /**< Platform must call this function when a GATT unsubscribe is requested on any CHIP
     *   service characteristic, that is, when an existing GATT subscription on a CHIP service
     *   characteristic is canceled. */
    bool HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /// Call when a GATT unsubscribe request succeeds.
    bool HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /// Call when a GATT write request is received.
    bool HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                             System::PacketBufferHandle && pBuf);

    /// Call when a GATT indication is received.
    bool HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
                                  System::PacketBufferHandle && pBuf);

    /// Call when an outstanding GATT write request receives a positive receipt confirmation.
    bool HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /// Call when an outstanding GATT indication receives a positive receipt confirmation.
    bool HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId);

    /**< Platform must call this function when any previous operation undertaken by the BleLayer via BleAdapter
     *   fails, such as a characteristic write request or subscribe attempt, or when a BLE connection is closed.
     *
     *   In most cases, this will prompt CHIP to close the associated chipConnection and notify that platform that
     *   it has abandoned the underlying BLE connection.
     *
     *   NOTE: if the application explicitly closes a BLE connection with an associated chipConnection such that
     *   the BLE connection close will not generate an upcall to CHIP, HandleConnectionError must be called with
     *   err = BLE_ERROR_APP_CLOSED_CONNECTION to prevent the leak of this chipConnection and its end point object. */
    void HandleConnectionError(BLE_CONNECTION_OBJECT connObj, CHIP_ERROR err);

private:
    // Private data members:

    // UUID of CHIP service characteristic used for central writes.
    static const ChipBleUUID CHIP_BLE_CHAR_1_ID;
    // UUID of CHIP service characteristic used for peripheral indications.
    static const ChipBleUUID CHIP_BLE_CHAR_2_ID;
    // UUID of CHIP service characteristic used for additional data
    static const ChipBleUUID CHIP_BLE_CHAR_3_ID;

    BleConnectionDelegate * mConnectionDelegate;
    BlePlatformDelegate * mPlatformDelegate;
    BleApplicationDelegate * mApplicationDelegate;
    chip::System::Layer * mSystemLayer;

    // Private functions:
    void HandleAckReceived(BLE_CONNECTION_OBJECT connObj);
    CHIP_ERROR HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, System::PacketBufferHandle && pBuf);

    static BleTransportProtocolVersion GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg);

    static void OnConnectionComplete(void * appState, BLE_CONNECTION_OBJECT connObj);
    static void OnConnectionError(void * appState, CHIP_ERROR err);
};

} /* namespace Ble */
} /* namespace chip */
