//
// Created by Fear1ess on 2021/4/2.
//

#include <jni.h>
#include "cJSON.h"
#include "utils.h"
#include "openssl/sha.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "wd_result.h"
#include "wd_syscall.h"
#include "syscall.h"
#include "fcntl.h"
#include "errno.h"

IMPORTWDSYSCALL

//字节流转换为十六进制字符串
void bytes2Hex(const unsigned char *source, char *dest, int sourceLen, int mac_format) {
    short i;
    unsigned char highByte, lowByte;
    int m = (mac_format) ? 3 : 2;
    for (i = 0; i < sourceLen; i++)
    {
        highByte = source[i] >> 4;
        lowByte = source[i] & 0x0f;

        highByte += 0x30;

        if (highByte > 0x39)
            dest[i * m] = highByte + 0x07;
        else
            dest[i * m] = highByte;

        lowByte += 0x30;
        if (lowByte > 0x39)
            dest[i * m + 1] = lowByte + 0x07;
        else
            dest[i * m + 1] = lowByte;

        //add ':'
        if(mac_format) dest[i * m + 2] = ':';
    }

    //remove last ':'
    if(mac_format) dest[sourceLen * 3 - 1] = 0;
    return;
}

//十六进制字符串转换为字节流
void hex2Bytes(const char* source, unsigned char* dest, int sourceLen)
{
    short i;
    unsigned char highByte, lowByte;

    for (i = 0; i < sourceLen; i += 2)
    {
        highByte = toupper(source[i]);
        lowByte = toupper(source[i + 1]);

        if (highByte > 0x39)
            highByte -= 0x37;
        else
            highByte -= 0x30;

        if (lowByte > 0x39)
            lowByte -= 0x37;
        else
            lowByte -= 0x30;

        dest[i / 2] = (highByte << 4) | lowByte;
    }
    return;
}

void addJniStringToJson(JNIEnv *env, cJSON *json, const char *key, jobject jstr) {
    if(jstr == NULL) {
        cJSON_AddStringToObject(json, key, "");
    }else{
        jboolean bl = 0;
        const char* value= (*env)->GetStringUTFChars(env, jstr, &bl);
        cJSON_AddStringToObject(json, key, value);
        (*env)->ReleaseStringUTFChars(env, jstr, value);
    }
}

void getJniStringSha256(JNIEnv* env, jobject jstr, char* sha256) {
    jboolean bl = 0;
    const char* data = (*env)->GetStringUTFChars(env, jstr, &bl);
    uint8_t output[32];
    SHA256((uint8_t*)data, strlen(data), output);
    (*env)->ReleaseStringUTFChars(env, jstr, data);
    bytes2Hex(output, sha256, 32, 0);
    sha256[64] = 0;
}

int read_cmd(const char *cmd, const char *mode, char *r_buf, size_t r_len) {
    FILE* fp =  popen(cmd, mode);
    int res;
    if(!fp) return WD_ERROR;
    int read_size = fread(r_buf, 1, r_len, fp);
    if(read_size > 0) delete_enter(r_buf, read_size);
    if(read_size == -1) res = WD_ERROR;
    else res = WD_OK;
    pclose(fp);
    return res;
}


char *wd_util_trim(char *start)
{
    char *end;

    if(NULL == start) return NULL;

    end = start + strlen(start);
    if(start == end) return start;

    while(start < end && isspace((int)(*start))) start++;
    if(start == end) return start;

    while(start < end && isspace((int)(*(end - 1)))) end--;
    *end = '\0';
    return start;
}

void delete_enter(char* buf, int len) {
    int i = 0;
    while(i < len) {
        if (buf[i] == '\n') {
            buf[i] = 0;
            return;
        }
        ++i;
    }
}

int read_file(const char *file_path, const char *mode, char *r_buf, size_t r_len) {
    FILE* fp =  fopen(file_path, mode);
    int res;
    if(!fp) return WD_ERROR;
    int read_size = fread(r_buf, 1, r_len, fp);
    if(read_size > 0) delete_enter(r_buf, read_size);
    if(read_size == -1) res = WD_ERROR;
    else res = WD_OK;
    fclose(fp);
    return res;
}

int is_file_exists(const char *file_path) {
    int fd = WDSYSCALL(SYS_faccessat, AT_FDCWD, file_path, R_OK, 0);
    int err = errno;
    if(fd == -1) return 0;
    WDSYSCALL(SYS_close, fd);
    return 1;
}
