#include <emscripten.h>
#include <emscripten/bind.h>

#include <unordered_map>

namespace fugg {
    namespace embind {
        using TypeID = emscripten::internal::TYPEID;
        using GenericWireType = emscripten::internal::EM_GENERIC_WIRE_TYPE;
        using VariableArguments = emscripten::internal::GenericWireType*;
        using Value = emscripten::EM_VAL; 
        using Destructors = emscripten::internal::EM_DESTRUCTORS;

        enum class Type {
            // Primitives
            Void,
            Bool,
            Integer,
            Float,
            Emval,
            // Complex
            String,
            WideString,
            MemoryView,
        };

        struct TypeInfo {
            std::string name;
            Type type;
        };


        struct FunctionEntry {
            uintptr_t invoker;
            uintptr_t fn;
        };

        struct MethodCaller {
            const emscripten::internal::TYPEID return_type;
            const unsigned int arg_count;
            const emscripten::internal::TYPEID* arg_types;
        };

        extern std::unordered_map<TypeID, const TypeInfo *const> kTypeMap;
        extern std::unordered_map<std::string, const FunctionEntry *const> kFunctionMap;
        extern std::unordered_map<emscripten::internal::EM_METHOD_CALLER, MethodCaller*> kMethodCallers;
    }
}