/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include <curl/curl.h>
		#include "http_curl/http_curl.h"
		#include "async/async_call_queue_thread.h"
		#include "platform.h"

		using namespace GS::Threading;
		using namespace GS::HTTP;


namespace GS {
	namespace HTTP {

//------------------------------------------------------------------------------
class	CurlThread : public ASyncCallQueueThread
{
		Curl		*icurl;
		void		*curl;

public:

		void		Execute()
		{
			curl = curl_easy_init();
			if (!curl)
				return;

			ASyncCallQueueThread::Execute();

			curl_easy_cleanup(curl);
			curl = NULL;
		}

static	size_t		WriteData(void *buffer, size_t size, size_t nmemb, void *userp)
		{
			Array <char> *data = (Array <char> *)userp;

			size_t offset = data->GetSize();
			size_t total_size = offset + size * nmemb;
			if	(!data->Reallocate(total_size))
				return 0;

			Memory::Copy(&data->c_ptr()[offset], buffer, size * nmemb);
			return size * nmemb;
		}
		void		Post(int ticket_id, const String &url, const String &post)
		{
			Array <char> response;

			curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str());
			curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData);
			curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

			if	(curl_easy_perform(curl) == 0)
				icurl->event_queue.QueueMemberCall(icurl, &Curl::OnRequestComplete, ticket_id, response);
			else
				icurl->event_queue.QueueMemberCall(icurl, &Curl::OnRequestError, ticket_id);
		}

		CurlThread(Curl *c) : icurl(c), curl(0) {}
};
//------------------------------------------------------------------------------

	} // HTTP
} // GS

//------------------------------------------------------------------------------
int			Curl::GetTicketId()
{	return u_ticket_id++;	}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void		Curl::Update()
{
	event_queue.ExecuteAll();
}
int			Curl::Post(const char *url, const char *post)
{
	int ticket_id = GetTicketId();
	curl_thread->QueueMemberCall(curl_thread, &CurlThread::Post, ticket_id, url, post);
	return ticket_id;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
Curl::Curl() : u_ticket_id(0)
{
	curl_thread = new CurlThread(this);
	curl_thread->Start();
}
Curl::~Curl()
{
	curl_thread->Stop();
	_safe_delete(curl_thread);
}
//------------------------------------------------------------------------------
