// Copyright 2021 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/Instance.h"

#include "dawn_wire/client/Client.h"

namespace dawn_wire::client {

    Instance::~Instance() {
        mRequestAdapterRequests.CloseAll([](RequestAdapterData* request) {
            request->callback(WGPURequestAdapterStatus_Unknown, nullptr,
                              "Instance destroyed before callback", request->userdata);
        });
    }

    void Instance::CancelCallbacksForDisconnect() {
        mRequestAdapterRequests.CloseAll([](RequestAdapterData* request) {
            request->callback(WGPURequestAdapterStatus_Unknown, nullptr, "GPU connection lost",
                              request->userdata);
        });
    }

    void Instance::RequestAdapter(const WGPURequestAdapterOptions* options,
                                  WGPURequestAdapterCallback callback,
                                  void* userdata) {
        if (client->IsDisconnected()) {
            callback(WGPURequestAdapterStatus_Error, nullptr, "GPU connection lost", userdata);
            return;
        }

        auto* allocation = client->AdapterAllocator().New(client);
        uint64_t serial = mRequestAdapterRequests.Add({callback, allocation->object->id, userdata});

        InstanceRequestAdapterCmd cmd;
        cmd.instanceId = this->id;
        cmd.requestSerial = serial;
        cmd.adapterObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
        cmd.options = options;

        client->SerializeCommand(cmd);
    }

    bool Client::DoInstanceRequestAdapterCallback(Instance* instance,
                                                  uint64_t requestSerial,
                                                  WGPURequestAdapterStatus status,
                                                  const char* message,
                                                  const WGPUAdapterProperties* properties,
                                                  const WGPUSupportedLimits* limits,
                                                  uint32_t featuresCount,
                                                  const WGPUFeatureName* features) {
        // May have been deleted or recreated so this isn't an error.
        if (instance == nullptr) {
            return true;
        }
        return instance->OnRequestAdapterCallback(requestSerial, status, message, properties,
                                                  limits, featuresCount, features);
    }

    bool Instance::OnRequestAdapterCallback(uint64_t requestSerial,
                                            WGPURequestAdapterStatus status,
                                            const char* message,
                                            const WGPUAdapterProperties* properties,
                                            const WGPUSupportedLimits* limits,
                                            uint32_t featuresCount,
                                            const WGPUFeatureName* features) {
        RequestAdapterData request;
        if (!mRequestAdapterRequests.Acquire(requestSerial, &request)) {
            return false;
        }

        Adapter* adapter = client->AdapterAllocator().GetObject(request.adapterObjectId);

        // If the return status is a failure we should give a null adapter to the callback and
        // free the allocation.
        if (status != WGPURequestAdapterStatus_Success) {
            client->AdapterAllocator().Free(adapter);
            request.callback(status, nullptr, message, request.userdata);
            return true;
        }

        adapter->SetProperties(properties);
        adapter->SetLimits(limits);
        adapter->SetFeatures(features, featuresCount);

        request.callback(status, ToAPI(adapter), message, request.userdata);
        return true;
    }

}  // namespace dawn_wire::client
