// 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 "common/Assert.h"
#include "dawn_wire/server/Server.h"

namespace dawn::wire::server {

    void Server::OnQueueWorkDone(QueueWorkDoneUserdata* data, WGPUQueueWorkDoneStatus status) {
        ReturnQueueWorkDoneCallbackCmd cmd;
        cmd.queue = data->queue;
        cmd.requestSerial = data->requestSerial;
        cmd.status = status;

        SerializeCommand(cmd);
    }

    bool Server::DoQueueOnSubmittedWorkDone(ObjectId queueId,
                                            uint64_t signalValue,
                                            uint64_t requestSerial) {
        auto* queue = QueueObjects().Get(queueId);
        if (queue == nullptr) {
            return false;
        }

        auto userdata = MakeUserdata<QueueWorkDoneUserdata>();
        userdata->queue = ObjectHandle{queueId, queue->generation};
        userdata->requestSerial = requestSerial;

        mProcs.queueOnSubmittedWorkDone(queue->handle, signalValue,
                                        ForwardToServer<&Server::OnQueueWorkDone>,
                                        userdata.release());
        return true;
    }

    bool Server::DoQueueWriteBuffer(ObjectId queueId,
                                    ObjectId bufferId,
                                    uint64_t bufferOffset,
                                    const uint8_t* data,
                                    uint64_t size) {
        // The null object isn't valid as `self` or `buffer` so we can combine the check with the
        // check that the ID is valid.
        auto* queue = QueueObjects().Get(queueId);
        auto* buffer = BufferObjects().Get(bufferId);
        if (queue == nullptr || buffer == nullptr) {
            return false;
        }

        if (size > std::numeric_limits<size_t>::max()) {
            auto* device = DeviceObjects().Get(queue->deviceInfo->self.id);
            if (device == nullptr) {
                return false;
            }
            return DoDeviceInjectError(reinterpret_cast<WGPUDevice>(device),
                                       WGPUErrorType_OutOfMemory,
                                       "Data size too large for write texture.");
        }

        mProcs.queueWriteBuffer(queue->handle, buffer->handle, bufferOffset, data,
                                static_cast<size_t>(size));
        return true;
    }

    bool Server::DoQueueWriteTexture(ObjectId queueId,
                                     const WGPUImageCopyTexture* destination,
                                     const uint8_t* data,
                                     uint64_t dataSize,
                                     const WGPUTextureDataLayout* dataLayout,
                                     const WGPUExtent3D* writeSize) {
        // The null object isn't valid as `self` so we can combine the check with the
        // check that the ID is valid.
        auto* queue = QueueObjects().Get(queueId);
        if (queue == nullptr) {
            return false;
        }

        if (dataSize > std::numeric_limits<size_t>::max()) {
            auto* device = DeviceObjects().Get(queue->deviceInfo->self.id);
            if (device == nullptr) {
                return false;
            }
            return DoDeviceInjectError(reinterpret_cast<WGPUDevice>(device),
                                       WGPUErrorType_OutOfMemory,
                                       "Data size too large for write texture.");
        }

        mProcs.queueWriteTexture(queue->handle, destination, data, static_cast<size_t>(dataSize),
                                 dataLayout, writeSize);
        return true;
    }

}  // namespace dawn::wire::server
