// Copyright 2019 The Dawn 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.

#ifndef DAWNWIRE_SERVER_OBJECTSTORAGE_H_
#define DAWNWIRE_SERVER_OBJECTSTORAGE_H_

#include "dawn_wire/WireCmd_autogen.h"

#include <algorithm>
#include <map>

namespace dawn_wire { namespace server {

    template <typename T>
    struct ObjectDataBase {
        // The backend-provided handle and serial to this object.
        T handle;
        uint32_t serial = 0;

        // Whether this object has been allocated, used by the KnownObjects queries
        // TODO(cwallez@chromium.org): make this an internal bit vector in KnownObjects.
        bool allocated;
    };

    // Stores what the backend knows about the type.
    template <typename T>
    struct ObjectData : public ObjectDataBase<T> {};

    enum class BufferMapWriteState { Unmapped, Mapped, MapError };

    template <>
    struct ObjectData<DawnBuffer> : public ObjectDataBase<DawnBuffer> {
        void* mappedData = nullptr;
        size_t mappedDataSize = 0;
        BufferMapWriteState mapWriteState = BufferMapWriteState::Unmapped;
    };

    // Keeps track of the mapping between client IDs and backend objects.
    template <typename T>
    class KnownObjects {
      public:
        using Data = ObjectData<T>;

        KnownObjects() {
            // Reserve ID 0 so that it can be used to represent nullptr for optional object values
            // in the wire format. However don't tag it as allocated so that it is an error to ask
            // KnownObjects for ID 0.
            Data reservation;
            reservation.handle = nullptr;
            reservation.allocated = false;
            mKnown.push_back(reservation);
        }

        // Get a backend objects for a given client ID.
        // Returns nullptr if the ID hasn't previously been allocated.
        const Data* Get(uint32_t id) const {
            if (id >= mKnown.size()) {
                return nullptr;
            }

            const Data* data = &mKnown[id];

            if (!data->allocated) {
                return nullptr;
            }

            return data;
        }
        Data* Get(uint32_t id) {
            if (id >= mKnown.size()) {
                return nullptr;
            }

            Data* data = &mKnown[id];

            if (!data->allocated) {
                return nullptr;
            }

            return data;
        }

        // Allocates the data for a given ID and returns it.
        // Returns nullptr if the ID is already allocated, or too far ahead.
        // Invalidates all the Data*
        Data* Allocate(uint32_t id) {
            if (id > mKnown.size()) {
                return nullptr;
            }

            Data data;
            data.allocated = true;
            data.handle = nullptr;

            if (id >= mKnown.size()) {
                mKnown.push_back(data);
                return &mKnown.back();
            }

            if (mKnown[id].allocated) {
                return nullptr;
            }

            mKnown[id] = data;
            return &mKnown[id];
        }

        // Marks an ID as deallocated
        void Free(uint32_t id) {
            ASSERT(id < mKnown.size());
            mKnown[id].allocated = false;
        }

        std::vector<T> AcquireAllHandles() {
            std::vector<T> objects;
            for (Data& data : mKnown) {
                if (data.allocated && data.handle != nullptr) {
                    objects.push_back(data.handle);
                    data.allocated = false;
                    data.handle = nullptr;
                }
            }

            return objects;
        }

      private:
        std::vector<Data> mKnown;
    };

    // ObjectIds are lost in deserialization. Store the ids of deserialized
    // objects here so they can be used in command handlers. This is useful
    // for creating ReturnWireCmds which contain client ids
    template <typename T>
    class ObjectIdLookupTable {
      public:
        void Store(T key, ObjectId id) {
            mTable[key] = id;
        }

        // Return the cached ObjectId, or 0 (null handle)
        ObjectId Get(T key) const {
            const auto it = mTable.find(key);
            if (it != mTable.end()) {
                return it->second;
            }
            return 0;
        }

        void Remove(T key) {
            auto it = mTable.find(key);
            if (it != mTable.end()) {
                mTable.erase(it);
            }
        }

      private:
        std::map<T, ObjectId> mTable;
    };

}}  // namespace dawn_wire::server

#endif  // DAWNWIRE_SERVER_OBJECTSTORAGE_H_
