// 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();

    // 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;
    }

}
