#include <stdio.h>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pthread.h>

#include"cJSON.h"

#include "tcfs.h"

char taskid[256] = {0};
char keyJsonA[] = "{\
\"address\":\"0fc37d644350f29a37f7a589056670efbaeb20ca\",\
\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"1eb8770334663d4649e446f7b0948a344fdfe571e74ad2e369e2ae23900dee68\",\
\"cipherparams\":{\"iv\":\"e009ec438c4374b0e55a25e4f563f95b\"},\
\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"134f661825996543fb43d89daa55e5ffb5b706731a66fc5b26ad59503145ce20\"},\
\"mac\":\"4bcd5086eee3c0328690df3e80825804a16c08c52336b47544f8f30e29339de3\"},\"id\":\"fb35d736-5dcb-41d2-baf3-4e72283d35b9\",\"version\":3}";

char keyJsonB[] = "{\
\"address\":\"8c5fa76cf8f27cbc84ab700428d5b2592ba38266\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\
\"ciphertext\":\"91e3990178b014143ec81ace6e827fb71d658e99d602199fdce132fa8e39824b\",\
\"cipherparams\":{\"iv\":\"554a1aa9ef16847dddfe74188c1b3c22\"},\"kdf\":\"scrypt\",\"kdfparams\":{\
\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"7b32ac533f38403c72931c10e57fe23f656767aca70be0d5c2ca57038339634b\"},\
\"mac\":\"f9dccc5faefb81a44fdb26c963c0309cc61df3afe4a63be0659b00b1d0f27ba8\"},\"id\":\"cc730321-d280-41e7-adde-afe6da834367\",\"version\":3}";


static void* threadGetStatusAdd(void*) {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    // 用户A信息
    char addressA[] = "0x0fc37d644350f29a37f7a589056670efbaeb20ca";
    long long ts = 1566740935;

    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressA, appid, ts);
    char sign_null_filehashA[1024] = {0};
    printf("data:%s\n", data_sign_str);
    int sign_ret = UserSign(keyJsonA, "12345678", data_sign_str, sign_null_filehashA, sizeof(sign_null_filehashA));
    if(sign_ret != 0) {
        printf("sign1 error\n");
        return NULL;
    }

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    TCFSUserCertification addr;
    strcpy(addr.address, addressA);
    addr.timestamp = ts;
    strcpy(addr.sign, sign_null_filehashA);

    for(;;) {
        char status[10240] = {0};
        int ret = GetTaskStatus(&app, &addr, taskid, status, sizeof(status));
        if(ret != 0) {
            printf("get task status add error, ret:%d", ret);

            sleep(10);
            continue;
        } else {
            cJSON* json = cJSON_Parse(status);
            cJSON* json_status = cJSON_GetObjectItem(json, "status");
            if((strcmp(json_status->valuestring, "FAILED") == 0) || ((strcmp(json_status->valuestring, "DONE") == 0))) {
                printf("break loop, get task status add:%s\n", json_status->valuestring);

                pthread_exit(0);
                break;
            }

        sleep(10);
        }
    }

    return NULL;
}

static void* threadGetStatusGet(void*) {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    char address[] = "0x8c5fa76cf8f27cbc84ab700428d5b2592ba38266";
        // 12345678

    long long ts = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512] = {0};
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", address, appid, ts);
    char sign[1024] = {0};
    int sign_ret = UserSign(keyJsonB, "12345678", data_sign_str, sign, sizeof(sign));
    if(sign_ret != 0) {
        printf("sign3 error\n");
        return NULL;
    }
    printf("sign dataB:%s, signB:%s\n", data_sign_str, sign);

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    TCFSUserCertification addr;
    strcpy(addr.address, address);
    addr.timestamp = ts;
    strcpy(addr.sign, sign);

    for(;;) {
        char status[10240] = {0};
        int ret = GetTaskStatus(&app, &addr, taskid, status, sizeof(status));
        if(ret != 0) {
            printf("get task status get error, ret:%d", ret);

            sleep(10);
            continue;
        } else {
            cJSON* json = cJSON_Parse(status);
            cJSON* json_status = cJSON_GetObjectItem(json, "status");
            if((strcmp(json_status->valuestring, "FAILED") == 0) || ((strcmp(json_status->valuestring, "DONE") == 0))) {
                printf("break loop get, get task status:%s\n", json_status->valuestring);

                pthread_exit(0);
                break;
            }

        sleep(10);
        }
    }

    return NULL;
}


void usage()  {
	printf("Usage: tcfs_demo command\n");
}

void addfile() {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    // step 1
    // 初始化sdk全局变量
    Init((char*)appid);

    // step 2
    // 上传文件到云存储空间

    // 用户A信息
    char addressA[] = "0x0fc37d644350f29a37f7a589056670efbaeb20ca";
    long long ts = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressA, appid, ts);
    char signA[1024] = {0};
    printf("data:%s\n", data_sign_str);
    int sign_ret = UserSign(keyJsonA, "12345678", data_sign_str, signA, sizeof(signA));
    if(sign_ret != 0) {
        printf("sign1 error\n");
        return;
    }

    TCFSUserCertification addr;
    strcpy(addr.address, addressA);
    addr.timestamp = ts;
    strcpy(addr.sign, signA);

    char srcPath[] = "/tmp/test/";
    char destPath[] = "/tcfs/::::/newest/中文目录/dest/";
    int add_ret = AddFile(&app, &addr, srcPath, destPath, taskid, sizeof(taskid));
    if(add_ret != 0) {
        printf("add file error, ret:%d\n", add_ret);
        return;
    } else {
        printf("add file task success, ret:%d\n", add_ret);
    }

    pthread_t pt_add = 0;
    int thread_ret = pthread_create (&pt_add, NULL, threadGetStatusAdd, NULL);
    if(thread_ret != 0) {
        printf("create thread error\n");
        return;
    }
    pthread_join(pt_add, NULL);

    sleep(10);

    Uninit();
}

void copyfile() {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    Init((char*)appid);

    char addressA[] = "0x0fc37d644350f29a37f7a589056670efbaeb20ca";
    char addressB[] = "0x8c5fa76cf8f27cbc84ab700428d5b2592ba38266";
    long long tsB = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressB, appid, tsB);
    char signB[1024] = {0};
    int sign_ret = UserSign(keyJsonB, "12345678", data_sign_str, signB, sizeof(signB));
    if(sign_ret != 0) {
        printf("sign3 error\n");
        return;
    }
    printf("sign dataB:%s, signB:%s\n", data_sign_str, signB);

    char shareTcfsPath[] = "/newest/test";
    char tcfsSignData[256] = {0};
    snprintf(tcfsSignData, sizeof(tcfsSignData), "%s%s%lld%s", addressA, addressB, tsB, shareTcfsPath);
    char tsfsSign[256] = {0};
    sign_ret = UserSign(keyJsonA, "12345678", tcfsSignData, tsfsSign, sizeof(tsfsSign));
    if(sign_ret != 0) {
        printf("sign4 error\n");
        return;
    }
    printf("sign tcfsSignData:%s, signB:%s\n", tcfsSignData, tsfsSign);

    char tcfsPath[1024] = {0};
    snprintf(tcfsPath, sizeof(tcfsPath), "/tcfs/%s:%s:%lld:%s:%d%s", addressA, addressB, tsB, tsfsSign, strlen(shareTcfsPath), shareTcfsPath);
    printf("tcfsPath:%s\n", tcfsPath);

    char destPathCopy[] = "/tcfs/::::/newest/d/";

    // copyfile
    TCFSUserCertification addrB;
    strcpy(addrB.address, addressB);
    addrB.timestamp = tsB;
    strcpy(addrB.sign, signB);

    int copy_ret = CopyFile(&app, &addrB, tcfsPath, destPathCopy);
    if(copy_ret != 0) {
            printf("copy file error, ret:%d\n", copy_ret);
            return;
    } else {
        printf("copy file success, ret:%d\n", copy_ret);
    }

    sleep(10);

    Uninit();
}

void getfile() {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    Init((char*)appid);

    char addressB[] = "0x8c5fa76cf8f27cbc84ab700428d5b2592ba38266";
    long long tsB = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressB, appid, tsB);
    char signB[1024] = {0};
    int sign_ret = UserSign(keyJsonB, "12345678", data_sign_str, signB, sizeof(signB));
    if(sign_ret != 0) {
        printf("sign3 error\n");
        return;
    }
    printf("sign dataB:%s, signB:%s\n", data_sign_str, signB);

    TCFSUserCertification addrB;
    strcpy(addrB.address, addressB);
    addrB.timestamp = tsB;
    strcpy(addrB.sign, signB);

    char tcfsPathGet[] = "/tcfs/::::/newest/test/";
    char destPathGet[] = "test/";
    int get_ret = GetFile(&app, &addrB, tcfsPathGet, destPathGet, taskid, sizeof(taskid));
    if(get_ret != 0) {
        printf("get file error, ret:%d\n", get_ret);
        return;
    } else {
        printf("get file task success, ret:%d\n", get_ret);
    }

    pthread_t pt_get = 0;
    int thread_ret = pthread_create (&pt_get, NULL, threadGetStatusGet, NULL);
    if(thread_ret != 0) {
        printf("create threadget error\n");
        return;
    }
    pthread_join(pt_get, NULL);

    sleep(10);

    Uninit();
}

void deletefile() {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    Init((char*)appid);

    char addressA[] = "0x0fc37d644350f29a37f7a589056670efbaeb20ca";
    long long ts = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressA, appid, ts);
    char signA[1024] = {0};
    printf("data:%s\n", data_sign_str);
    int sign_ret = UserSign(keyJsonA, "12345678", data_sign_str, signA, sizeof(signA));
    if(sign_ret != 0) {
        printf("sign1 error\n");
        return;
    }

    TCFSUserCertification addr;
    strcpy(addr.address, addressA);
    addr.timestamp = ts;
    strcpy(addr.sign, signA);

    char needDeletePath[] = "/tcfs/::::/newest/test/";
    int delete_ret = DeleteFile(&app, &addr, needDeletePath);
    if(delete_ret != 0) {
        printf("delete file failed, ret:%d\n", delete_ret);
    } else {
        printf("delete file sucess, ret:%d\n", delete_ret);
    }

    sleep(10);

    Uninit();
}

void dir() {
    char appid[] = "17b4cf0dfd7fbce35b917677093b917a040552df30979f2d1cb4ded051046856";
    char appid_sign[] = "ea6438086f372f6ad9b8e341d78dea70";
    long long appid_ts = 1566740935;

    TCFSAppCertification app;
    strcpy(app.appid, appid);
    strcpy(app.sign, appid_sign);
    app.timestamp = appid_ts;

    Init((char*)appid);

    char addressA[] = "0x0fc37d644350f29a37f7a589056670efbaeb20ca";
    long long ts = 1566740935;
    // 签名sign的获取需要按照SDK三种方式进行获取
    // 本demo采用的是本地函数获取签名的方式
    char data_sign_str[512];
    snprintf(data_sign_str, sizeof(data_sign_str), "%s%s%lld", addressA, appid, ts);
    char signA[1024] = {0};
    printf("data:%s\n", data_sign_str);
    int sign_ret = UserSign(keyJsonA, "12345678", data_sign_str, signA, sizeof(signA));
    if(sign_ret != 0) {
        printf("sign1 error\n");
        return;
    }

    TCFSUserCertification addr;
    strcpy(addr.address, addressA);
    addr.timestamp = ts;
    strcpy(addr.sign, signA);

    char path[] = "/tcfs/::::/newest/abc/";
    char node[10 * 1024] = {0};
    int dir_ret = Dir(&app, &addr, path, 0, 1000, node, sizeof(node));
    if(dir_ret != 0) {
        printf("dir file failed, ret:%d\n", dir_ret);
    } else {
        printf("dir file sucess, ret:%d, node:%s\n", dir_ret, node);
    }

    sleep(10);

    Uninit();
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        usage();
        return 0;
    }

    std::string command = argv[1];
    if(command == "addfile") {
        addfile();
    } else if(command == "getfile") {
        getfile();
    } else if(command == "copyfile") {
        copyfile();
    } else if(command == "deletefile") {
        deletefile();
    } else if(command == "dir") {
        dir();
    } else {
        printf("cannot find command\n");
    }
    return 0;
}


