#ifndef COMMON_H
#define COMMON_H

#include "jsi-helpers.h"
#include <logger.h>
#include <sys/types.h>
#include <thread>
#include <plugger-react-native.h>

using namespace facebook::jsi;
namespace jsi = facebook::jsi;

using namespace std;

// Methods That Need to Be Injected

static jsi::Value initializePluggerInSync(
        jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments,
        std::size_t count) {
    jsi::Value retVal = executeJNIFunction(runtime, thisValue, arguments, count,
                                           "initializePluggerInSync",
                                           "(Ljava/util/HashMap;)Ljava/lang/Boolean;",
                                           false);
    return retVal;
}

static jsi::Value setLocation(
        jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments,
        std::size_t count) {
    jsi::Value retVal = executeJNIFunction(runtime, thisValue, arguments, count,
                                           "setLocation",
                                           "(Ljava/lang/Double;Ljava/lang/Double;)V",
                                           true);
    return retVal;
}

static jsi::Value setGuest(
        jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments,
        std::size_t count) {
    jsi::Value retVal = executeJNIFunction(runtime, thisValue, arguments, count,
                                           "setGuest",
                                           "(Ljava/lang/String;)V",
                                           true);
    return retVal;
}

static jsi::Value setUser(
        jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments,
        std::size_t count) {
    jsi::Value retVal = executeJNIFunction(runtime, thisValue, arguments, count,
                                           "setUser",
                                           "(Ljava/lang/String;)V",
                                           true);
    return retVal;
}

static jsi::Value isPluggerInitialized(
        jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments,
        std::size_t count) {
    jsi::Value retVal = executeJNIFunction(runtime, thisValue, arguments, count,
                                           "isPluggerInitialized",
                                           "()Ljava/lang/Boolean;",
                                           false);
    return retVal;
}


// Installing Methods in JSI Runtime

void install(Runtime &jsiRuntime) {

    Object module = Object(jsiRuntime);

    registerCxxFunction(jsiRuntime,module, "initializePluggerInSync", 1, initializePluggerInSync);
    registerCxxFunction(jsiRuntime,module, "setLocation", 2, setLocation);
    registerCxxFunction(jsiRuntime,module, "setGuest", 1, setGuest);
    registerCxxFunction(jsiRuntime,module, "setUser", 1, setUser);
    registerCxxFunction(jsiRuntime,module, "isPluggerInitialized", 0, isPluggerInitialized);

    jsiRuntime.global().setProperty(jsiRuntime, "PluggerJSIModule", std::move(module));
}

extern "C" JNIEXPORT void JNICALL
Java_com_pluggerreactnative_PluggerReactNativeModule_nativeInstall(JNIEnv *env, jobject thiz,
                                                                   jlong jsi) {
    LOGI("Java_com_pluggerreactnative_PluggerReactNativeModule_nativeInstall");
    auto runtime = reinterpret_cast<jsi::Runtime *>(jsi);
    if (runtime) {
        LOGI("invoking pluggerreactnative::install");
        pluggerreactnative::install(*runtime);
        install(*runtime);
    }
    env->GetJavaVM(&java_vm);
    java_object = env->NewGlobalRef(thiz);
}

#endif /* COMMON_H */
