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