/*
 * comunicator.cpp
 *
 *  Created on: 25.5.2011
 *      Author: petr
 */

#include "comunicator.h"
#include <cstdlib>
#include <cstring>

//definica obecnych promennych
char *responseBuffer = NULL;
size_t m_Size = 0;

//inicializace singleton
Comunicator* Comunicator::instance = new Comunicator;
string Comunicator::cookie = string("");

void* Realloc(void* ptr, size_t size) {
	if(ptr) {
		free(ptr);
		return malloc(size);
	} else
		return malloc(size);
};

// Callback must be declared static, otherwise it won't link...
size_t WriteMemoryCallback(char* ptr, size_t size, size_t nmemb) {
	// Calculate the real size of the incoming buffer
	size_t realsize = size * nmemb;
//cout << ptr;
	// (Re)Allocate memory for the buffer
	responseBuffer = (char*) Realloc(responseBuffer, realsize);

	// Test if Buffer is initialized correctly & copy memory
	if (responseBuffer == NULL) {
		realsize = 0;
	}

	memcpy(responseBuffer, ptr, realsize);
	m_Size += realsize;

	// return the real size of the buffer...
	return realsize;
};

Comunicator *Comunicator::getInstance() {
	//kontorla jeslti je instance vytvorena
	if (!Comunicator::instance) {
		Comunicator::instance = new Comunicator;
	}

	return Comunicator::instance;
}

Comunicator Comunicator::setUrl(string url) {
	host = url;

	return (*this);
}

Json::Value Comunicator::login(string username, string password, int &isOk) {
	Json::Value retVal;
	ParamMap params;
	string status;
	int statusCode;

	//nastaveni hodnot
	params["user[username]"] = username;
	params["user[password]"] = password;

	retVal = sendJsonRequest("user", "login", "signin", status, statusCode, params);

	//vyhodnoceni odpovedi
	if (statusCode != 200) {
		isOk = 0;
	} else {
		isOk = 1;

		//nastaveni cookie
		Comunicator::cookie = retVal["user"]["cookie"].asString();
	}

	return retVal;
}

Json::Value Comunicator::sendJsonRequest(string object, string method, string id, string &status, int &statusCode, ParamMap params) {
	Json::Value retVal;
	curlpp::Easy request;
	//sestaveni url
	string url;

	url = host + "/" + object + "/" + method + "/" + id + ".json";

	//priprava requestu
	request.reset();
	request.setOpt<Options::Url>(url);
	//request.setOpt(new Options::Verbose(true));
	request.setOpt<Options::Cookie>("_mlc=" + cookie);

	std::list<std::string> header;

	//request.setOpt(new Options::Post(true));
	request.setOpt(new curlpp::options::HttpHeader(header));

	//zapsani parametru
	ParamMap::iterator paramPos = params.begin();
	curlpp::Forms formPart;

	while (paramPos != params.end()) {
		formPart.push_back(new FormParts::Content(paramPos->first, paramPos->second));

		paramPos++;
	}

	request.setOpt(new Options::HttpPost(formPart));


	//nastaveni callbacku
	curlpp::types::WriteFunctionFunctor functor(WriteMemoryCallback);
	curlpp::options::WriteFunction *test = new curlpp::options::WriteFunction(functor);
	request.setOpt(test);

	request.perform();

	//naparsovani a vraci JSON
	decoder.parse(responseBuffer, retVal, false);
	status = retVal.get("status", "UNKNOWN").asString();
	statusCode = retVal.get("statusCode", 500).asInt();

	return retVal["data"];
}

Comunicator::Comunicator() {

}

void writeStatus(string status, int statusCode) {
	cout << "CHYBA PŘI KOMUNIKACI SE SERVEREM" << endl;
	cout << "Server hlásí : " << status << endl;
	cout << "Chybový kód : " << statusCode << endl << endl;
}
