/*
 *
 *    Copyright (c) 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.
 */

#include <lib/support/BytesCircularBuffer.h>

#include <algorithm>
#include <limits>
#include <nlassert.h>
#include <string.h>

#include <lib/support/CodeUtils.h>

namespace chip {

size_t BytesCircularBuffer::Advance(size_t dataLocation, size_t amount) const
{
    dataLocation += amount;
    if (dataLocation >= mCapacity)
        dataLocation -= mCapacity;
    return dataLocation;
}

void BytesCircularBuffer::Read(uint8_t * dest, size_t length, size_t offset) const
{
    // length is an instance of SizeType
    // offset is maximized at sizeof(SizeType) for all use cases.
    static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - sizeof(SizeType),
                  "SizeType too large, may cause overflow");
    VerifyOrDie(StorageUsed() >= offset + length);

    size_t start       = Advance(mDataStart, offset);
    size_t firstPiece  = std::min(mCapacity - start, length);
    size_t secondPiece = length - firstPiece;
    ::memcpy(dest, mStorage + start, firstPiece);
    ::memcpy(dest + firstPiece, mStorage, secondPiece);
}

void BytesCircularBuffer::Write(const uint8_t * source, size_t length)
{
    // Always reserve 1 byte to prevent mDataStart == mDataEnd because then it would be
    // ambiguous whether we have 0 bytes or mCapacity bytes stored.
    VerifyOrDie(StorageAvailable() - 1 >= length);

    size_t firstPiece  = std::min(mCapacity - mDataEnd, length);
    size_t secondPiece = length - firstPiece;
    ::memcpy(mStorage + mDataEnd, source, firstPiece);
    ::memcpy(mStorage, source + firstPiece, secondPiece);
    mDataEnd = Advance(mDataEnd, length);
}

void BytesCircularBuffer::Drop(size_t length)
{
    VerifyOrDie(StorageUsed() >= length);
    mDataStart = Advance(mDataStart, length);
}

size_t BytesCircularBuffer::StorageAvailable() const
{
    return mCapacity - StorageUsed();
}

size_t BytesCircularBuffer::StorageUsed() const
{
    if (mDataStart <= mDataEnd)
    {
        return mDataEnd - mDataStart;
    }

    return mCapacity + mDataEnd - mDataStart;
}

CHIP_ERROR BytesCircularBuffer::Push(const ByteSpan & payload)
{
    size_t length = payload.size();
    if (length > std::numeric_limits<SizeType>::max())
        return CHIP_ERROR_INVALID_ARGUMENT;

    static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - (sizeof(SizeType) + 1),
                  "SizeType too large, may cause overflow");
    size_t storageNeed = length + sizeof(SizeType) + 1;
    if (storageNeed > mCapacity)
        return CHIP_ERROR_INVALID_ARGUMENT;

    // Free up space until there is enough space.
    while (storageNeed > StorageAvailable())
    {
        VerifyOrDie(Pop() == CHIP_NO_ERROR);
    }

    SizeType size = static_cast<SizeType>(length);
    Write(reinterpret_cast<uint8_t *>(&size), sizeof(size));
    Write(payload.data(), length);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BytesCircularBuffer::Push(const ByteSpan & payload1, const ByteSpan & payload2)
{
    size_t length = payload1.size() + payload2.size();
    if (length > std::numeric_limits<SizeType>::max())
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - (sizeof(SizeType) + 1),
                  "SizeType too large, may cause overflow");
    size_t storageNeed = length + sizeof(SizeType) + 1;
    if (storageNeed > mCapacity)
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    // Free up space until there is enough space.
    while (storageNeed > StorageAvailable())
    {
        VerifyOrDie(Pop() == CHIP_NO_ERROR);
    }

    SizeType size = static_cast<SizeType>(length);
    Write(reinterpret_cast<uint8_t *>(&size), sizeof(size));
    Write(payload1.data(), payload1.size());
    Write(payload2.data(), payload2.size());

    return CHIP_NO_ERROR;
}

CHIP_ERROR BytesCircularBuffer::Pop()
{
    if (IsEmpty())
        return CHIP_ERROR_INCORRECT_STATE;

    size_t length = GetFrontSize();
    Drop(sizeof(SizeType));
    Drop(length);

    return CHIP_NO_ERROR;
}

bool BytesCircularBuffer::IsEmpty() const
{
    return StorageUsed() == 0;
}

size_t BytesCircularBuffer::GetFrontSize() const
{
    if (IsEmpty())
        return 0;

    SizeType length;
    Read(reinterpret_cast<uint8_t *>(&length), sizeof(length), 0 /* offset */);
    return length;
}

CHIP_ERROR BytesCircularBuffer::ReadFront(MutableByteSpan & dest) const
{
    if (IsEmpty())
        return CHIP_ERROR_INCORRECT_STATE;

    size_t length = GetFrontSize();
    if (dest.size() < length)
        return CHIP_ERROR_INVALID_ARGUMENT;

    dest = dest.SubSpan(0, length);

    Read(dest.data(), length, sizeof(SizeType) /* offset */);
    return CHIP_NO_ERROR;
}

} // namespace chip
