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

#include <memory>
#include <utility>
#include <vector>

#include "src/dawn/node/utils/Debug.h"

namespace wgpu::binding {

////////////////////////////////////////////////////////////////////////////////
// wgpu::bindings::GPUShaderModule
////////////////////////////////////////////////////////////////////////////////
GPUShaderModule::GPUShaderModule(wgpu::ShaderModule shader, std::shared_ptr<AsyncRunner> async)
    : shader_(std::move(shader)), async_(std::move(async)) {}

interop::Promise<interop::Interface<interop::GPUCompilationInfo>> GPUShaderModule::compilationInfo(
    Napi::Env env) {
    struct GPUCompilationMessage : public interop::GPUCompilationMessage {
        WGPUCompilationMessage message;

        explicit GPUCompilationMessage(const WGPUCompilationMessage& m) : message(m) {}
        std::string getMessage(Napi::Env) override { return message.message; }
        interop::GPUCompilationMessageType getType(Napi::Env) override {
            switch (message.type) {
                case WGPUCompilationMessageType_Error:
                    return interop::GPUCompilationMessageType::kError;
                case WGPUCompilationMessageType_Warning:
                    return interop::GPUCompilationMessageType::kWarning;
                case WGPUCompilationMessageType_Info:
                    return interop::GPUCompilationMessageType::kInfo;
                default:
                    UNIMPLEMENTED();
            }
        }
        uint64_t getLineNum(Napi::Env) override { return message.lineNum; }
        uint64_t getLinePos(Napi::Env) override { return message.linePos; }
        uint64_t getOffset(Napi::Env) override { return message.offset; }
        uint64_t getLength(Napi::Env) override { return message.length; }
    };

    using Messages = std::vector<interop::Interface<interop::GPUCompilationMessage>>;

    struct GPUCompilationInfo : public interop::GPUCompilationInfo {
        std::vector<Napi::ObjectReference> messages;

        GPUCompilationInfo(Napi::Env env, Messages msgs) {
            messages.reserve(msgs.size());
            for (auto& msg : msgs) {
                messages.emplace_back(Napi::Persistent(Napi::Object(env, msg)));
            }
        }
        Messages getMessages(Napi::Env) override {
            Messages out;
            out.reserve(messages.size());
            for (auto& msg : messages) {
                out.emplace_back(msg.Value());
            }
            return out;
        }
    };

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

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

    shader_.GetCompilationInfo(
        [](WGPUCompilationInfoRequestStatus status, WGPUCompilationInfo const* compilationInfo,
           void* userdata) {
            auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));

            Messages messages(compilationInfo->messageCount);
            for (uint32_t i = 0; i < compilationInfo->messageCount; i++) {
                auto& msg = compilationInfo->messages[i];
                messages[i] =
                    interop::GPUCompilationMessage::Create<GPUCompilationMessage>(c->env, msg);
            }

            c->promise.Resolve(interop::GPUCompilationInfo::Create<GPUCompilationInfo>(
                c->env, c->env, std::move(messages)));
        },
        ctx);

    return promise;
}

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

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

}  // namespace wgpu::binding
