#include "http_client.h"
#include <winsock.h>
#include <sstream>

#include "curl/curl.h"
#include "json/json.h"

#pragma comment(lib, "libcurl.lib")

static const std::string kUrl = "http://test-api.live.offcncloud.com/api/v1/board";

ZgHttpClient::ZgHttpClient()
	:curl_(NULL),
	file_(NULL)
{
	curl_ = curl_easy_init();
}
ZgHttpClient::~ZgHttpClient()
{
	curl_easy_cleanup(curl_);
	curl_ = NULL;
}

size_t ZgHttpClient::Response(void *ptr, size_t size, size_t nmemb)
{
	std::string message((const char*)ptr, (size_t)size * nmemb);

	sResult_ = sResult_ + message;

	return size * nmemb;
}
size_t ZgHttpClient::cbResponse(void *ptr, size_t size, size_t nmemb, void *userdata)
{
	return ((ZgHttpClient *)userdata)->Response(ptr, size, nmemb);
}
static
int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
{
	return 0;
}

bool ZgHttpClient::Post(std::string request, std::string params, std::map<std::string, std::string> headers, std::string &response, std::string context_type)
{
	sError_ = "";

	curl_easy_setopt(curl_, CURLOPT_URL, request.c_str());

	struct curl_slist *headers_list = NULL;
	//headers_list = curl_slist_append(headers_list, "Content-Type:application/json;charset=UTF-8");
	//headers_list = curl_slist_append(headers_list, "Content-Type:application/x-www-form-urlencoded");
	headers_list = curl_slist_append(headers_list, context_type.c_str());

	std::map<std::string, std::string>::iterator itor;
	for (itor = headers.begin(); itor != headers.end(); itor++)
	{
		std::string item = itor->first + ":" + itor->second;
		headers_list = curl_slist_append(headers_list, item.c_str());
	}
	curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers_list);

	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //disable https
	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);

	curl_easy_setopt(curl_, CURLOPT_POST, 1);
	curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, params.c_str());

	//设置接收数据的处理函数
	curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, cbResponse);
	curl_easy_setopt(curl_, CURLOPT_WRITEDATA, this);

	curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 5);

	CURLcode res = curl_easy_perform(curl_);

	curl_slist_free_all(headers_list);

	long nCode = 0;
	res = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &nCode);
	if (nCode != 200)
	{
		response = sResult_;

		sError_ = "";
		return false;
	}

	response = sResult_;

	sError_ = "";
	return true;
}
bool ZgHttpClient::Get(std::string &url, std::list<std::string> &headerlist, std::string &result, std::string &sError)
{
	curl_easy_setopt(curl_, CURLOPT_URL ,url.c_str());
	curl_easy_setopt(curl_, CURLOPT_POST, 0);

	struct curl_slist *headers = NULL;

	if (headerlist.size() > 0)
	{
		std::list<std::string>::iterator itor;
		for (itor = headerlist.begin(); itor != headerlist.end(); itor++)
		{
			headers = curl_slist_append(headers, itor->c_str());
		}

		if (headers != NULL)
		{
			curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
		}
	}

	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //disable https
	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
	curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1);
	curl_easy_setopt(curl_, CURLOPT_READFUNCTION, NULL);

	std::stringstream out;
	curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, cbResponse);
	curl_easy_setopt(curl_, CURLOPT_WRITEDATA, this);
	curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);

	curl_easy_setopt(curl_, CURLOPT_DEBUGFUNCTION, my_trace);

	curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 50); // set transport and time out time  
	curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 50);

	CURLcode res = curl_easy_perform(curl_);

	curl_slist_free_all(headers);

	if (res != CURLE_OK)
	{
		sError = "post request failed\n";
		sError_ = "";
		return false;
	}

	std::string returnValue = out.str();

	long nCode = 0;
	res = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &nCode);
	if (nCode != 200)
	{
		sError = sError_;
		sError_ = "";
		return false;
	}

	result = sResult_;

	sResult_ = "";
	sError_ = "";
	return true;
}

std::string ZgHttpClient::buildResponse(int code, std::string msg)
{
	Json::Value root;
	Json::StreamWriterBuilder builder;
	builder["commentStyle"] = "None";		//固定这么写
	builder["indentation"] = "   ";		//固定这么写

	root["code"] = code;
	root["data"] = msg.c_str();

	return Json::writeString(builder, root);
}

int ZgHttpClient::cbProgressCallback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
	return ((ZgHttpClient *)userdata)->ProgressCallback(dltotal, dlnow, ultotal, ulnow);
}
int ZgHttpClient::ProgressCallback(double dltotal, double dlnow, double ultotal, double ulnow)
{
	return 0;
}
size_t ZgHttpClient::cbDownLoadCallback(void *ptr, size_t size, size_t nmemb, void *userdata)
{
	return ((ZgHttpClient *)userdata)->DownLoadCallback(ptr, size, nmemb);
}
size_t ZgHttpClient::DownLoadCallback(void *ptr, size_t size, size_t nmemb)
{
	size_t nWrite = fwrite(ptr, size, nmemb, file_);

	return nWrite;
}

bool ZgHttpClient::DownLoad(std::string url, std::string filename, std::string &sError)
{
	file_full_path_ = filename;

	if (file_)
	{
		fclose(file_);
		file_ = NULL;
	}

	file_ = fopen(file_full_path_.c_str(), "w");
	if (file_)
	{
		fclose(file_);
		file_ = NULL;
	}

	file_ = fopen(file_full_path_.c_str(), "ab+");

	curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
	curl_easy_setopt(curl_, CURLOPT_POST, 0);

	struct curl_slist *headers = NULL;

	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //disable https
	curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
	curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1);
	curl_easy_setopt(curl_, CURLOPT_READFUNCTION, NULL);

	std::stringstream out;
	curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, cbDownLoadCallback);
	curl_easy_setopt(curl_, CURLOPT_WRITEDATA, this);
	curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);

	curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 5); // set transport and time out time  
	curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 5);

	CURLcode res = curl_easy_perform(curl_);

	curl_slist_free_all(headers);

	if (res != CURLE_OK)
	{
		fclose(file_);
		file_ = NULL;

		sError = "post request failed\n";
		sError_ = "";
		return false;
	}

	fclose(file_);
	file_ = NULL;

	sResult_ = "";
	sError_ = "";

	return true;
}