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

namespace dawn::wire::server {

namespace {

template <ObjectType objectType, typename Pipeline>
void HandleCreateRenderPipelineAsyncCallbackResult(KnownObjects<Pipeline>* knownObjects,
                                                   WGPUCreatePipelineAsyncStatus status,
                                                   Pipeline pipeline,
                                                   CreatePipelineAsyncUserData* data) {
    // May be null if the device was destroyed. Device destruction destroys child
    // objects on the wire.
    auto* pipelineObject = knownObjects->Get(data->pipelineObjectID, 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(pipelineObject != nullptr);

    if (status == WGPUCreatePipelineAsyncStatus_Success) {
        // Assign the handle and allocated status if the pipeline is created successfully.
        pipelineObject->state = AllocationState::Allocated;
        pipelineObject->handle = pipeline;

        // This should be impossible to fail. It would require a command to be sent that
        // creates a duplicate ObjectId, which would fail validation.
        bool success =
            TrackDeviceChild(pipelineObject->deviceInfo, objectType, data->pipelineObjectID);
        ASSERT(success);
    } else {
        // Otherwise, free the ObjectId which will make it unusable.
        knownObjects->Free(data->pipelineObjectID);
        ASSERT(pipeline == nullptr);
    }
}

}  // anonymous namespace

void Server::OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message) {
    ReturnDeviceUncapturedErrorCallbackCmd cmd;
    cmd.device = device;
    cmd.type = type;
    cmd.message = message;

    SerializeCommand(cmd);
}

void Server::OnDeviceLost(ObjectHandle device, WGPUDeviceLostReason reason, const char* message) {
    ReturnDeviceLostCallbackCmd cmd;
    cmd.device = device;
    cmd.reason = reason;
    cmd.message = message;

    SerializeCommand(cmd);
}

void Server::OnLogging(ObjectHandle device, WGPULoggingType type, const char* message) {
    ReturnDeviceLoggingCallbackCmd cmd;
    cmd.device = device;
    cmd.type = type;
    cmd.message = message;

    SerializeCommand(cmd);
}

bool Server::DoDevicePopErrorScope(ObjectId deviceId, uint64_t requestSerial) {
    auto* device = DeviceObjects().Get(deviceId);
    if (device == nullptr) {
        return false;
    }

    auto userdata = MakeUserdata<ErrorScopeUserdata>();
    userdata->requestSerial = requestSerial;
    userdata->device = ObjectHandle{deviceId, device->generation};

    mProcs.devicePopErrorScope(device->handle, ForwardToServer<&Server::OnDevicePopErrorScope>,
                               userdata.release());
    return true;
}

void Server::OnDevicePopErrorScope(ErrorScopeUserdata* userdata,
                                   WGPUErrorType type,
                                   const char* message) {
    ReturnDevicePopErrorScopeCallbackCmd cmd;
    cmd.device = userdata->device;
    cmd.requestSerial = userdata->requestSerial;
    cmd.type = type;
    cmd.message = message;

    SerializeCommand(cmd);
}

bool Server::DoDeviceCreateComputePipelineAsync(ObjectId deviceId,
                                                uint64_t requestSerial,
                                                ObjectHandle pipelineObjectHandle,
                                                const WGPUComputePipelineDescriptor* descriptor) {
    auto* device = DeviceObjects().Get(deviceId);
    if (device == nullptr) {
        return false;
    }

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

    resultData->generation = pipelineObjectHandle.generation;
    resultData->deviceInfo = device->info.get();

    auto userdata = MakeUserdata<CreatePipelineAsyncUserData>();
    userdata->device = ObjectHandle{deviceId, device->generation};
    userdata->requestSerial = requestSerial;
    userdata->pipelineObjectID = pipelineObjectHandle.id;

    mProcs.deviceCreateComputePipelineAsync(
        device->handle, descriptor, ForwardToServer<&Server::OnCreateComputePipelineAsyncCallback>,
        userdata.release());
    return true;
}

void Server::OnCreateComputePipelineAsyncCallback(CreatePipelineAsyncUserData* data,
                                                  WGPUCreatePipelineAsyncStatus status,
                                                  WGPUComputePipeline pipeline,
                                                  const char* message) {
    HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::ComputePipeline>(
        &ComputePipelineObjects(), status, pipeline, data);

    ReturnDeviceCreateComputePipelineAsyncCallbackCmd cmd;
    cmd.device = data->device;
    cmd.status = status;
    cmd.requestSerial = data->requestSerial;
    cmd.message = message;

    SerializeCommand(cmd);
}

bool Server::DoDeviceCreateRenderPipelineAsync(ObjectId deviceId,
                                               uint64_t requestSerial,
                                               ObjectHandle pipelineObjectHandle,
                                               const WGPURenderPipelineDescriptor* descriptor) {
    auto* device = DeviceObjects().Get(deviceId);
    if (device == nullptr) {
        return false;
    }

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

    resultData->generation = pipelineObjectHandle.generation;
    resultData->deviceInfo = device->info.get();

    auto userdata = MakeUserdata<CreatePipelineAsyncUserData>();
    userdata->device = ObjectHandle{deviceId, device->generation};
    userdata->requestSerial = requestSerial;
    userdata->pipelineObjectID = pipelineObjectHandle.id;

    mProcs.deviceCreateRenderPipelineAsync(
        device->handle, descriptor, ForwardToServer<&Server::OnCreateRenderPipelineAsyncCallback>,
        userdata.release());
    return true;
}

void Server::OnCreateRenderPipelineAsyncCallback(CreatePipelineAsyncUserData* data,
                                                 WGPUCreatePipelineAsyncStatus status,
                                                 WGPURenderPipeline pipeline,
                                                 const char* message) {
    HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::RenderPipeline>(
        &RenderPipelineObjects(), status, pipeline, data);

    ReturnDeviceCreateRenderPipelineAsyncCallbackCmd cmd;
    cmd.device = data->device;
    cmd.status = status;
    cmd.requestSerial = data->requestSerial;
    cmd.message = message;

    SerializeCommand(cmd);
}

}  // namespace dawn::wire::server
