// 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/server/Server.h"

#include "dawn_wire/SupportedFeatures.h"

namespace dawn_wire::server {

    bool Server::DoAdapterRequestDevice(ObjectId adapterId,
                                        uint64_t requestSerial,
                                        ObjectHandle deviceHandle,
                                        const WGPUDeviceDescriptor* descriptor) {
        auto* adapter = AdapterObjects().Get(adapterId);
        if (adapter == nullptr) {
            return false;
        }

        auto* resultData = DeviceObjects().Allocate(deviceHandle.id, AllocationState::Reserved);
        if (resultData == nullptr) {
            return false;
        }

        resultData->generation = deviceHandle.generation;

        auto userdata = MakeUserdata<RequestDeviceUserdata>();
        userdata->adapter = ObjectHandle{adapterId, adapter->generation};
        userdata->requestSerial = requestSerial;
        userdata->deviceObjectId = deviceHandle.id;

        mProcs.adapterRequestDevice(adapter->handle, descriptor,
                                    ForwardToServer<&Server::OnRequestDeviceCallback>,
                                    userdata.release());
        return true;
    }

    void Server::OnRequestDeviceCallback(RequestDeviceUserdata* data,
                                         WGPURequestDeviceStatus status,
                                         WGPUDevice device,
                                         const char* message) {
        auto* deviceObject = DeviceObjects().Get(data->deviceObjectId, AllocationState::Reserved);
        // Should be impossible to fail. ObjectIds can't be freed by a destroy command until
        // they move from Reserved to Allocated, or if they are destroyed here.
        ASSERT(deviceObject != nullptr);

        ReturnAdapterRequestDeviceCallbackCmd cmd = {};
        cmd.adapter = data->adapter;
        cmd.requestSerial = data->requestSerial;
        cmd.status = status;
        cmd.message = message;

        if (status != WGPURequestDeviceStatus_Success) {
            // Free the ObjectId which will make it unusable.
            DeviceObjects().Free(data->deviceObjectId);
            ASSERT(device == nullptr);
            SerializeCommand(cmd);
            return;
        }

        std::vector<WGPUFeatureName> features;

        size_t featuresCount = mProcs.deviceEnumerateFeatures(device, nullptr);
        features.resize(featuresCount);
        mProcs.deviceEnumerateFeatures(device, features.data());

        // The client should only be able to request supported features, so all enumerated
        // features that were enabled must also be supported by the wire.
        // Note: We fail the callback here, instead of immediately upon receiving
        // the request to preserve callback ordering.
        for (WGPUFeatureName f : features) {
            if (!IsFeatureSupported(f)) {
                // Release the device.
                mProcs.deviceRelease(device);
                // Free the ObjectId which will make it unusable.
                DeviceObjects().Free(data->deviceObjectId);

                cmd.status = WGPURequestDeviceStatus_Error;
                cmd.message = "Requested feature not supported.";
                SerializeCommand(cmd);
                return;
            }
        }

        cmd.featuresCount = features.size();
        cmd.features = features.data();

        WGPUSupportedLimits limits = {};
        mProcs.deviceGetLimits(device, &limits);
        cmd.limits = &limits;

        // Assign the handle and allocated status if the device is created successfully.
        deviceObject->state = AllocationState::Allocated;
        deviceObject->handle = device;
        SetForwardingDeviceCallbacks(deviceObject);

        SerializeCommand(cmd);
    }

}  // namespace dawn_wire::server
