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

#include <algorithm>

namespace dawn::wire::server {

    bool Server::DoInstanceRequestAdapter(ObjectId instanceId,
                                          uint64_t requestSerial,
                                          ObjectHandle adapterHandle,
                                          const WGPURequestAdapterOptions* options) {
        auto* instance = InstanceObjects().Get(instanceId);
        if (instance == nullptr) {
            return false;
        }

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

        resultData->generation = adapterHandle.generation;

        auto userdata = MakeUserdata<RequestAdapterUserdata>();
        userdata->instance = ObjectHandle{instanceId, instance->generation};
        userdata->requestSerial = requestSerial;
        userdata->adapterObjectId = adapterHandle.id;

        mProcs.instanceRequestAdapter(instance->handle, options,
                                      ForwardToServer<&Server::OnRequestAdapterCallback>,
                                      userdata.release());
        return true;
    }

    void Server::OnRequestAdapterCallback(RequestAdapterUserdata* data,
                                          WGPURequestAdapterStatus status,
                                          WGPUAdapter adapter,
                                          const char* message) {
        auto* adapterObject =
            AdapterObjects().Get(data->adapterObjectId, 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(adapterObject != nullptr);

        ReturnInstanceRequestAdapterCallbackCmd cmd = {};
        cmd.instance = data->instance;
        cmd.requestSerial = data->requestSerial;
        cmd.status = status;
        cmd.message = message;

        if (status != WGPURequestAdapterStatus_Success) {
            // Free the ObjectId which will make it unusable.
            AdapterObjects().Free(data->adapterObjectId);
            ASSERT(adapter == nullptr);
            SerializeCommand(cmd);
            return;
        }

        WGPUAdapterProperties properties = {};
        WGPUSupportedLimits limits = {};
        std::vector<WGPUFeatureName> features;

        // Assign the handle and allocated status if the adapter is created successfully.
        adapterObject->state = AllocationState::Allocated;
        adapterObject->handle = adapter;

        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();

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

        SerializeCommand(cmd);
    }

}  // namespace dawn::wire::server
