//
// Created by 12567 on 2021/3/31.
//

#include <jni.h>
#include <syscall.h>
#include "wdun.h"
#include "cJSON.h"
#include "wd_jni.h"
#include "collect.h"
#include "fake_dlfcn.h"

//import asm symbol
IMPORTWDSYSCALL

#define WDMAIN_CLASS_NAME              "com/reyun/wandun/WdMain"
#define WDMAIN_GETWDID_METHOD_NAME     "getWdIdNative"
#define WDMAIN_GETWDID_METHOD_SIG      "()Ljava/lang/String;"
#define WDMAIN_INIT_METHOD_NAME        "initNative"
#define WDMAIN_INIT_METHOD_SIG         "(Landroid/content/Context;)V"

jobject g_app_context = NULL;

struct wd_funcs g_funcs;

JNIEXPORT jstring jni_get_wdid(JNIEnv* env, jobject thiz) {
    return do_collect(env);
}

JNIEXPORT void jni_init(JNIEnv* env, jobject thiz, jobject context) {
    if(!g_app_context) {
        g_app_context = (*env)->NewGlobalRef(env, context);
    }
}

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    logd("wdun_core", "%s", "enter jni_onload...");
    JNIEnv* env = NULL;
    if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) == JNI_OK) {
        jclass cls = (*env)->FindClass(env, WDMAIN_CLASS_NAME);
        JNINativeMethod methods[] = {{WDMAIN_GETWDID_METHOD_NAME, WDMAIN_GETWDID_METHOD_SIG, (void*)jni_get_wdid},
                                     {WDMAIN_INIT_METHOD_NAME, WDMAIN_INIT_METHOD_SIG, (void*)jni_init}};
        (*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(JNINativeMethod));
        (*env)->DeleteLocalRef(env, cls);
    }

    logd("wdun_core", "%s", "find libc symbol...");

    //find libc needed symbol
    struct so_info* si = fake_dlopen("libc.so", 0);
    if(si != NULL) {
        g_funcs.wd_popen = fake_dlsym(si, "popen");
        g_funcs.wd_pclose = fake_dlsym(si, "pclose");
        g_funcs.wd_system_property_get = fake_dlsym(si, "__system_property_get");
        fake_dlclose(si);
    }
    if(!g_funcs.wd_popen) g_funcs.wd_popen = popen;
    if(!g_funcs.wd_pclose) g_funcs.wd_pclose = pclose;
    if(!g_funcs.wd_system_property_get) g_funcs.wd_system_property_get = __system_property_get;
    logd("wdun_core", "%s", "leave jni_onload...");
    return JNI_VERSION_1_6;
}

