//
// Created by #Suyghur, on 2021/06/09.
//



#include <jni.h>
#include <toolkit.h>
#include <comm_map.h>
#include <params_kit.h>
#include <request_kit.h>
#include <md5/md5.h>
#include "include/logger.h"
#include "aes/aes_utils.h"

static void InitSdkDrive(JNIEnv *env, jobject thiz, jobject context) {
    CommMap::GetInstance()->Init(env, context);
    Logger::is_debug = ParamsKit::GetDebugModel(env, context);
    Logger::D(env, ToolKit::ToJsonString(CommMap::GetInstance()->comm_params));
}

static void SetParam(JNIEnv *env, jobject thiz, jstring key, jstring value) {
    std::string key_ = ToolKit::JString2String(env, key);
    std::string value_ = ToolKit::JString2String(env, value);
    if (key_ == "device_id") {
        if (value_ == CommMap::GetInstance()->comm_params["android_id"].asString()) {
            CommMap::GetInstance()->comm_params["id_type"] = 1;
        } else {
            CommMap::GetInstance()->comm_params["id_type"] = 0;
        }
    }
    CommMap::GetInstance()->comm_params[key_] = value_;
    Logger::D(env, ToolKit::ToJsonString(CommMap::GetInstance()->comm_params));
}

static jstring GetParam(JNIEnv *env, jobject thiz, jstring key) {
    std::string key_ = ToolKit::JString2String(env, key);
    return env->NewStringUTF(CommMap::GetInstance()->comm_params[key_].asString().c_str());
}

static jstring InvokeJob(JNIEnv *env, jobject thiz, jobject context, jstring key, jstring data) {
    const char *key_ = env->GetStringUTFChars(key, JNI_FALSE);
    const char *data_ = env->GetStringUTFChars(data, JNI_FALSE);

    //添加公共参数
    Json::Value root = ToolKit::ToJsonObject(data_);
    root["common"] = CommMap::GetInstance()->comm_params;

    //生成aes key
//    char *raw_key = AesUtils::GetRawKey();
//    std::string md5_key = md5(raw_key);
//    auto *key64= static_cast<char *>(malloc(65));
//    memset(key64,0,64);
//    sprintf(key64,"%s%s",md5_key,reverse(md5_key.begin(),md5_key.end()))
//    std::string  aes_key=md5()
//    LOGD("test : %s", ToolKit::StrReverse(key_));
    char *p = AesUtils::Encrypt(ToolKit::ToJsonString(root).c_str(), reinterpret_cast<const uint8_t *>(key_));
    jstring result = ToolKit::GetJString(env, p);
    env->ReleaseStringUTFChars(key, key_);
    env->ReleaseStringUTFChars(data, data_);
//    delete (raw);
    free(p);
    return result;

//    std::string enc = RequestKit::EncryptRequest2(env, context, data);
//    env->ReleaseStringUTFChars(raw, raw_);
//    jstring result = ToolKit::GetJString(env, enc.c_str());
//    free(src);
//    std::string raw = ToolKit::ToJsonString(HandleRequest(env, params));
//    //aes key
//    char *raw_key = AesUtils::GetRawKey();
//    std::string raw_key_md5 = md5(raw_key);
//    char *iv_32 = AesUtils::GetIv32(raw_key_md5.c_str());
//    char *key_64 = static_cast<char *>(malloc(65));
//    sprintf(key_64, "%s%s", raw_key_md5.c_str(), iv_32);
//    key_64[65] = '\0';
//    std::string key = md5(key_64);
//    std::string aes_key = key.substr(8, 16);
//    std::string p = AesUtils::Encrypt(raw.c_str(), reinterpret_cast<const uint8_t *>(aes_key.c_str()));
//    Json::Value root;
//    root["p"] = p;
//    root["ts"] = raw_key_md5;
//    free(raw_key);
//    free(iv_32);
//    free(key_64);
//    delete aes_key;
//    free((void *) aes_key);
}

static jstring ParseJob(JNIEnv *env, jobject thiz, jobject context, jstring key, jstring data) {
    const char *key_ = env->GetStringUTFChars(key, JNI_FALSE);
    const char *data_ = env->GetStringUTFChars(data, JNI_FALSE);

//    Json::Value root = ToolKit::ToJsonObject(data_);
//    const char *p = root["p"].asCString();
    char *raw = AesUtils::Decrypt(data_, reinterpret_cast<const uint8_t *>(key_));
    jstring result = ToolKit::GetJString(env, raw);
    env->ReleaseStringUTFChars(key, key_);
    env->ReleaseStringUTFChars(data, data_);
//    delete (p);
    free(raw);
    return result;
//    std::string raw = RequestKit::DecryptResponse2(env, context, data);
//    jstring result = ToolKit::GetJString(env, raw.c_str());
//    return result;
//    time_t ts = time(nullptr);
//    LOGD("%ld", ts);
//    char *key = AesUtils::GetRawKey();
//    return env->NewStringUTF("");
}

static jstring Test(JNIEnv *env, jobject thiz) {
    char *key = AesUtils::GetRawKey();
    jstring result = ToolKit::GetJString(env, key);
    free(key);
    return result;
}

static JNINativeMethod gMethod[] = {
        {"initSdkDrive", "(Landroid/content/Context;)V",                                                      (void *) InitSdkDrive},
        {"setParam",     "(Ljava/lang/String;Ljava/lang/String;)V",                                           (void *) SetParam},
        {"getParam",     "(Ljava/lang/String;)Ljava/lang/String;",                                            (void *) GetParam},
        {"invokeJob",    "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) InvokeJob},
        {"parseJob",     "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) ParseJob},
        {"test",         "()Ljava/lang/String;",                                                              (void *) Test},
};

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = nullptr;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    jclass clz = env->FindClass("cn/yyxx/eyuangame/core/impl/SdkDrive");
    if (env->RegisterNatives(clz, gMethod, sizeof(gMethod) / sizeof(gMethod[0])) < 0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}