// Copyright 2017 The NXT 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.

#include "backend/CommandAllocator.h"

#include "common/Assert.h"
#include "common/Math.h"

#include <algorithm>
#include <climits>
#include <cstdlib>

namespace backend {

    constexpr uint32_t EndOfBlock = UINT_MAX;          // std::numeric_limits<uint32_t>::max();
    constexpr uint32_t AdditionalData = UINT_MAX - 1;  // std::numeric_limits<uint32_t>::max() - 1;

    // TODO(cwallez@chromium.org): figure out a way to have more type safety for the iterator

    CommandIterator::CommandIterator() : mEndOfBlock(EndOfBlock) {
        Reset();
    }

    CommandIterator::~CommandIterator() {
        ASSERT(mDataWasDestroyed);

        if (!IsEmpty()) {
            for (auto& block : mBlocks) {
                free(block.block);
            }
        }
    }

    CommandIterator::CommandIterator(CommandIterator&& other) : mEndOfBlock(EndOfBlock) {
        if (!other.IsEmpty()) {
            mBlocks = std::move(other.mBlocks);
            other.Reset();
        }
        other.DataWasDestroyed();
        Reset();
    }

    CommandIterator& CommandIterator::operator=(CommandIterator&& other) {
        if (!other.IsEmpty()) {
            mBlocks = std::move(other.mBlocks);
            other.Reset();
        } else {
            mBlocks.clear();
        }
        other.DataWasDestroyed();
        Reset();
        return *this;
    }

    CommandIterator::CommandIterator(CommandAllocator&& allocator)
        : mBlocks(allocator.AcquireBlocks()), mEndOfBlock(EndOfBlock) {
        Reset();
    }

    CommandIterator& CommandIterator::operator=(CommandAllocator&& allocator) {
        mBlocks = allocator.AcquireBlocks();
        Reset();
        return *this;
    }

    void CommandIterator::Reset() {
        mCurrentBlock = 0;

        if (mBlocks.empty()) {
            // This will case the first NextCommandId call to try to move to the next block and stop
            // the iteration immediately, without special casing the initialization.
            mCurrentPtr = reinterpret_cast<uint8_t*>(&mEndOfBlock);
            mBlocks.emplace_back();
            mBlocks[0].size = sizeof(mEndOfBlock);
            mBlocks[0].block = mCurrentPtr;
        } else {
            mCurrentPtr = AlignPtr(mBlocks[0].block, alignof(uint32_t));
        }
    }

    void CommandIterator::DataWasDestroyed() {
        mDataWasDestroyed = true;
    }

    bool CommandIterator::IsEmpty() const {
        return mBlocks[0].block == reinterpret_cast<const uint8_t*>(&mEndOfBlock);
    }

    bool CommandIterator::NextCommandId(uint32_t* commandId) {
        uint8_t* idPtr = AlignPtr(mCurrentPtr, alignof(uint32_t));
        ASSERT(idPtr + sizeof(uint32_t) <=
               mBlocks[mCurrentBlock].block + mBlocks[mCurrentBlock].size);

        uint32_t id = *reinterpret_cast<uint32_t*>(idPtr);

        if (id == EndOfBlock) {
            mCurrentBlock++;
            if (mCurrentBlock >= mBlocks.size()) {
                Reset();
                *commandId = EndOfBlock;
                return false;
            }
            mCurrentPtr = AlignPtr(mBlocks[mCurrentBlock].block, alignof(uint32_t));
            return NextCommandId(commandId);
        }

        mCurrentPtr = idPtr + sizeof(uint32_t);
        *commandId = id;
        return true;
    }

    void* CommandIterator::NextCommand(size_t commandSize, size_t commandAlignment) {
        uint8_t* commandPtr = AlignPtr(mCurrentPtr, commandAlignment);
        ASSERT(commandPtr + sizeof(commandSize) <=
               mBlocks[mCurrentBlock].block + mBlocks[mCurrentBlock].size);

        mCurrentPtr = commandPtr + commandSize;
        return commandPtr;
    }

    void* CommandIterator::NextData(size_t dataSize, size_t dataAlignment) {
        uint32_t id;
        bool hasId = NextCommandId(&id);
        ASSERT(hasId);
        ASSERT(id == AdditionalData);

        return NextCommand(dataSize, dataAlignment);
    }

    // Potential TODO(cwallez@chromium.org):
    //  - Host the size and pointer to next block in the block itself to avoid having an allocation
    //    in the vector
    //  - Assume T's alignof is, say 64bits, static assert it, and make commandAlignment a constant
    //    in Allocate
    //  - Be able to optimize allocation to one block, for command buffers expected to live long to
    //    avoid cache misses
    //  - Better block allocation, maybe have NXT API to say command buffer is going to have size
    //    close to another

    CommandAllocator::CommandAllocator()
        : mCurrentPtr(reinterpret_cast<uint8_t*>(&mDummyEnum[0])),
          mEndPtr(reinterpret_cast<uint8_t*>(&mDummyEnum[1])) {
    }

    CommandAllocator::~CommandAllocator() {
        ASSERT(mBlocks.empty());
    }

    CommandBlocks&& CommandAllocator::AcquireBlocks() {
        ASSERT(mCurrentPtr != nullptr && mEndPtr != nullptr);
        ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t)));
        ASSERT(mCurrentPtr + sizeof(uint32_t) <= mEndPtr);
        *reinterpret_cast<uint32_t*>(mCurrentPtr) = EndOfBlock;

        mCurrentPtr = nullptr;
        mEndPtr = nullptr;
        return std::move(mBlocks);
    }

    uint8_t* CommandAllocator::Allocate(uint32_t commandId,
                                        size_t commandSize,
                                        size_t commandAlignment) {
        ASSERT(mCurrentPtr != nullptr);
        ASSERT(mEndPtr != nullptr);
        ASSERT(commandId != EndOfBlock);

        // It should always be possible to allocate one id, for EndOfBlock tagging,
        ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t)));
        ASSERT(mCurrentPtr + sizeof(uint32_t) <= mEndPtr);
        uint32_t* idAlloc = reinterpret_cast<uint32_t*>(mCurrentPtr);

        uint8_t* commandAlloc = AlignPtr(mCurrentPtr + sizeof(uint32_t), commandAlignment);
        uint8_t* nextPtr = AlignPtr(commandAlloc + commandSize, alignof(uint32_t));

        // When there is not enough space, we signal the EndOfBlock, so that the iterator nows to
        // move to the next one. EndOfBlock on the last block means the end of the commands.
        if (nextPtr + sizeof(uint32_t) > mEndPtr) {
            // Even if we are not able to get another block, the list of commands will be
            // well-formed and iterable as this block will be that last one.
            *idAlloc = EndOfBlock;

            // Make sure we have space for current allocation, plus end of block and alignment
            // padding for the first id.
            ASSERT(nextPtr > mCurrentPtr);
            if (!GetNewBlock(static_cast<size_t>(nextPtr - mCurrentPtr) + sizeof(uint32_t) +
                             alignof(uint32_t))) {
                return nullptr;
            }
            return Allocate(commandId, commandSize, commandAlignment);
        }

        *idAlloc = commandId;
        mCurrentPtr = nextPtr;
        return commandAlloc;
    }

    uint8_t* CommandAllocator::AllocateData(size_t commandSize, size_t commandAlignment) {
        return Allocate(AdditionalData, commandSize, commandAlignment);
    }

    bool CommandAllocator::GetNewBlock(size_t minimumSize) {
        // Allocate blocks doubling sizes each time, to a maximum of 16k (or at least minimumSize).
        mLastAllocationSize =
            std::max(minimumSize, std::min(mLastAllocationSize * 2, size_t(16384)));

        uint8_t* block = reinterpret_cast<uint8_t*>(malloc(mLastAllocationSize));
        if (block == nullptr) {
            return false;
        }

        mBlocks.push_back({mLastAllocationSize, block});
        mCurrentPtr = AlignPtr(block, alignof(uint32_t));
        mEndPtr = block + mLastAllocationSize;
        return true;
    }

}  // namespace backend
