#include "api.h"
#include "cos_api.h"
#include "cos_sys_config.h"
#include "cos_config.h"
#include "util/auth_tool.h"
#include "Poco/TaskManager.h"

#include <stdlib.h>
#include <sys/stat.h>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include <vector>

using namespace qcloud_cos;

CosConfig g_config;

void result2ufileError(ufile_error & retError, qcloud_cos::CosResult tRet)
{
	retError.errorCode = tRet.GetErrorCode().c_str();
	retError.errorMessage = tRet.GetErrorMsg().c_str();
	retError.httpStatus = tRet.GetHttpStatus();
	retError.resourceAddr = tRet.GetResourceAddr().c_str();
	retError.cosRequestId = tRet.GetXCosRequestId().c_str();
	retError.cosTraceId = tRet.GetXCosTraceId().c_str();
	retError.bIsSuccess = tRet.IsSucc();
}

ufile_error ufile_load_config_from_json(const char * json_buf, ufile_config * cfg)
{
	ufile_error retError;
	if (nullptr == cfg)
	{
		retError.bIsSuccess = false;
		return retError;
	}
	Poco::JSON::Parser parser;
	Poco::Dynamic::Var result;
	try {
		result = parser.parse(json_buf);
	}
	catch (Poco::JSON::JSONException& jsonErr) {
		retError.errorMessage = jsonErr.message().c_str();
		retError.bIsSuccess = false;
		return retError;
	}
	if (result.type() != typeid(Poco::JSON::Object::Ptr)) {
		retError.errorMessage = "failed to parse config file";
		retError.bIsSuccess = false;
		return retError;
	}
	Poco::JSON::Object::Ptr object = result.extract<Poco::JSON::Object::Ptr>();

	uint64_t appid = 0;
	std::string strPublicKey = "";
	std::string strPrivateKey = "";
	std::string strRegion = "";
	CosConfig::JsonObjectGetIntegerValue(object, "AppID", &appid);
	CosConfig::JsonObjectGetStringValue(object, "AccessKey", &strPublicKey);
	CosConfig::JsonObjectGetStringValue(object, "SecretId", &strPublicKey);
	CosConfig::JsonObjectGetStringValue(object, "SecretKey", &strPrivateKey);
	CosConfig::JsonObjectGetStringValue(object, "Region", &strRegion);
	cfg->appid = appid;
	cfg->public_key = strPublicKey.c_str();
	cfg->private_key = strPrivateKey.c_str();
	cfg->region = strRegion.c_str();
	retError.bIsSuccess = true;
	return retError;
}

void ufile_free_config(ufile_config cfg)
{
	//此函数无调用，暂且不实现
}

ufile_error ufile_sdk_initialize(const ufile_config cfg, int open_verbose)
{
	UNUSED_PARAM(open_verbose);
	ufile_error retError;
	CosConfig config(cfg.appid, cfg.public_key, cfg.private_key, cfg.region);
	g_config = config;
	retError.bIsSuccess = true;
	return retError;
}

void ufile_sdk_cleanup()
{
}

ufile_error ufile_head(const char * bucket_name, const char * key, ufile_file_info * info)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

void ufile_free_file_info(ufile_file_info info)
{
	//此函数无调用，暂且不实现
}

ufile_error ufile_put_buf(const char * bucket_name, const char * key, const char * mime_type, char * buffer, size_t buf_len)
{
	ufile_error retError;

	return ufile_error();
}

ufile_error ufile_put_file(const char * bucket_name, const char * key, const char * mime_type, FILE * file)
{
	ufile_error retError;

	return ufile_error();
}

ufile_error ufile_put_file_by_filepath(const char * bucket_name, const char * key, const char * mime_type, const char * file_path)
{
	UNUSED_PARAM(mime_type);
	ufile_error retError;
	PutObjectByFileReq req(bucket_name, key, file_path);
	PutObjectByFileResp resp;
	CosAPI cosApi(g_config);
	CosResult result = cosApi.PutObject(req, &resp);
	result2ufileError(retError, result);
	return retError;
}

void set_upload_company(int company)
{
}

ufile_error ufile_delete(const char * bucket_name, const char * key)
{
	ufile_error retError;
	DeleteObjectReq req(bucket_name, key);
	DeleteObjectResp resp;
	CosAPI cosApi(g_config);
	CosResult result = cosApi.DeleteObject(req, &resp);
	result2ufileError(retError, result);
	return ufile_error();
}

ufile_error ufile_multiple_upload_init(ufile_mutipart_state * self, const char * bucket_name, const char * key, const char * mime_type)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_multiple_upload_part(ufile_mutipart_state * self, char * buffer, size_t buf_len, int part_number)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_multiple_upload_finish(ufile_mutipart_state * self)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_multiple_upload_abort(ufile_mutipart_state * self)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_download(const char * bucket_name, const char * key, FILE * file, size_t * return_size, const char * path)
{
	ufile_error retError;
	if (nullptr == file)
	{
		retError.errorMessage = "file is nullptr";
		retError.bIsSuccess = false;
		return retError;
	}
	std::ostringstream os;
	GetObjectByStreamReq req(bucket_name, key, os);
	GetObjectByStreamResp resp;
	CosAPI cosApi(g_config);
	CosResult result = cosApi.GetObject(req, &resp);
	if (result.IsSucc())
	{
		const char * tBuf = os.str().c_str();
		fwrite(tBuf, sizeof(tBuf), strlen(tBuf), file);
	}
	result2ufileError(retError, result);
	return retError;
}

ufile_error ufile_download_piece(const char * bucket_name, const char * key, size_t start_position, char * buf, size_t buf_len, size_t * return_size)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_bucket_create(const char * bucket_name, const char * region, const char * bucket_type)
{
	//此函数无调用，暂且不实现
	return ufile_error();
}

ufile_error ufile_bucket_delete(const char * bucket_name)
{
	ufile_error retError;
	DeleteBucketReq req(bucket_name);
	DeleteBucketResp resp;
	CosAPI cosApi(g_config);
	CosResult result = cosApi.DeleteBucket(req, &resp);
	result2ufileError(retError, result);
	return ufile_error();
}

