/*
 *
 *    Copyright (c) 2020-2021 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 implements the CHIP Connection object that maintains a BLE connection.
 *
 */

#include <transport/raw/BLE.h>

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

#include <inttypes.h>

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

namespace chip {
namespace Transport {

BLEBase::~BLEBase()
{
    ClearState();
}

void BLEBase::ClearState()
{
    if (mBleLayer)
    {
        mBleLayer->CancelBleIncompleteConnection();
        mBleLayer->OnChipBleConnectReceived = nullptr;
        mBleLayer->mBleTransport            = nullptr;
        mBleLayer                           = nullptr;
    }

    if (mBleEndPoint)
    {
        mBleEndPoint->Close();
        mBleEndPoint = nullptr;
    }

    mState = State::kNotReady;
}

CHIP_ERROR BLEBase::Init(const BleListenParameters & param)
{
    BleLayer * bleLayer = param.GetBleLayer();

    VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(bleLayer != nullptr, CHIP_ERROR_INCORRECT_STATE);

    mBleLayer = bleLayer;
    if (mBleLayer->mBleTransport == nullptr || !param.PreserveExistingBleLayerTransport())
    {
        mBleLayer->mBleTransport = this;
        ChipLogDetail(Inet, "BLEBase::Init - setting/overriding transport");
    }
    else
    {
        ChipLogDetail(Inet, "BLEBase::Init - not overriding transport");
    }
    mBleLayer->OnChipBleConnectReceived = nullptr;

    mState = State::kInitialized;

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEBase::SetEndPoint(Ble::BLEEndPoint * endPoint)
{
    VerifyOrReturnError(endPoint->mState == BLEEndPoint::kState_Connected, CHIP_ERROR_INVALID_ARGUMENT);

    mBleEndPoint = endPoint;

    // Manually trigger the OnConnectComplete callback.
    OnEndPointConnectComplete(endPoint, CHIP_NO_ERROR);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEBase::SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf)
{
    ReturnErrorCodeIf(address.GetTransportType() != Type::kBle, CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorCodeIf(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);

    if (mState == State::kConnected)
    {
        ReturnErrorOnFailure(mBleEndPoint->Send(std::move(msgBuf)));
    }
    else
    {
        ReturnErrorOnFailure(SendAfterConnect(std::move(msgBuf)));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR BLEBase::SendAfterConnect(System::PacketBufferHandle && msg)
{
    CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;

    for (size_t i = 0; i < mPendingPacketsSize; i++)
    {
        if (mPendingPackets[i].IsNull())
        {
            ChipLogDetail(Inet, "Message appended to BLE send queue");
            mPendingPackets[i] = std::move(msg);
            err                = CHIP_NO_ERROR;
            break;
        }
    }

    return err;
}

void BLEBase::OnBleConnectionComplete(Ble::BLEEndPoint * endPoint)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    ChipLogDetail(Inet, "BleConnectionComplete: endPoint %p", endPoint);

    mBleEndPoint = endPoint;

    // Initiate CHIP over BLE protocol connection.
    err = mBleEndPoint->StartConnect();
    SuccessOrExit(err);

exit:
    if (err != CHIP_NO_ERROR)
    {
        if (mBleEndPoint != nullptr)
        {
            mBleEndPoint->Close();
            mBleEndPoint = nullptr;
        }
        ChipLogError(Inet, "Failed to setup BLE endPoint: %" CHIP_ERROR_FORMAT, err.Format());
    }
}

void BLEBase::OnBleConnectionError(CHIP_ERROR err)
{
    ClearPendingPackets();
    ChipLogDetail(Inet, "BleConnection Error: %" CHIP_ERROR_FORMAT, err.Format());
}

void BLEBase::OnEndPointMessageReceived(BLEEndPoint * endPoint, PacketBufferHandle && buffer)
{
    HandleMessageReceived(Transport::PeerAddress(Transport::Type::kBle), std::move(buffer));
}

void BLEBase::OnEndPointConnectComplete(BLEEndPoint * endPoint, CHIP_ERROR err)
{
    mState = State::kConnected;

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Inet, "Failed to establish BLE connection: %" CHIP_ERROR_FORMAT, err.Format());
        OnEndPointConnectionClosed(endPoint, err);
        return;
    }

    for (size_t i = 0; i < mPendingPacketsSize; i++)
    {
        if (!mPendingPackets[i].IsNull())
        {
            err = endPoint->Send(std::move(mPendingPackets[i]));
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Inet, "Deferred sending failed: %" CHIP_ERROR_FORMAT, err.Format());
            }
        }
    }
    ChipLogDetail(Inet, "BLE EndPoint %p Connection Complete", endPoint);
}

void BLEBase::OnEndPointConnectionClosed(BLEEndPoint * endPoint, CHIP_ERROR err)
{
    mState       = State::kInitialized;
    mBleEndPoint = nullptr;
    ClearPendingPackets();
}

void BLEBase::ClearPendingPackets()
{
    ChipLogDetail(Inet, "Clearing BLE pending packets.");
    for (size_t i = 0; i < mPendingPacketsSize; i++)
    {
        mPendingPackets[i] = nullptr;
    }
}

} // namespace Transport
} // namespace chip
