// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <utility>
#include <vector>

#include "absl/types/span.h"  // TODO(343500108): Use std::span when we have C++20.
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/wire/SupportedFeatures.h"
#include "src/dawn/wire/WireResult.h"
#include "src/dawn/wire/server/ObjectStorage.h"
#include "src/dawn/wire/server/Server.h"

namespace dawn::wire::server {

WireResult Server::DoAdapterRequestDevice(Known<WGPUAdapter> adapter,
                                          Known<WGPUInstance> instance,
                                          Future future,
                                          ObjectHandle deviceHandle,
                                          Future deviceLostFuture,
                                          const DeviceDescriptor* descriptor) {
    Reserved<WGPUDevice> device;
    WIRE_TRY(Allocate(&device, deviceHandle, AllocationState::Reserved));

    auto userdata = MakeUserdata<RequestDeviceUserdata>();
    userdata->instanceId = instance.id;
    userdata->future = future;
    userdata->device = device.AsHandle();

    // Update the descriptor with the device lost callback associated with this request.
    auto deviceLostUserdata = MakeUserdata<DeviceLostUserdata>();
    deviceLostUserdata->instanceId = instance.id;
    deviceLostUserdata->future = deviceLostFuture;

    WGPUDeviceDescriptor desc = *ToAPI(descriptor);
    desc.deviceLostCallbackInfo =
        MakeCallbackInfo<WGPUDeviceLostCallbackInfo, &Server::OnDeviceLost>(
            deviceLostUserdata.release());
    desc.uncapturedErrorCallbackInfo = {
        nullptr,
        [](WGPUDevice const*, WGPUErrorType type, WGPUStringView message, void*, void* userdata) {
            DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
            {
                auto serverGuard = info->server->GetGuard();
                info->server->OnUncapturedError(info->self, FromAPI(type), FromAPI(message));
            }
            info->server->Flush();
        },
        nullptr, device->info.get()};

    mProcs->adapterRequestDevice(
        adapter->handle, &desc,
        MakeCallbackInfo<WGPURequestDeviceCallbackInfo, &Server::OnRequestDeviceCallback,
                         wgpu::CallbackMode::AllowSpontaneous>(userdata.release()));
    return WireResult::Success;
}

void Server::OnRequestDeviceCallback(RequestDeviceUserdata* data,
                                     wgpu::RequestDeviceStatus status,
                                     WGPUDevice device,
                                     StringView message) {
    ReturnAdapterRequestDeviceCallbackCmd cmd = {};
    cmd.instanceId = data->instanceId;
    cmd.future = data->future;
    cmd.status = status;
    cmd.message = message;

    if (status != wgpu::RequestDeviceStatus::Success) {
        DAWN_ASSERT(device == nullptr);
        SerializeCommand(std::move(cmd));
        return;
    }

    // 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.
    FreeMembers<SupportedFeatures> supportedFeatures(mProcs);
    mProcs->deviceGetFeatures(device, ToAPI(&supportedFeatures));
    for (wgpu::FeatureName feature : supportedFeatures.features) {
        if (!IsFeatureSupported(ToAPI(feature))) {
            // Release the device.
            mProcs->deviceRelease(device);
            device = nullptr;

            cmd.status = wgpu::RequestDeviceStatus::Error;
            cmd.message = "Requested feature not supported.";
            SerializeCommand(std::move(cmd));
            return;
        }
    }
    cmd.features = supportedFeatures.features;

    // Query and report the adapter limits, including all known extension limits.
    // TODO(crbug.com/421950205): Use dawn::utils::ComboLimits here.
    WGPULimits limits = {};
    // Chained CompatibilityModeLimits.
    WGPUCompatibilityModeLimits compatLimits = WGPU_COMPATIBILITY_MODE_LIMITS_INIT;
    limits.nextInChain = &compatLimits.chain;
    // Chained DawnTexelCopyBufferRowAlignmentLimits.
    WGPUDawnTexelCopyBufferRowAlignmentLimits texelCopyBufferRowAlignmentLimits =
        WGPU_DAWN_TEXEL_COPY_BUFFER_ROW_ALIGNMENT_LIMITS_INIT;
    compatLimits.chain.next = &texelCopyBufferRowAlignmentLimits.chain;

    mProcs->deviceGetLimits(device, &limits);
    cmd.limits = FromAPI(&limits);

    // Assign the handle and allocated status if the device is created successfully.
    Known<WGPUDevice> reservation;
    if (FillReservation(data->device, device, &reservation) == WireResult::FatalError) {
        cmd.status = wgpu::RequestDeviceStatus::CallbackCancelled;
        cmd.message = "Destroyed before request was fulfilled.";
        SerializeCommand(std::move(cmd));
        return;
    }
    DAWN_ASSERT(reservation.data != nullptr);
    reservation->info->server = this;
    reservation->info->self = reservation.AsHandle();
    SetForwardingDeviceCallbacks(reservation);
    SerializeCommand(std::move(cmd));
}

}  // namespace dawn::wire::server
