// 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 "src/dawn/node/binding/GPUQueue.h"

#include <cassert>
#include <limits>
#include <memory>
#include <utility>

#include "src/dawn/node/binding/Converter.h"
#include "src/dawn/node/binding/GPUBuffer.h"
#include "src/dawn/node/binding/GPUCommandBuffer.h"
#include "src/dawn/node/utils/Debug.h"

namespace wgpu::binding {

////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUQueue
////////////////////////////////////////////////////////////////////////////////
GPUQueue::GPUQueue(wgpu::Queue queue, std::shared_ptr<AsyncRunner> async)
    : queue_(std::move(queue)), async_(std::move(async)), label_("") {}

void GPUQueue::submit(Napi::Env env,
                      std::vector<interop::Interface<interop::GPUCommandBuffer>> commandBuffers) {
    std::vector<wgpu::CommandBuffer> bufs(commandBuffers.size());
    for (size_t i = 0; i < commandBuffers.size(); i++) {
        bufs[i] = *commandBuffers[i].As<GPUCommandBuffer>();
    }
    Converter conv(env);
    uint32_t bufs_size;
    if (!conv(bufs_size, bufs.size())) {
        return;
    }
    queue_.Submit(bufs_size, bufs.data());
}

interop::Promise<void> GPUQueue::onSubmittedWorkDone(Napi::Env env) {
    struct Context {
        Napi::Env env;
        interop::Promise<void> promise;
        AsyncTask task;
    };
    auto ctx = new Context{env, interop::Promise<void>(env, PROMISE_INFO), AsyncTask(env, async_)};
    auto promise = ctx->promise;

    queue_.OnSubmittedWorkDone(
        [](WGPUQueueWorkDoneStatus status, void* userdata) {
            auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));
            if (status != WGPUQueueWorkDoneStatus::WGPUQueueWorkDoneStatus_Success) {
                Napi::Error::New(c->env, "onSubmittedWorkDone() failed")
                    .ThrowAsJavaScriptException();
            }
            c->promise.Resolve();
        },
        ctx);

    return promise;
}

void GPUQueue::writeBuffer(Napi::Env env,
                           interop::Interface<interop::GPUBuffer> buffer,
                           interop::GPUSize64 bufferOffset,
                           interop::AllowSharedBufferSource data,
                           interop::GPUSize64 dataOffsetElements,
                           std::optional<interop::GPUSize64> sizeElements) {
    wgpu::Buffer buf = *buffer.As<GPUBuffer>();
    Converter::BufferSource src{};
    Converter conv(env);
    if (!conv(src, data)) {
        return;
    }

    // Note that in the JS semantics of WebGPU, writeBuffer works in number of elements of the
    // typed arrays.
    if (dataOffsetElements > uint64_t(src.size / src.bytesPerElement)) {
        binding::Errors::OperationError(env, "dataOffset is larger than data's size.")
            .ThrowAsJavaScriptException();
        return;
    }
    uint64_t dataOffset = dataOffsetElements * src.bytesPerElement;
    src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset;
    src.size -= dataOffset;

    // Size defaults to dataSize - dataOffset. Instead of computing in elements, we directly
    // use it in bytes, and convert the provided value, if any, in bytes.
    uint64_t size64 = uint64_t(src.size);
    if (sizeElements.has_value()) {
        if (sizeElements.value() > std::numeric_limits<uint64_t>::max() / src.bytesPerElement) {
            binding::Errors::OperationError(env, "size overflows.").ThrowAsJavaScriptException();
            return;
        }
        size64 = sizeElements.value() * src.bytesPerElement;
    }

    if (size64 > uint64_t(src.size)) {
        binding::Errors::OperationError(env, "size + dataOffset is larger than data's size.")
            .ThrowAsJavaScriptException();
        return;
    }

    if (size64 % 4 != 0) {
        binding::Errors::OperationError(env, "size is not a multiple of 4 bytes.")
            .ThrowAsJavaScriptException();
        return;
    }

    assert(size64 <= std::numeric_limits<size_t>::max());
    queue_.WriteBuffer(buf, bufferOffset, src.data, static_cast<size_t>(size64));
}

void GPUQueue::writeTexture(Napi::Env env,
                            interop::GPUImageCopyTexture destination,
                            interop::AllowSharedBufferSource data,
                            interop::GPUImageDataLayout dataLayout,
                            interop::GPUExtent3D size) {
    wgpu::ImageCopyTexture dst{};
    Converter::BufferSource src{};
    wgpu::TextureDataLayout layout{};
    wgpu::Extent3D sz{};
    Converter conv(env);
    if (!conv(dst, destination) ||    //
        !conv(src, data) ||           //
        !conv(layout, dataLayout) ||  //
        !conv(sz, size)) {
        return;
    }

    queue_.WriteTexture(&dst, src.data, src.size, &layout, &sz);
}

void GPUQueue::copyExternalImageToTexture(Napi::Env env,
                                          interop::GPUImageCopyExternalImage source,
                                          interop::GPUImageCopyTextureTagged destination,
                                          interop::GPUExtent3D copySize) {
    UNIMPLEMENTED(env);
}

std::string GPUQueue::getLabel(Napi::Env) {
    return label_;
}

void GPUQueue::setLabel(Napi::Env, std::string value) {
    queue_.SetLabel(value.c_str());
    label_ = value;
}

}  // namespace wgpu::binding
