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

#include "dawn_wire/client/Client.h"

#include "common/Compiler.h"
#include "dawn_wire/client/Device.h"

namespace dawn::wire::client {

    namespace {

        class NoopCommandSerializer final : public CommandSerializer {
          public:
            static NoopCommandSerializer* GetInstance() {
                static NoopCommandSerializer gNoopCommandSerializer;
                return &gNoopCommandSerializer;
            }

            ~NoopCommandSerializer() = default;

            size_t GetMaximumAllocationSize() const final {
                return 0;
            }
            void* GetCmdSpace(size_t size) final {
                return nullptr;
            }
            bool Flush() final {
                return false;
            }
        };

    }  // anonymous namespace

    Client::Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService)
        : ClientBase(), mSerializer(serializer), mMemoryTransferService(memoryTransferService) {
        if (mMemoryTransferService == nullptr) {
            // If a MemoryTransferService is not provided, fall back to inline memory.
            mOwnedMemoryTransferService = CreateInlineMemoryTransferService();
            mMemoryTransferService = mOwnedMemoryTransferService.get();
        }
    }

    Client::~Client() {
        DestroyAllObjects();
    }

    void Client::DestroyAllObjects() {
        for (auto& objectList : mObjects) {
            ObjectType objectType = static_cast<ObjectType>(&objectList - mObjects.data());
            if (objectType == ObjectType::Device) {
                continue;
            }
            while (!objectList.empty()) {
                ObjectBase* object = objectList.head()->value();

                DestroyObjectCmd cmd;
                cmd.objectType = objectType;
                cmd.objectId = object->id;
                SerializeCommand(cmd);
                FreeObject(objectType, object);
            }
        }

        while (!mObjects[ObjectType::Device].empty()) {
            ObjectBase* object = mObjects[ObjectType::Device].head()->value();

            DestroyObjectCmd cmd;
            cmd.objectType = ObjectType::Device;
            cmd.objectId = object->id;
            SerializeCommand(cmd);
            FreeObject(ObjectType::Device, object);
        }
    }

    ReservedTexture Client::ReserveTexture(WGPUDevice device) {
        auto* allocation = TextureAllocator().New(this);

        ReservedTexture result;
        result.texture = ToAPI(allocation->object.get());
        result.id = allocation->object->id;
        result.generation = allocation->generation;
        result.deviceId = FromAPI(device)->id;
        result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
        return result;
    }

    ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
        auto* allocation = SwapChainAllocator().New(this);

        ReservedSwapChain result;
        result.swapchain = ToAPI(allocation->object.get());
        result.id = allocation->object->id;
        result.generation = allocation->generation;
        result.deviceId = FromAPI(device)->id;
        result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
        return result;
    }

    ReservedDevice Client::ReserveDevice() {
        auto* allocation = DeviceAllocator().New(this);

        ReservedDevice result;
        result.device = ToAPI(allocation->object.get());
        result.id = allocation->object->id;
        result.generation = allocation->generation;
        return result;
    }

    ReservedInstance Client::ReserveInstance() {
        auto* allocation = InstanceAllocator().New(this);

        ReservedInstance result;
        result.instance = ToAPI(allocation->object.get());
        result.id = allocation->object->id;
        result.generation = allocation->generation;
        return result;
    }

    void Client::ReclaimTextureReservation(const ReservedTexture& reservation) {
        TextureAllocator().Free(FromAPI(reservation.texture));
    }

    void Client::ReclaimSwapChainReservation(const ReservedSwapChain& reservation) {
        SwapChainAllocator().Free(FromAPI(reservation.swapchain));
    }

    void Client::ReclaimDeviceReservation(const ReservedDevice& reservation) {
        DeviceAllocator().Free(FromAPI(reservation.device));
    }

    void Client::ReclaimInstanceReservation(const ReservedInstance& reservation) {
        InstanceAllocator().Free(FromAPI(reservation.instance));
    }

    void Client::Disconnect() {
        mDisconnected = true;
        mSerializer = ChunkedCommandSerializer(NoopCommandSerializer::GetInstance());

        auto& deviceList = mObjects[ObjectType::Device];
        {
            for (LinkNode<ObjectBase>* device = deviceList.head(); device != deviceList.end();
                 device = device->next()) {
                static_cast<Device*>(device->value())
                    ->HandleDeviceLost(WGPUDeviceLostReason_Undefined, "GPU connection lost");
            }
        }
        for (auto& objectList : mObjects) {
            for (LinkNode<ObjectBase>* object = objectList.head(); object != objectList.end();
                 object = object->next()) {
                object->value()->CancelCallbacksForDisconnect();
            }
        }
    }

    bool Client::IsDisconnected() const {
        return mDisconnected;
    }

}  // namespace dawn::wire::client
