/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 the CHIP Connection object that maintains a BLE connection.
 *
 */

#pragma once

#include <ble/BleConfig.h>

#include <utility>

#include <ble/BleError.h>
#include <ble/BleLayer.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/DLLUtil.h>
#include <system/SystemPacketBuffer.h>
#include <transport/raw/Base.h>

namespace chip {
namespace Transport {

/** Defines listening parameters for setting up a BLE transport */
class BleListenParameters
{
public:
    explicit BleListenParameters(Ble::BleLayer * layer) : mLayer(layer) {}
    BleListenParameters(const BleListenParameters &) = default;
    BleListenParameters(BleListenParameters &&)      = default;

    Ble::BleLayer * GetBleLayer() const { return mLayer; }

    /**
     * PreserveExistingBleLayerTransport controls whether the BleBase transport
     * initialized with these parameters should update the global BleLayer transport
     * if it is already set.
     *
     * This is relevant when there is more than one TransportMgr,
     * for example, when a device is both a commissioner (has a CHIPDeviceController)
     * and a commissionee (has a Server) since each TransportMgr will have a BleBase
     * which can override the global BleLayer transport to point to itself.
     *
     * The default value is true - don't override the global BleLayer transport if it is
     * already set. In other words, the first BleBase to initialize (eg. Server) will be
     * the active BleBase transport, and the second BleBase to initialize (eg. CHIPDeviceController)
     * will need to call BleBase.SetBleLayerTransportToSelf if it needs to commission using BLE.
     *
     * Call SetPreserveExistingBleLayerTransport(false) to set the global
     * BleLayer transport to the BleBase created with these parameters, even if it is already
     * set to another BleBase.
     *
     * Use the BleBase.IsBleLayerTransportSetToSelf() and BleBase.SetBleLayerTransportToSelf
     * methods to toggle between BleBase transports when there is more than one.
     */
    bool PreserveExistingBleLayerTransport() const { return mPreserveExistingBleLayerTransport; }
    BleListenParameters & SetPreserveExistingBleLayerTransport(bool preserveExistingBleLayerTransport)
    {
        mPreserveExistingBleLayerTransport = preserveExistingBleLayerTransport;

        return *this;
    }

private:
    Ble::BleLayer * mLayer;
    bool mPreserveExistingBleLayerTransport = true;
};

/** Implements a transport using BLE.
 *
 *  TODO: BLE transport currently only allow one BLE connection, neet to clearify if we should support multiple BLE connections.
 */
class DLL_EXPORT BLEBase : public Base, public Ble::BleLayerDelegate
{
    /**
     *  The State of the BLE connection
     *
     */
    enum class State
    {
        kNotReady    = 0, /**< State before initialization. */
        kInitialized = 1, /**< State after class is connected and ready. */
        kConnected   = 2, /**< Endpoint connected. */
    };

public:
    BLEBase(System::PacketBufferHandle * packetBuffers, size_t packetBuffersSize) :
        mPendingPackets(packetBuffers), mPendingPacketsSize(packetBuffersSize)
    {}
    ~BLEBase() override;

    /**
     * Initialize a BLE transport to a given peripheral or a given device name.
     *
     * @param param        BLE configuration parameters for this transport
     */
    CHIP_ERROR Init(const BleListenParameters & param);

    CHIP_ERROR SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf) override;

    bool CanSendToPeer(const Transport::PeerAddress & address) override
    {
        return (mState != State::kNotReady) && (address.GetTransportType() == Type::kBle);
    }

    CHIP_ERROR SetEndPoint(Ble::BLEEndPoint * endPoint) override;

    /**
     * Change BLE transport to this
     *
     * This is relevant when there is more than one TransportMgr,
     * for example, when a device is both a commissioner (has a CHIPDeviceController)
     * and a commissionee (has a Server) since each TransportMgr will set
     * the global BleLayer transport to point to itself.
     *
     * In this scenario, the device will need the ability to toggle between a
     * BleLayer transport for commissioner functionality and one for commissionee functionality.
     */
    void SetBleLayerTransportToSelf() { mBleLayer->mBleTransport = this; }
    bool IsBleLayerTransportSetToSelf() { return mBleLayer->mBleTransport == this; }

private:
    void ClearState();

    /**
     * Sends the specified message once a connection has been established.
     *
     * @param msg - what buffer to send once a connection has been established.
     *
     * Ownership of msg is taken over and will be freed at some unspecified time
     * in the future (once connection succeeds/fails).
     */
    CHIP_ERROR SendAfterConnect(System::PacketBufferHandle && msg);

    // Those functions are BLEConnectionDelegate callbacks used when the connection
    // parameters used a name instead of a BLE_CONNECTION_OBJECT.
    void OnBleConnectionComplete(Ble::BLEEndPoint * endPoint) override;
    void OnBleConnectionError(CHIP_ERROR err) override;

    void ClearPendingPackets();

    // Those functions are BLEEndPoint callbacks
    void OnEndPointMessageReceived(Ble::BLEEndPoint * endPoint, System::PacketBufferHandle && buffer) override;
    void OnEndPointConnectComplete(Ble::BLEEndPoint * endPoint, CHIP_ERROR err) override;
    void OnEndPointConnectionClosed(Ble::BLEEndPoint * endPoint, CHIP_ERROR err) override;

    Ble::BleLayer * mBleLayer       = nullptr;          ///< Associated ble layer
    State mState                    = State::kNotReady; ///< State of the BLE transport
    Ble::BLEEndPoint * mBleEndPoint = nullptr;          ///< BLE endpoint used by transport

    // Data to be sent when connections succeed
    System::PacketBufferHandle * mPendingPackets;
    const size_t mPendingPacketsSize;
};

template <size_t kPendingPacketSize>
class BLE : public BLEBase
{
public:
    BLE() : BLEBase(mPendingPackets, kPendingPacketSize) {}

private:
    System::PacketBufferHandle mPendingPackets[kPendingPacketSize];
};

} // namespace Transport
} // namespace chip
