#include <jni.h>
#include <ctime>
#include "external/json/json.h"
#include "tool_kit.h"
#include "comm_map.h"
#include "yylog.h"
#include "external/md5/md5.h"
#include "aes_kit.h"
//
// Created by KaiWeiCai on 2022/1/14.
//


#define API_KEY "qDikI9v?>!x)1rS&yo"


#ifdef __cplusplus
extern "C" {
#endif


void InitSdkDrive(JNIEnv *env, jobject clz, jobject context) {
    CommMap::GetInstance()->Init(env, context);

}
jstring InvokeJobWithoutParams(JNIEnv *env,jobject clz,jstring data){
    const char  *_data = env->GetStringUTFChars(data,JNI_FALSE);
    time_t t;
    long ts = time(&t);
    Json::Value root = ToolKit::ToJsonObject(_data);
    std::string timestamp = std::to_string(ts);
    std::string sort_signature = ToolKit::GetJsonSortSignature(root);
    sort_signature.append("&time=").append(timestamp).append(API_KEY);
    YYLog::D(env, "before md5: " + sort_signature);
    std::string sign = md5(sort_signature);

    root["time"]= timestamp;
    root["sign"]= sign;

    std::string random_str = ToolKit::GenerateRandString(5);
    std::string request_data = random_str.append(ToolKit::ToJsonString(root));

    jstring result = AesKit::Encrypt(env, request_data.c_str());


    YYLog::D(env, "请求路由: " + root["route_path"].asString());
    YYLog::D(env, "请求参数: " + request_data);

    YYLog::LogHandler(env, "请求路由: " + root["route_path"].asString() + "\n");
    YYLog::LogHandler(env, "请求参数: " + request_data + "\n");


    if (_data) {
        env->ReleaseStringUTFChars(data, _data);
    }
    return result;
}


jstring InvokeJob(JNIEnv *env,jobject clz,jstring data){
    const char  *_data = env->GetStringUTFChars(data,JNI_FALSE);
    time_t t;
    long ts = time(&t);
    Json::Value root = ToolKit::ToJsonObject(_data);
    Json::Value::Members members = CommMap::GetInstance()->comm_params.getMemberNames();
    for (auto &member:members) {
        root[member] = CommMap::GetInstance()->comm_params[member];
    }
    std::string timestamp = std::to_string(ts);
    std::string sort_signature = ToolKit::GetJsonSortSignature(root);
    sort_signature.append("&time=").append(timestamp).append(API_KEY);
    YYLog::D(env, "before md5: " + sort_signature);
    std::string sign = md5(sort_signature);

    root["time"]= timestamp;
    root["sign"]= sign;

    std::string random_str = ToolKit::GenerateRandString(5);
    std::string request_data = random_str.append(ToolKit::ToJsonString(root));

    jstring result = AesKit::Encrypt(env, request_data.c_str());


    YYLog::D(env, "请求路由: " + root["route_path"].asString());
    YYLog::D(env, "请求参数: " + request_data);

    YYLog::LogHandler(env, "请求路由: " + root["route_path"].asString() + "\n");
    YYLog::LogHandler(env, "请求参数: " + request_data + "\n");


    if (_data) {
        env->ReleaseStringUTFChars(data, _data);
    }
    return result;



}

jstring ParseJob(JNIEnv *env,jobject clz,jstring data){
    const char *_data = env->GetStringUTFChars(data,JNI_FALSE);
    jstring result = AesKit::Decrypt(env,_data);
    if (_data){
        env->ReleaseStringUTFChars(data,_data);
    }
    return result;

}

static JNINativeMethod gMethods[] = {

        {"initDrive",  "(Landroid/content/Context;)V",            (void *) InitSdkDrive},
        {"invokeJobWithoutParams", "(Ljava/lang/String;)Ljava/lang/String;",  (void *) InvokeJobWithoutParams},
//        {"setParam",   "(Ljava/lang/String;Ljava/lang/String;)V", (void *) SetParam},
//        {"getParam",   "(Ljava/lang/String;)Ljava/lang/String;",  (void *) GetParam},
        {"invokeJob",  "(Ljava/lang/String;)Ljava/lang/String;",  (void *) InvokeJob},
        {"parseJob",   "(Ljava/lang/String;)Ljava/lang/String;",  (void *) ParseJob},
//        {"RsaEncrypt", "(Ljava/lang/String;)Ljava/lang/String;",  (void *) RsaEncrypt}
};

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/commsdk/core/SdkDrive");
    if (env->RegisterNatives(clz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

#ifdef __cplusplus
}
#endif