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

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

#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)) {
    }

    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), async_};
        auto promise = ctx->promise;

        queue_.OnSubmittedWorkDone(
            0,
            [](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::BufferSource 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::BufferSource 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,
                                              interop::GPUImageCopyExternalImage source,
                                              interop::GPUImageCopyTextureTagged destination,
                                              interop::GPUExtent3D copySize) {
        UNIMPLEMENTED();
    }

    std::variant<std::string, interop::UndefinedType> GPUQueue::getLabel(Napi::Env) {
        UNIMPLEMENTED();
    }

    void GPUQueue::setLabel(Napi::Env, std::variant<std::string, interop::UndefinedType> value) {
        UNIMPLEMENTED();
    }

}  // namespace wgpu::binding
