// 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/GPUDevice.h"

#include <memory>

#include "src/dawn_node/binding/Converter.h"
#include "src/dawn_node/binding/Errors.h"
#include "src/dawn_node/binding/GPUBindGroup.h"
#include "src/dawn_node/binding/GPUBindGroupLayout.h"
#include "src/dawn_node/binding/GPUBuffer.h"
#include "src/dawn_node/binding/GPUCommandBuffer.h"
#include "src/dawn_node/binding/GPUCommandEncoder.h"
#include "src/dawn_node/binding/GPUComputePipeline.h"
#include "src/dawn_node/binding/GPUPipelineLayout.h"
#include "src/dawn_node/binding/GPUQuerySet.h"
#include "src/dawn_node/binding/GPUQueue.h"
#include "src/dawn_node/binding/GPURenderBundleEncoder.h"
#include "src/dawn_node/binding/GPURenderPipeline.h"
#include "src/dawn_node/binding/GPUSampler.h"
#include "src/dawn_node/binding/GPUShaderModule.h"
#include "src/dawn_node/binding/GPUSupportedLimits.h"
#include "src/dawn_node/binding/GPUTexture.h"
#include "src/dawn_node/utils/Debug.h"

namespace wgpu::binding {

    namespace {

        class DeviceLostInfo : public interop::GPUDeviceLostInfo {
          public:
            DeviceLostInfo(interop::GPUDeviceLostReason reason, std::string message)
                : reason_(reason), message_(message) {
            }
            std::variant<interop::GPUDeviceLostReason> getReason(Napi::Env env) override {
                return reason_;
            }
            std::string getMessage(Napi::Env) override {
                return message_;
            }

          private:
            interop::GPUDeviceLostReason reason_;
            std::string message_;
        };

        class OOMError : public interop::GPUOutOfMemoryError {};
        class ValidationError : public interop::GPUValidationError {
          public:
            ValidationError(std::string message) : message_(std::move(message)) {
            }

            std::string getMessage(Napi::Env) override {
                return message_;
            };

          private:
            std::string message_;
        };

    }  // namespace

    ////////////////////////////////////////////////////////////////////////////////
    // wgpu::bindings::GPUDevice
    ////////////////////////////////////////////////////////////////////////////////
    GPUDevice::GPUDevice(Napi::Env env, wgpu::Device device)
        : env_(env), device_(device), async_(std::make_shared<AsyncRunner>(env, device)) {
        device_.SetLoggingCallback(
            [](WGPULoggingType type, char const* message, void* userdata) {
                std::cout << type << ": " << message << std::endl;
            },
            nullptr);
        device_.SetUncapturedErrorCallback(
            [](WGPUErrorType type, char const* message, void* userdata) {
                std::cout << type << ": " << message << std::endl;
            },
            nullptr);

        device_.SetDeviceLostCallback(
            [](WGPUDeviceLostReason reason, char const* message, void* userdata) {
                auto r = interop::GPUDeviceLostReason::kDestroyed;
                switch (reason) {
                    case WGPUDeviceLostReason_Force32:
                        UNREACHABLE("WGPUDeviceLostReason_Force32");
                        break;
                    case WGPUDeviceLostReason_Destroyed:
                    case WGPUDeviceLostReason_Undefined:
                        r = interop::GPUDeviceLostReason::kDestroyed;
                        break;
                }
                auto* self = static_cast<GPUDevice*>(userdata);
                for (auto promise : self->lost_promises_) {
                    promise.Resolve(
                        interop::GPUDeviceLostInfo::Create<DeviceLostInfo>(self->env_, r, message));
                }
            },
            this);
    }

    GPUDevice::~GPUDevice() {
    }

    interop::Interface<interop::GPUSupportedFeatures> GPUDevice::getFeatures(Napi::Env env) {
        class Features : public interop::GPUSupportedFeatures {
          public:
            bool has(Napi::Env, std::string feature) override {
                UNIMPLEMENTED();
            }
            std::vector<std::string> keys(Napi::Env) override {
                UNIMPLEMENTED();
            }
        };
        return interop::GPUSupportedFeatures::Create<Features>(env);
    }

    interop::Interface<interop::GPUSupportedLimits> GPUDevice::getLimits(Napi::Env env) {
        wgpu::SupportedLimits limits{};
        if (!device_.GetLimits(&limits)) {
            Napi::Error::New(env, "failed to get device limits").ThrowAsJavaScriptException();
        }
        return interop::GPUSupportedLimits::Create<GPUSupportedLimits>(env, limits);
    }

    interop::Interface<interop::GPUQueue> GPUDevice::getQueue(Napi::Env env) {
        // TODO(crbug.com/dawn/1144): Should probably return the same Queue JS object.
        return interop::GPUQueue::Create<GPUQueue>(env, device_.GetQueue(), async_);
    }

    void GPUDevice::destroy(Napi::Env env) {
        for (auto promise : lost_promises_) {
            promise.Resolve(interop::GPUDeviceLostInfo::Create<DeviceLostInfo>(
                env_, interop::GPUDeviceLostReason::kDestroyed, "device was destroyed"));
        }
        lost_promises_.clear();
        device_.Release();
    }

    interop::Interface<interop::GPUBuffer> GPUDevice::createBuffer(
        Napi::Env env,
        interop::GPUBufferDescriptor descriptor) {
        Converter conv(env);

        wgpu::BufferDescriptor desc{};
        if (!conv(desc.label, descriptor.label) ||
            !conv(desc.mappedAtCreation, descriptor.mappedAtCreation) ||
            !conv(desc.size, descriptor.size) || !conv(desc.usage, descriptor.usage)) {
            return {};
        }
        return interop::GPUBuffer::Create<GPUBuffer>(env, device_.CreateBuffer(&desc), desc,
                                                     device_, async_);
    }

    interop::Interface<interop::GPUTexture> GPUDevice::createTexture(
        Napi::Env env,
        interop::GPUTextureDescriptor descriptor) {
        Converter conv(env);

        wgpu::TextureDescriptor desc{};
        if (!conv(desc.label, descriptor.label) || !conv(desc.usage, descriptor.usage) ||  //
            !conv(desc.size, descriptor.size) ||                                           //
            !conv(desc.dimension, descriptor.dimension) ||                                 //
            !conv(desc.mipLevelCount, descriptor.mipLevelCount) ||                         //
            !conv(desc.sampleCount, descriptor.sampleCount) ||                             //
            !conv(desc.format, descriptor.format)) {
            return {};
        }
        return interop::GPUTexture::Create<GPUTexture>(env, device_.CreateTexture(&desc));
    }

    interop::Interface<interop::GPUSampler> GPUDevice::createSampler(
        Napi::Env env,
        interop::GPUSamplerDescriptor descriptor) {
        Converter conv(env);

        wgpu::SamplerDescriptor desc{};
        if (!conv(desc.label, descriptor.label) ||                //
            !conv(desc.addressModeU, descriptor.addressModeU) ||  //
            !conv(desc.addressModeV, descriptor.addressModeV) ||  //
            !conv(desc.addressModeW, descriptor.addressModeW) ||  //
            !conv(desc.magFilter, descriptor.magFilter) ||        //
            !conv(desc.minFilter, descriptor.minFilter) ||        //
            !conv(desc.mipmapFilter, descriptor.mipmapFilter) ||  //
            !conv(desc.lodMinClamp, descriptor.lodMinClamp) ||    //
            !conv(desc.lodMaxClamp, descriptor.lodMaxClamp) ||    //
            !conv(desc.compare, descriptor.compare) ||            //
            !conv(desc.maxAnisotropy, descriptor.maxAnisotropy)) {
            return {};
        }
        return interop::GPUSampler::Create<GPUSampler>(env, device_.CreateSampler(&desc));
    }

    interop::Interface<interop::GPUExternalTexture> GPUDevice::importExternalTexture(
        Napi::Env,
        interop::GPUExternalTextureDescriptor descriptor) {
        UNIMPLEMENTED();
    }

    interop::Interface<interop::GPUBindGroupLayout> GPUDevice::createBindGroupLayout(
        Napi::Env env,
        interop::GPUBindGroupLayoutDescriptor descriptor) {
        Converter conv(env);

        wgpu::BindGroupLayoutDescriptor desc{};
        if (!conv(desc.label, descriptor.label) ||
            !conv(desc.entries, desc.entryCount, descriptor.entries)) {
            return {};
        }

        return interop::GPUBindGroupLayout::Create<GPUBindGroupLayout>(
            env, device_.CreateBindGroupLayout(&desc));
    }

    interop::Interface<interop::GPUPipelineLayout> GPUDevice::createPipelineLayout(
        Napi::Env env,
        interop::GPUPipelineLayoutDescriptor descriptor) {
        Converter conv(env);

        wgpu::PipelineLayoutDescriptor desc{};
        if (!conv(desc.label, descriptor.label) ||
            !conv(desc.bindGroupLayouts, desc.bindGroupLayoutCount, descriptor.bindGroupLayouts)) {
            return {};
        }

        return interop::GPUPipelineLayout::Create<GPUPipelineLayout>(
            env, device_.CreatePipelineLayout(&desc));
    }

    interop::Interface<interop::GPUBindGroup> GPUDevice::createBindGroup(
        Napi::Env env,
        interop::GPUBindGroupDescriptor descriptor) {
        Converter conv(env);

        wgpu::BindGroupDescriptor desc{};
        if (!conv(desc.label, descriptor.label) || !conv(desc.layout, descriptor.layout) ||
            !conv(desc.entries, desc.entryCount, descriptor.entries)) {
            return {};
        }

        return interop::GPUBindGroup::Create<GPUBindGroup>(env, device_.CreateBindGroup(&desc));
    }

    interop::Interface<interop::GPUShaderModule> GPUDevice::createShaderModule(
        Napi::Env env,
        interop::GPUShaderModuleDescriptor descriptor) {
        Converter conv(env);

        wgpu::ShaderModuleWGSLDescriptor wgsl_desc{};
        wgpu::ShaderModuleDescriptor sm_desc{};
        if (!conv(wgsl_desc.source, descriptor.code) || !conv(sm_desc.label, descriptor.label)) {
            return {};
        }
        sm_desc.nextInChain = &wgsl_desc;

        return interop::GPUShaderModule::Create<GPUShaderModule>(
            env, device_.CreateShaderModule(&sm_desc), async_);
    }

    interop::Interface<interop::GPUComputePipeline> GPUDevice::createComputePipeline(
        Napi::Env env,
        interop::GPUComputePipelineDescriptor descriptor) {
        Converter conv(env);

        wgpu::ComputePipelineDescriptor desc{};
        if (!conv(desc, descriptor)) {
            return {};
        }

        return interop::GPUComputePipeline::Create<GPUComputePipeline>(
            env, device_.CreateComputePipeline(&desc));
    }

    interop::Interface<interop::GPURenderPipeline> GPUDevice::createRenderPipeline(
        Napi::Env env,
        interop::GPURenderPipelineDescriptor descriptor) {
        Converter conv(env);

        wgpu::RenderPipelineDescriptor desc{};
        if (!conv(desc, descriptor)) {
            return {};
        }

        return interop::GPURenderPipeline::Create<GPURenderPipeline>(
            env, device_.CreateRenderPipeline(&desc));
    }

    interop::Promise<interop::Interface<interop::GPUComputePipeline>>
    GPUDevice::createComputePipelineAsync(Napi::Env env,
                                          interop::GPUComputePipelineDescriptor descriptor) {
        using Promise = interop::Promise<interop::Interface<interop::GPUComputePipeline>>;

        Converter conv(env);

        wgpu::ComputePipelineDescriptor desc{};
        if (!conv(desc, descriptor)) {
            Promise promise(env, PROMISE_INFO);
            promise.Reject(Errors::OperationError(env));
            return promise;
        }

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

        device_.CreateComputePipelineAsync(
            &desc,
            [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline,
               char const* message, void* userdata) {
                auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));

                switch (status) {
                    case WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_Success:
                        c->promise.Resolve(interop::GPUComputePipeline::Create<GPUComputePipeline>(
                            c->env, pipeline));
                        break;
                    default:
                        c->promise.Reject(Errors::OperationError(c->env));
                        break;
                }
            },
            ctx);

        return promise;
    }

    interop::Promise<interop::Interface<interop::GPURenderPipeline>>
    GPUDevice::createRenderPipelineAsync(Napi::Env env,
                                         interop::GPURenderPipelineDescriptor descriptor) {
        using Promise = interop::Promise<interop::Interface<interop::GPURenderPipeline>>;

        Converter conv(env);

        wgpu::RenderPipelineDescriptor desc{};
        if (!conv(desc, descriptor)) {
            Promise promise(env, PROMISE_INFO);
            promise.Reject(Errors::OperationError(env));
            return promise;
        }

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

        device_.CreateRenderPipelineAsync(
            &desc,
            [](WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline,
               char const* message, void* userdata) {
                auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));

                switch (status) {
                    case WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_Success:
                        c->promise.Resolve(interop::GPURenderPipeline::Create<GPURenderPipeline>(
                            c->env, pipeline));
                        break;
                    default:
                        c->promise.Reject(Errors::OperationError(c->env));
                        break;
                }
            },
            ctx);

        return promise;
    }

    interop::Interface<interop::GPUCommandEncoder> GPUDevice::createCommandEncoder(
        Napi::Env env,
        interop::GPUCommandEncoderDescriptor descriptor) {
        wgpu::CommandEncoderDescriptor desc{};
        return interop::GPUCommandEncoder::Create<GPUCommandEncoder>(
            env, device_.CreateCommandEncoder(&desc));
    }

    interop::Interface<interop::GPURenderBundleEncoder> GPUDevice::createRenderBundleEncoder(
        Napi::Env env,
        interop::GPURenderBundleEncoderDescriptor descriptor) {
        Converter conv(env);

        wgpu::RenderBundleEncoderDescriptor desc{};
        if (!conv(desc.label, descriptor.label) ||
            !conv(desc.colorFormats, desc.colorFormatsCount, descriptor.colorFormats) ||
            !conv(desc.depthStencilFormat, descriptor.depthStencilFormat) ||
            !conv(desc.sampleCount, descriptor.sampleCount)) {
            return {};
        }

        return interop::GPURenderBundleEncoder::Create<GPURenderBundleEncoder>(
            env, device_.CreateRenderBundleEncoder(&desc));
    }

    interop::Interface<interop::GPUQuerySet> GPUDevice::createQuerySet(
        Napi::Env env,
        interop::GPUQuerySetDescriptor descriptor) {
        Converter conv(env);

        wgpu::QuerySetDescriptor desc{};
        if (!conv(desc.label, descriptor.label) || !conv(desc.type, descriptor.type) ||
            !conv(desc.count, descriptor.count) ||
            !conv(desc.pipelineStatistics, desc.pipelineStatisticsCount,
                  descriptor.pipelineStatistics)) {
            return {};
        }

        return interop::GPUQuerySet::Create<GPUQuerySet>(env, device_.CreateQuerySet(&desc));
    }

    interop::Promise<interop::Interface<interop::GPUDeviceLostInfo>> GPUDevice::getLost(
        Napi::Env env) {
        auto promise =
            interop::Promise<interop::Interface<interop::GPUDeviceLostInfo>>(env, PROMISE_INFO);
        lost_promises_.emplace_back(promise);
        return promise;
    }

    void GPUDevice::pushErrorScope(Napi::Env env, interop::GPUErrorFilter filter) {
        wgpu::ErrorFilter f;
        switch (filter) {
            case interop::GPUErrorFilter::kOutOfMemory:
                f = wgpu::ErrorFilter::OutOfMemory;
                break;
            case interop::GPUErrorFilter::kValidation:
                f = wgpu::ErrorFilter::Validation;
                break;
            default:
                Napi::Error::New(env, "unhandled GPUErrorFilter value")
                    .ThrowAsJavaScriptException();
                return;
        }
        device_.PushErrorScope(f);
    }

    interop::Promise<std::optional<interop::GPUError>> GPUDevice::popErrorScope(Napi::Env env) {
        using Promise = interop::Promise<std::optional<interop::GPUError>>;
        struct Context {
            Napi::Env env;
            Promise promise;
            AsyncTask task;
        };
        auto* ctx = new Context{env, Promise(env, PROMISE_INFO), async_};
        auto promise = ctx->promise;

        bool ok = device_.PopErrorScope(
            [](WGPUErrorType type, char const* message, void* userdata) {
                auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));
                auto env = c->env;
                switch (type) {
                    case WGPUErrorType::WGPUErrorType_NoError:
                        c->promise.Resolve({});
                        break;
                    case WGPUErrorType::WGPUErrorType_OutOfMemory:
                        c->promise.Resolve(interop::GPUOutOfMemoryError::Create<OOMError>(env));
                        break;
                    case WGPUErrorType::WGPUErrorType_Unknown:
                    case WGPUErrorType::WGPUErrorType_DeviceLost:
                    case WGPUErrorType::WGPUErrorType_Validation:
                        c->promise.Resolve(
                            interop::GPUValidationError::Create<ValidationError>(env, message));
                        break;
                    default:
                        c->promise.Reject("unhandled error type");
                        break;
                }
            },
            ctx);

        if (ok) {
            return promise;
        }

        delete ctx;
        promise.Reject(Errors::OperationError(env));
        return promise;
    }

    std::optional<std::string> GPUDevice::getLabel(Napi::Env) {
        UNIMPLEMENTED();
    };

    void GPUDevice::setLabel(Napi::Env, std::optional<std::string> value) {
        UNIMPLEMENTED();
    };

    interop::Interface<interop::EventHandler> GPUDevice::getOnuncapturederror(Napi::Env) {
        UNIMPLEMENTED();
    }

    void GPUDevice::setOnuncapturederror(Napi::Env,
                                         interop::Interface<interop::EventHandler> value) {
        UNIMPLEMENTED();
    }

    void GPUDevice::addEventListener(
        Napi::Env,
        std::string type,
        std::optional<interop::Interface<interop::EventListener>> callback,
        std::optional<std::variant<interop::AddEventListenerOptions, bool>> options) {
        UNIMPLEMENTED();
    }

    void GPUDevice::removeEventListener(
        Napi::Env,
        std::string type,
        std::optional<interop::Interface<interop::EventListener>> callback,
        std::optional<std::variant<interop::EventListenerOptions, bool>> options) {
        UNIMPLEMENTED();
    }

    bool GPUDevice::dispatchEvent(Napi::Env, interop::Interface<interop::Event> event) {
        UNIMPLEMENTED();
    }

}  // namespace wgpu::binding
