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

#include "dawn/common/StringViewUtils.h"
#include "dawn/wire/SupportedFeatures.h"
#include "dawn/wire/server/ObjectStorage.h"
#include "dawn/wire/server/Server.h"

namespace dawn::wire::server {

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

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

    if (userdataCount == 1) {
        mProcs.instanceRequestAdapter(instance->handle, options,
                                      ForwardToServer<&Server::OnRequestAdapterCallback>,
                                      userdata.release());
    } else {
        mProcs.instanceRequestAdapter2(
            instance->handle, options,
            {nullptr, WGPUCallbackMode_AllowSpontaneous,
             ForwardToServer2<&Server::OnRequestAdapterCallback>, userdata.release(), nullptr});
    }
    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->adapterObjectId, adapter) == WireResult::FatalError) {
        cmd.status = WGPURequestAdapterStatus_Unknown;
        cmd.message = ToOutputStringView("Destroyed before request was fulfilled.");
        SerializeCommand(cmd);
        return;
    }

    // Query and report the adapter supported features.
    std::vector<WGPUFeatureName> features;

    size_t featuresCount = mProcs.adapterEnumerateFeatures(adapter, nullptr);
    features.resize(featuresCount);
    mProcs.adapterEnumerateFeatures(adapter, features.data());

    // Hide features the wire cannot support.
    auto it = std::partition(features.begin(), features.end(), IsFeatureSupported);

    cmd.featuresCount = std::distance(features.begin(), it);
    cmd.features = features.data();

    // Query and report the adapter info.
    WGPUAdapterInfo info = {};
    WGPUChainedStructOut** propertiesChain = &info.nextInChain;

    // Query AdapterPropertiesMemoryHeaps if the feature is supported.
    WGPUAdapterPropertiesMemoryHeaps memoryHeapProperties = {};
    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;
    }

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

    // Query and report the adapter limits, including DawnExperimentalSubgroupLimits and
    // DawnExperimentalImmediateDataLimits.
    WGPUSupportedLimits limits = {};

    WGPUDawnExperimentalSubgroupLimits experimentalSubgroupLimits = {};
    experimentalSubgroupLimits.chain.sType = WGPUSType_DawnExperimentalSubgroupLimits;
    limits.nextInChain = &experimentalSubgroupLimits.chain;

    // Chained DawnExperimentalImmediateDataLimits.
    WGPUDawnExperimentalImmediateDataLimits experimentalImmediateDataLimits = {};
    experimentalImmediateDataLimits.chain.sType = WGPUSType_DawnExperimentalImmediateDataLimits;
    experimentalSubgroupLimits.chain.next = &experimentalImmediateDataLimits.chain;

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

    SerializeCommand(cmd);
    mProcs.adapterInfoFreeMembers(info);
    mProcs.adapterPropertiesMemoryHeapsFreeMembers(memoryHeapProperties);
}

}  // namespace dawn::wire::server
