// 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/TypeTraits_autogen.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;

        // Used by the error-propagation mechanism to know if this object is an error.
        // TODO(cwallez@chromium.org): this is doubling the memory usage of
        // std::vector<ObjectDataBase> consider making it a special marker value in handle instead.
        bool valid;
        // 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, bool IsBuilder = IsBuilderType<T>::value>
    struct ObjectData : public ObjectDataBase<T> {};

    template <typename T>
    struct ObjectData<T, true> : public ObjectDataBase<T> {
        ObjectHandle builtObject = ObjectHandle{0, 0};
    };

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

    // 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.valid = false;
            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.valid = false;
            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.valid = false;
                    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_
