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

#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/server/ObjectStorage.h"
#include "src/dawn/wire/server/Server.h"

namespace dawn::wire::server {

WireResult Server::DoInstanceRequestAdapter(Known<WGPUInstance> instance,
                                            ObjectHandle eventManager,
                                            WGPUFuture future,
                                            ObjectHandle adapterHandle,
                                            const WGPURequestAdapterOptions* options) {
    Reserved<WGPUAdapter> adapter;
    WIRE_TRY(Allocate(&adapter, adapterHandle, AllocationState::Reserved));

    auto userdata = MakeUserdata<RequestAdapterUserdata>();
    userdata->eventManager = eventManager;
    userdata->future = future;
    userdata->adapter = adapter.AsHandle();

    mProcs->instanceRequestAdapter(
        instance->handle, options,
        MakeCallbackInfo<WGPURequestAdapterCallbackInfo, &Server::OnRequestAdapterCallback,
                         WGPUCallbackMode_AllowSpontaneous>(userdata.release()));
    return WireResult::Success;
}

void Server::OnRequestAdapterCallback(RequestAdapterUserdata* data,
                                      WGPURequestAdapterStatus status,
                                      WGPUAdapter adapter,
                                      WGPUStringView message) {
    ReturnInstanceRequestAdapterCallbackCmd cmd = {};
    cmd.eventManager = data->eventManager;
    cmd.future = data->future;
    cmd.status = status;
    cmd.message = message;

    if (status != WGPURequestAdapterStatus_Success) {
        DAWN_ASSERT(adapter == nullptr);
        SerializeCommand(cmd);
        return;
    }

    // Assign the handle and allocated status if the adapter is created successfully.
    if (FillReservation(data->adapter, adapter) == WireResult::FatalError) {
        cmd.status = WGPURequestAdapterStatus_CallbackCancelled;
        cmd.message = ToOutputStringView("Destroyed before request was fulfilled.");
        SerializeCommand(cmd);
        return;
    }

    // Query and report the adapter supported features.
    FreeMembers<WGPUSupportedFeatures> supportedFeatures(mProcs);
    mProcs->adapterGetFeatures(adapter, &supportedFeatures);
    cmd.featuresCount = supportedFeatures.featureCount;
    cmd.features = supportedFeatures.features;

    // Query and report the adapter info.
    FreeMembers<WGPUAdapterInfo> info(mProcs);
    WGPUChainedStruct** propertiesChain = &info.nextInChain;

    // Query AdapterPropertiesMemoryHeaps if the feature is supported.
    FreeMembers<WGPUAdapterPropertiesMemoryHeaps> memoryHeapProperties(mProcs);
    memoryHeapProperties.chain.sType = WGPUSType_AdapterPropertiesMemoryHeaps;
    if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesMemoryHeaps)) {
        *propertiesChain = &memoryHeapProperties.chain;
        propertiesChain = &(*propertiesChain)->next;
    }

    // Query AdapterPropertiesD3D if the feature is supported.
    WGPUAdapterPropertiesD3D d3dProperties = {};
    d3dProperties.chain.sType = WGPUSType_AdapterPropertiesD3D;
    if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesD3D)) {
        *propertiesChain = &d3dProperties.chain;
        propertiesChain = &(*propertiesChain)->next;
    }

    // Query AdapterPropertiesVk if the feature is supported.
    WGPUAdapterPropertiesVk vkProperties = {};
    vkProperties.chain.sType = WGPUSType_AdapterPropertiesVk;
    if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_AdapterPropertiesVk)) {
        *propertiesChain = &vkProperties.chain;
        propertiesChain = &(*propertiesChain)->next;
    }

    // Query AdapterPropertiesSubgroupMatrixConfigs if the feature is supported.
    FreeMembers<WGPUAdapterPropertiesSubgroupMatrixConfigs> subgroupMatrixConfigs(mProcs);
    // WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs{};
    subgroupMatrixConfigs.chain.sType = WGPUSType_AdapterPropertiesSubgroupMatrixConfigs;
    if (mProcs->adapterHasFeature(adapter, WGPUFeatureName_ChromiumExperimentalSubgroupMatrix)) {
        *propertiesChain = &subgroupMatrixConfigs.chain;
        propertiesChain = &(*propertiesChain)->next;
    }

    WGPUDawnAdapterPropertiesPowerPreference powerProperties = {};
    powerProperties.chain.sType = WGPUSType_DawnAdapterPropertiesPowerPreference;
    *propertiesChain = &powerProperties.chain;
    propertiesChain = &(*propertiesChain)->next;

    mProcs->adapterGetInfo(adapter, &info);
    cmd.info = &info;

    // 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;
    compatLimits.chain.sType = WGPUSType_CompatibilityModeLimits;
    limits.nextInChain = &compatLimits.chain;
    // Chained DawnTexelCopyBufferRowAlignmentLimits.
    WGPUDawnTexelCopyBufferRowAlignmentLimits texelCopyBufferRowAlignmentLimits =
        WGPU_DAWN_TEXEL_COPY_BUFFER_ROW_ALIGNMENT_LIMITS_INIT;
    compatLimits.chain.next = &texelCopyBufferRowAlignmentLimits.chain;

    mProcs->adapterGetLimits(adapter, &limits);
    cmd.limits = &limits;

    SerializeCommand(cmd);
}

}  // namespace dawn::wire::server
