// 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 { namespace 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) {
        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) {
        Converter conv(env);

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

        using Promise = interop::Promise<interop::Interface<interop::GPUComputePipeline>>;

        struct Context {
            Napi::Env env;
            Promise promise;
            AsyncTask task;
        };
        auto ctx = new Context{env, env, 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) {
        Converter conv(env);

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

        using Promise = interop::Promise<interop::Interface<interop::GPURenderPipeline>>;

        struct Context {
            Napi::Env env;
            Promise promise;
            AsyncTask task;
        };
        auto ctx = new Context{env, env, 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);
        lost_promises_.emplace_back(promise);
        return promise;
    }

    void GPUDevice::pushErrorScope(Napi::Env env, interop::GPUErrorFilter filter) {
        wgpu::ErrorFilter f = wgpu::ErrorFilter::None;
        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, env, 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 p(env);
        p.Resolve(
            interop::GPUValidationError::Create<ValidationError>(env, "failed to pop error scope"));
        return p;
    }

    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
