#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <com_sobot_chat_core_SobotUtil.h>
#include <md5.h>


static const uint8_t *getKey() {
    const int len = 13;
    uint8_t *src = malloc(len + 1);

    for (int i = 0; i < len; ++i) {
        switch (i) {
            case 0:  src[i] = 's'; break;
            case 1:  src[i] = 'o'; break;
            case 2:  src[i] = 'b'; break;
            case 3:  src[i] = 'o'; break;
            case 4:  src[i] = 't'; break;
            case 5:  src[i] = '*'; break;
            case 6:  src[i] = '&'; break;
            case 7:  src[i] = '^'; break;
            case 8:  src[i] = '%'; break;
            case 9:  src[i] = '$'; break;
            case 10: src[i] = '#'; break;
            case 11: src[i] = '@'; break;
            case 12: src[i] = '!'; break;
        }
    }
    src[len] = '\0';
    return src;
}

char *jstringToChar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env, "utf-8");
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) (*env)->CallObjectMethod(env, jstr, mid, strencode);
    jsize alen = (*env)->GetArrayLength(env, barr);
    jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);
    return rtn;
}

JNIEXPORT jstring JNICALL Java_com_sobot_chat_core_SobotUtil_getKey
  (JNIEnv *env, jclass j, jstring a, jstring b, jstring c, jstring d, jstring e){
    char *aa =jstringToChar(env,a);
    char *cc =jstringToChar(env,c);
    char *dd =jstringToChar(env,d);
    int len = strlen(aa) + strlen(dd)+ strlen(cc)+ strlen(getKey())+1;
    char *result = (char *) malloc(len);
    memset(result,0,len);
    sprintf(result, "%s%s%s%s", aa,dd,cc,getKey());
    MD5_CTX context = { 0 };
    MD5Init(&context);
    MD5Update(&context, result, strlen(result));
    unsigned char dest[16] = { 0 };
    MD5Final(dest, &context);

    int i = 0;
    char szMd5[33] = { 0 };
    for (i = 0; i < 16; i++)
     {
          sprintf(szMd5, "%s%02x", szMd5, dest[i]);
     }
     free((void*)aa);
     free((void*)cc);
     free((void*)dd);
     free((void*)result);
     return (*env)->NewStringUTF(env, szMd5);
}