// 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.

// This file provides core interop helpers used by the code generated by the
// templates.

#ifndef DAWN_NODE_INTEROP_CORE_WEBGPU_H_
#define DAWN_NODE_INTEROP_CORE_WEBGPU_H_

#include <cstdint>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <variant>
#include <vector>

#include "napi.h"

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

#define ENABLE_INTEROP_LOGGING 0  // Enable for verbose interop logging

#if ENABLE_INTEROP_LOGGING
#    define INTEROP_LOG(...) LOG(__VA_ARGS__)
#else
#    define INTEROP_LOG(...)
#endif

// A helper macro for constructing a PromiseInfo with the current file, function and line.
// See PromiseInfo
#define PROMISE_INFO                     \
    ::wgpu::interop::PromiseInfo {       \
        __FILE__, __FUNCTION__, __LINE__ \
    }

namespace wgpu::interop {

    ////////////////////////////////////////////////////////////////////////////////
    // Primitive JavaScript types
    ////////////////////////////////////////////////////////////////////////////////
    using Object = Napi::Object;
    using ArrayBuffer = Napi::ArrayBuffer;
    using Int8Array = Napi::TypedArrayOf<int8_t>;
    using Int16Array = Napi::TypedArrayOf<int16_t>;
    using Int32Array = Napi::TypedArrayOf<int32_t>;
    using Uint8Array = Napi::TypedArrayOf<uint8_t>;
    using Uint16Array = Napi::TypedArrayOf<uint16_t>;
    using Uint32Array = Napi::TypedArrayOf<uint32_t>;
    using Float32Array = Napi::TypedArrayOf<float>;
    using Float64Array = Napi::TypedArrayOf<double>;
    using DataView = Napi::TypedArray;

    template <typename T>
    using FrozenArray = std::vector<T>;

    ////////////////////////////////////////////////////////////////////////////////
    // Result
    ////////////////////////////////////////////////////////////////////////////////

    // Result is used to hold an success / error state by functions that perform JS <-> C++
    // conversion
    struct [[nodiscard]] Result {
        // Returns true if the operation succeeded, false if there was an error
        inline operator bool() const {
            return error.empty();
        }

        // If Result is an error, then a new Error is returned with the
        // stringified values append to the error message.
        // If Result is a success, then a success Result is returned.
        template <typename... VALUES>
        Result Append(VALUES && ... values) {
            if (*this) {
                return *this;
            }
            std::stringstream ss;
            ss << error << "\n";
            utils::Write(ss, std::forward<VALUES>(values)...);
            return {ss.str()};
        }

        // The error message, if the operation failed.
        std::string error;
    };

    // A successful result
    extern Result Success;

    // Returns a Result with the given error message
    Result Error(std::string msg);

    ////////////////////////////////////////////////////////////////////////////////
    // Interface<T>
    ////////////////////////////////////////////////////////////////////////////////

    // Interface<T> is a templated wrapper around a JavaScript object, which
    // implements the template-generated interface type T. Interfaces are returned
    // by either calling T::Bind() or T::Create().
    template <typename T>
    class Interface {
      public:
        // Constructs an Interface with no JS object.
        inline Interface() {
        }

        // Constructs an Interface wrapping the given JS object.
        // The JS object must have been created with a call to T::Bind().
        explicit inline Interface(Napi::Object o) : object(o) {
        }

        // Implicit conversion operators to Napi objects.
        inline operator napi_value() const {
            return object;
        }
        inline operator const Napi::Value&() const {
            return object;
        }
        inline operator const Napi::Object&() const {
            return object;
        }

        // Member and dereference operators
        inline T* operator->() const {
            return T::Unwrap(object);
        }
        inline T* operator*() const {
            return T::Unwrap(object);
        }

        // As<IMPL>() returns the unwrapped object cast to the implementation type.
        // The interface implementation *must* be of the template type IMPL.
        template <typename IMPL>
        inline IMPL* As() const {
            return static_cast<IMPL*>(T::Unwrap(object));
        }

      private:
        Napi::Object object;
    };

    ////////////////////////////////////////////////////////////////////////////////
    // Promise<T>
    ////////////////////////////////////////////////////////////////////////////////

    // Info holds details about where the promise was constructed.
    // Used for printing debug messages when a promise is finalized without being resolved
    // or rejected.
    // Use the PROMISE_INFO macro to populate this structure.
    struct PromiseInfo {
        const char* file = nullptr;
        const char* function = nullptr;
        int line = 0;
    };

    namespace detail {
        // Base class for Promise<T> specializations.
        class PromiseBase {
          public:
            // Implicit conversion operators to Napi promises.
            inline operator napi_value() const {
                return state->deferred.Promise();
            }
            inline operator Napi::Value() const {
                return state->deferred.Promise();
            }
            inline operator Napi::Promise() const {
                return state->deferred.Promise();
            }

            // Reject() rejects the promise with the given failure value.
            void Reject(Napi::Value value) const {
                state->deferred.Reject(value);
                state->resolved_or_rejected = true;
            }
            void Reject(Napi::Error err) const {
                Reject(err.Value());
            }
            void Reject(std::string err) const {
                Reject(Napi::Error::New(state->deferred.Env(), err));
            }

          protected:
            void Resolve(Napi::Value value) const {
                state->deferred.Resolve(value);
                state->resolved_or_rejected = true;
            }

            struct State {
                Napi::Promise::Deferred deferred;
                PromiseInfo info;
                bool resolved_or_rejected = false;
            };

            PromiseBase(Napi::Env env, const PromiseInfo& info)
                : state(new State{Napi::Promise::Deferred::New(env), info}) {
                state->deferred.Promise().AddFinalizer(
                    [](Napi::Env, State* state) {
                        // TODO(https://github.com/gpuweb/cts/issues/784):
                        // Devices are never destroyed, so we always end up
                        // leaking the Device.lost promise. Enable this once
                        // fixed.
                        if ((false)) {
                            if (!state->resolved_or_rejected) {
                                ::wgpu::utils::Fatal("Promise not resolved or rejected",
                                                     state->info.file, state->info.line,
                                                     state->info.function);
                            }
                        }
                        delete state;
                    },
                    state);
            }

            State* const state;
        };
    }  // namespace detail

    // Promise<T> is a templated wrapper around a JavaScript promise, which can
    // resolve to the template type T.
    template <typename T>
    class Promise : public detail::PromiseBase {
      public:
        // Constructor
        Promise(Napi::Env env, const PromiseInfo& info) : PromiseBase(env, info) {
        }

        // Resolve() fulfills the promise with the given value.
        void Resolve(T&& value) const {
            PromiseBase::Resolve(ToJS(state->deferred.Env(), std::forward<T>(value)));
        }
    };

    // Specialization for Promises that resolve with no value
    template <>
    class Promise<void> : public detail::PromiseBase {
      public:
        // Constructor
        Promise(Napi::Env env, const PromiseInfo& info) : PromiseBase(env, info) {
        }

        // Resolve() fulfills the promise.
        void Resolve() const {
            PromiseBase::Resolve(state->deferred.Env().Undefined());
        }
    };

    ////////////////////////////////////////////////////////////////////////////////
    // Converter<T>
    ////////////////////////////////////////////////////////////////////////////////

    // Converter<T> is specialized for each type T which can be converted from C++
    // to JavaScript, or JavaScript to C++.
    // Each specialization of Converter<T> is expected to have two static methods
    // with the signatures:
    //
    //  // FromJS() converts the JavaScript value 'in' to the C++ value 'out'.
    //  static Result FromJS(Napi::Env, Napi::Value in, T& out);
    //
    //  // ToJS() converts the C++ value 'in' to a JavaScript value, and returns
    //  // this value.
    //  static Napi::Value ToJS(Napi::Env, T in);
    template <typename T>
    class Converter {};

    template <>
    class Converter<Napi::Object> {
      public:
        static inline Result FromJS(Napi::Env, Napi::Value value, Napi::Object& out) {
            if (value.IsObject()) {
                out = value.ToObject();
                return Success;
            }
            return Error("value is not an object");
        }
        static inline Napi::Value ToJS(Napi::Env, Napi::Object value) {
            return value;
        }
    };

    template <>
    class Converter<ArrayBuffer> {
      public:
        static inline Result FromJS(Napi::Env, Napi::Value value, ArrayBuffer& out) {
            if (value.IsArrayBuffer()) {
                out = value.As<ArrayBuffer>();
                return Success;
            }
            return Error("value is not a ArrayBuffer");
        };
        static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) {
            return value;
        }
    };

    template <>
    class Converter<Napi::TypedArray> {
      public:
        static inline Result FromJS(Napi::Env, Napi::Value value, Napi::TypedArray& out) {
            if (value.IsTypedArray()) {
                out = value.As<Napi::TypedArray>();
                return Success;
            }
            return Error("value is not a TypedArray");
        };
        static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) {
            return value;
        }
    };

    template <typename T>
    class Converter<Napi::TypedArrayOf<T>> {
      public:
        // clang-format off
        // The Napi element type of T
        static constexpr napi_typedarray_type element_type =
              std::is_same<T, int8_t>::value   ? napi_int8_array
            : std::is_same<T, uint8_t>::value  ? napi_uint8_array
            : std::is_same<T, int16_t>::value  ? napi_int16_array
            : std::is_same<T, uint16_t>::value ? napi_uint16_array
            : std::is_same<T, int32_t>::value  ? napi_int32_array
            : std::is_same<T, uint32_t>::value ? napi_uint32_array
            : std::is_same<T, float>::value    ? napi_float32_array
            : std::is_same<T, double>::value   ? napi_float64_array
            : std::is_same<T, int64_t>::value  ? napi_bigint64_array
            : std::is_same<T, uint64_t>::value ? napi_biguint64_array
            : static_cast<napi_typedarray_type>(-1);
        // clang-format on
        static_assert(static_cast<int>(element_type) >= 0,
                      "unsupported T type for Napi::TypedArrayOf<T>");
        static inline Result FromJS(Napi::Env, Napi::Value value, Napi::TypedArrayOf<T>& out) {
            if (value.IsTypedArray()) {
                auto arr = value.As<Napi::TypedArrayOf<T>>();
                if (arr.TypedArrayType() == element_type) {
                    out = arr;
                    return Success;
                }
                return Error("value is not a TypedArray of the correct element type");
            }
            return Error("value is not a TypedArray");
        };
        static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) {
            return value;
        }
    };

    template <>
    class Converter<std::string> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, std::string&);
        static Napi::Value ToJS(Napi::Env, std::string);
    };

    template <>
    class Converter<bool> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, bool&);
        static Napi::Value ToJS(Napi::Env, bool);
    };

    template <>
    class Converter<int8_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, int8_t&);
        static Napi::Value ToJS(Napi::Env, int8_t);
    };

    template <>
    class Converter<uint8_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, uint8_t&);
        static Napi::Value ToJS(Napi::Env, uint8_t);
    };

    template <>
    class Converter<int16_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, int16_t&);
        static Napi::Value ToJS(Napi::Env, int16_t);
    };

    template <>
    class Converter<uint16_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, uint16_t&);
        static Napi::Value ToJS(Napi::Env, uint16_t);
    };

    template <>
    class Converter<int32_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, int32_t&);
        static Napi::Value ToJS(Napi::Env, int32_t);
    };

    template <>
    class Converter<uint32_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, uint32_t&);
        static Napi::Value ToJS(Napi::Env, uint32_t);
    };

    template <>
    class Converter<int64_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, int64_t&);
        static Napi::Value ToJS(Napi::Env, int64_t);
    };

    template <>
    class Converter<uint64_t> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, uint64_t&);
        static Napi::Value ToJS(Napi::Env, uint64_t);
    };

    template <>
    class Converter<float> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, float&);
        static Napi::Value ToJS(Napi::Env, float);
    };

    template <>
    class Converter<double> {
      public:
        static Result FromJS(Napi::Env, Napi::Value, double&);
        static Napi::Value ToJS(Napi::Env, double);
    };

    template <typename T>
    class Converter<Interface<T>> {
      public:
        static Result FromJS(Napi::Env env, Napi::Value value, Interface<T>& out) {
            if (!value.IsObject()) {
                return Error("value is not object");
            }
            auto obj = value.As<Napi::Object>();
            if (!T::Unwrap(obj)) {
                return Error("object is not of the correct interface type");
            }
            out = Interface<T>(obj);
            return Success;
        }
        static Napi::Value ToJS(Napi::Env env, const Interface<T>& value) {
            return {env, value};
        }
    };

    template <typename T>
    class Converter<std::optional<T>> {
      public:
        static Result FromJS(Napi::Env env, Napi::Value value, std::optional<T>& out) {
            if (value.IsNull() || value.IsUndefined()) {
                out.reset();
                return Success;
            }
            T v{};
            auto res = Converter<T>::FromJS(env, value, v);
            if (!res) {
                return res;
            }
            out = std::move(v);
            return Success;
        }
        static Napi::Value ToJS(Napi::Env env, std::optional<T> value) {
            if (value.has_value()) {
                return Converter<T>::ToJS(env, value.value());
            }
            return env.Null();
        }
    };

    template <typename T>
    class Converter<std::vector<T>> {
      public:
        static inline Result FromJS(Napi::Env env, Napi::Value value, std::vector<T>& out) {
            if (!value.IsArray()) {
                return Error("value is not an array");
            }
            auto arr = value.As<Napi::Array>();
            std::vector<T> vec(arr.Length());
            for (size_t i = 0; i < vec.size(); i++) {
                auto res = Converter<T>::FromJS(env, arr[static_cast<uint32_t>(i)], vec[i]);
                if (!res) {
                    return res.Append("for array element ", i);
                }
            }
            out = std::move(vec);
            return Success;
        }
        static inline Napi::Value ToJS(Napi::Env env, const std::vector<T>& vec) {
            auto arr = Napi::Array::New(env, vec.size());
            for (size_t i = 0; i < vec.size(); i++) {
                arr.Set(static_cast<uint32_t>(i), Converter<T>::ToJS(env, vec[i]));
            }
            return arr;
        }
    };

    template <typename K, typename V>
    class Converter<std::unordered_map<K, V>> {
      public:
        static inline Result FromJS(Napi::Env env,
                                    Napi::Value value,
                                    std::unordered_map<K, V>& out) {
            if (!value.IsObject()) {
                return Error("value is not an object");
            }
            auto obj = value.ToObject();
            auto keys = obj.GetPropertyNames();
            std::unordered_map<K, V> map(keys.Length());
            for (uint32_t i = 0; i < static_cast<uint32_t>(keys.Length()); i++) {
                K key{};
                V value{};
                auto key_res = Converter<K>::FromJS(env, keys[i], key);
                if (!key_res) {
                    return key_res.Append("for object key");
                }
                auto value_res = Converter<V>::FromJS(env, obj.Get(keys[i]), value);
                if (!value_res) {
                    return value_res.Append("for object value of key: ", key);
                }
                map[key] = value;
            }
            out = std::move(map);
            return Success;
        }
        static inline Napi::Value ToJS(Napi::Env env, std::unordered_map<K, V> value) {
            auto obj = Napi::Object::New(env);
            for (auto it : value) {
                obj.Set(Converter<K>::ToJS(env, it.first), Converter<V>::ToJS(env, it.second));
            }
            return obj;
        }
    };

    template <typename... TYPES>
    class Converter<std::variant<TYPES...>> {
        template <typename TY>
        static inline Result TryFromJS(Napi::Env env,
                                       Napi::Value value,
                                       std::variant<TYPES...>& out) {
            TY v{};
            auto res = Converter<TY>::FromJS(env, value, v);
            if (!res) {
                return Error("no possible types matched");
            }
            out = std::move(v);
            return Success;
        }

        template <typename T0, typename T1, typename... TN>
        static inline Result TryFromJS(Napi::Env env,
                                       Napi::Value value,
                                       std::variant<TYPES...>& out) {
            if (TryFromJS<T0>(env, value, out)) {
                return Success;
            }
            return TryFromJS<T1, TN...>(env, value, out);
        }

      public:
        static inline Result FromJS(Napi::Env env, Napi::Value value, std::variant<TYPES...>& out) {
            return TryFromJS<TYPES...>(env, value, out);
        }
        static inline Napi::Value ToJS(Napi::Env env, std::variant<TYPES...> value) {
            return std::visit(
                [&](auto&& v) {
                    using T = std::remove_cv_t<std::remove_reference_t<decltype(v)>>;
                    return Converter<T>::ToJS(env, v);
                },
                value);
        }
    };

    template <typename T>
    class Converter<Promise<T>> {
      public:
        static inline Result FromJS(Napi::Env, Napi::Value, Promise<T>&) {
            UNIMPLEMENTED();
        }
        static inline Napi::Value ToJS(Napi::Env, Promise<T> promise) {
            return promise;
        }
    };

    ////////////////////////////////////////////////////////////////////////////////
    // Helpers
    ////////////////////////////////////////////////////////////////////////////////

    // FromJS() is a helper function which delegates to
    // Converter<T>::FromJS()
    template <typename T>
    inline Result FromJS(Napi::Env env, Napi::Value value, T& out) {
        return Converter<T>::FromJS(env, value, out);
    }

    // FromJSOptional() is similar to FromJS(), but if 'value' is either null
    // or undefined then 'out' is left unassigned.
    template <typename T>
    inline Result FromJSOptional(Napi::Env env, Napi::Value value, T& out) {
        if (value.IsNull() || value.IsUndefined()) {
            return Success;
        }
        return Converter<T>::FromJS(env, value, out);
    }

    // ToJS() is a helper function which delegates to Converter<T>::ToJS()
    template <typename T>
    inline Napi::Value ToJS(Napi::Env env, T&& value) {
        return Converter<std::remove_cv_t<std::remove_reference_t<T>>>::ToJS(
            env, std::forward<T>(value));
    }

    // DefaultedParameter can be used in the tuple parameter types passed to
    // FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args), for parameters
    // that have a default value. If the argument is omitted in the call, then
    // DefaultedParameter::default_value will be assigned to
    // DefaultedParameter::value.
    template <typename T>
    struct DefaultedParameter {
        T value;          // The argument value assigned by FromJS()
        T default_value;  // The default value if no argument supplied

        // Implicit conversion operator. Returns value.
        inline operator const T&() const {
            return value;
        }
    };

    // IsDefaultedParameter<T>::value is true iff T is of type DefaultedParameter.
    template <typename T>
    struct IsDefaultedParameter {
        static constexpr bool value = false;
    };
    template <typename T>
    struct IsDefaultedParameter<DefaultedParameter<T>> {
        static constexpr bool value = true;
    };

    // FromJS() is a helper function for bulk converting the arguments of 'info'.
    // PARAM_TYPES is a std::tuple<> describing the C++ function parameter types.
    // Parameters may be of the templated DefaultedParameter type, in which case
    // the parameter will default to the default-value if omitted.
    template <typename PARAM_TYPES, int BASE_INDEX = 0>
    inline Result FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args) {
        if constexpr (BASE_INDEX < std::tuple_size_v<PARAM_TYPES>) {
            using T = std::tuple_element_t<BASE_INDEX, PARAM_TYPES>;
            auto& value = info[BASE_INDEX];
            auto& out = std::get<BASE_INDEX>(args);
            if constexpr (IsDefaultedParameter<T>::value) {
                // Parameter has a default value.
                // Check whether the argument was provided.
                if (value.IsNull() || value.IsUndefined()) {
                    // Use default value for this parameter
                    out.value = out.default_value;
                } else {
                    // Argument was provided
                    auto res = FromJS(info.Env(), value, out.value);
                    if (!res) {
                        return res;
                    }
                }
            } else {
                // Parameter does not have a default value.
                auto res = FromJS(info.Env(), value, out);
                if (!res) {
                    return res;
                }
            }
            // Convert the rest of the arguments
            return FromJS<PARAM_TYPES, BASE_INDEX + 1>(info, args);
        } else {
            return Success;
        }
    }

}  // namespace wgpu::interop

#endif  //  DAWN_NODE_INTEROP_CORE_WEBGPU_H_
