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