#include "stdafx.h"
#ifdef OLIVIA_COMPILA
#include "olv_sens_ws.h"
#ifndef OLIVIA_NSENS

#include <curl.h>
#include <json.h>
#include <time.h>
#endif
/**
*	@file olv_sens_ws.cpp
*	Archivo de implementaciones de la utilidad para conexión al Web Service para lectura de los sensores de la herramienta Olivia.
*/
/**
*	Clase para conexión al Web Service para lectura de los sensores de la herramienta Olivia.
*/
Colv_sens_ws::Colv_sens_ws(void)
{
	info=NULL;
	cuerpo[0]=0;
}

Colv_sens_ws::~Colv_sens_ws(void)
{
}
//*************************************************************************************
void Colv_sens_ws::inicia(Info_sens *info_)
{
	info=info_;

	strcpy_s(url,OLV_MAX_URL,info->url );

	sprintf_s(cuerpo,OLV_MAX_CUERPO,"?%s=%s&id=%s&%s=%s&%s=%s&%s=%s&%s=%s",
	    info->camps.fn,info->fn_cont_status,		
		"%s",//deja abierto para meter el id del sensor que toque
		info->camps.startdate,info->fecha_ini,
		info->camps.enddate,info->fecha_fin,
		info->camps.usr,info->usr,
		info->camps.pwd,info->pwd);

}
//*************************************************************************************
/*
Pide el porcentaje de llenado en tanto por cien del contenedor id 
*/
double Colv_sens_ws::dame_porc_cont_i(char *id)
{
	int ndata;
	int ini;
	int *data_vol;	
	double perc;

	//manda pregunta
	if(!get_status_cont_i(id))
		return FALSE;

	//recibe respuesta
	ndata=0;
	data_vol=NULL;
	if(!answer_json(id,&ndata,&data_vol))
		return FALSE;

	perc=0;
	if(ndata>0)
	{	
		if(info->modo_pet==OLV_SENS_PET_UNICO)
			ini=ndata-1;//solo se queda con el valor único último
		else if(info->modo_pet==OLV_SENS_PET_MEDIA)
			ini=0;
		for (int i=ini;i<ndata;i++)
		{
			perc+=data_vol[i]*1./(ndata-ini);
		}
	}
	if(data_vol)
		free(data_vol);
	return perc;
}
//*************************************************************************************
BOOL Colv_sens_ws::get_status_cont_i(char *id)
{
	////////////
	//Monta el cuerpo POST
	char cuerpo_aux[OLV_MAX_CUERPO+OLV_MAX_URL];
	strcpy_s(cuerpo_aux,OLV_MAX_URL,url);
	sprintf_s(&cuerpo_aux[strlen(cuerpo_aux)],OLV_MAX_CUERPO,cuerpo,id);
		
	//envía el Post
	if(!post_curl(cuerpo_aux))
		return FALSE;	

	return TRUE;
}
//*************************************************************************************
BOOL Colv_sens_ws::post_curl(char *body)
{
#ifndef OLIVIA_NSENS

	//envía el Post
	CURL *curl;
	CURLcode res;
	BOOL mal=FALSE;
 
	/* In windows, this will init the winsock stuff */ 
	res=curl_global_init(CURL_GLOBAL_ALL);
	if(res != CURLE_OK) 
	{
		sprintf_s(err_str, "Error al iniciar conexión con servicio web: %s\n",
			curl_easy_strerror(res));
		return FALSE;
	}

	/* get a curl handle */ 
	curl = curl_easy_init();
	if(!curl) 
	{
		sprintf_s(err_str, "Error al iniciar conexión con servicio web: %s\n",
			curl_easy_strerror(res));
		return FALSE;
	}
	
	/* First set the URL that is about to receive our POST. This URL can
	just as well be a https:// URL if that is what should receive the
	data. */ 
	curl_easy_setopt(curl, CURLOPT_URL, body);
	cURL_JSON_data.clear();

	/* Specify which function will parse the answer */
	res=curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Colv_sens_ws::writeJSONURLCallback);

	/* Specify variable to parse data */
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)this);	

	/* Perform the request, res will get the return code */ 
	res = curl_easy_perform(curl);
	/* Check for errors */ 
	if(res != CURLE_OK)
	{
		sprintf_s(err_str, "Error al enviar POST en el servicio web: %s\n",
			curl_easy_strerror(res));
		mal=TRUE;
	}		

	/* always cleanup */ 
	curl_easy_cleanup(curl);
	
	curl_global_cleanup();

	return !mal;
#else
	return FALSE;
#endif
}
//*************************************************************************************
 size_t Colv_sens_ws::writeJSONURLCallback(char* buf, size_t siz, size_t nmemb, void* up)//Callback function to store the URL's data
{ 
#ifndef OLIVIA_NSENS

	if(!up)
		return siz*nmemb;
	Colv_sens_ws *cl=(Colv_sens_ws*)up;
	for (int c = 0; c<(int)(siz*nmemb); c++)
	{
		cl->cURL_JSON_data.push_back(buf[c]);
	}
	return siz*nmemb; 
#endif
	return 0;
}
//*************************************************************************************
BOOL Colv_sens_ws::answer_json(char *id_, int *ndata_, int **data_vol_)
{	
	#ifndef OLIVIA_NSENS
	int ndata,i;
	int *data_vol;
	std::string id;
	std::string err_code;
	Json::Reader jsonReader;
	Json::Value jsonData;
	Json::Value histoData;

	ndata=0;
	data_vol=0;

	if (jsonReader.parse(cURL_JSON_data, jsonData))
	{   		
		//comprueba que sea el id elegido
		id = jsonData[info->camps_json.id].asString();
		if(id.length()==0)
		{
			//mira a ver si ha habido error
			err_code=jsonData[info->camps_json.resp_code].asString();
			if(err_code.length()>0 && err_code.compare(info->camps_json.resp_code_err))
			{
				sprintf_s(err_str, "Error en la petición %s\n",jsonData[info->camps_json.resp_data].asString());
				jsonData.clear();
				return FALSE;
			}
		}
		if(strcmp(id.data(),id_))
		{
			sprintf_s(err_str, "Error, no se ha recibido el id del contenedor solicitado %s %s\n",id,id_);
			jsonData.clear();
			return FALSE;
		}
		//coge la info histórica de carga
		histoData = jsonData[info->camps_json.histo];
		ndata = (int) histoData.size();
		//crea el array para almacenar los valores de carga
		data_vol=(int*)malloc(ndata*sizeof(int));
		if(!data_vol)
		{
			sprintf_s(err_str, "Error, sin memoria al leer info JSON\n");
			jsonData.clear();
			return FALSE;
		}
		i=0;
		for (Json::ValueConstIterator it = histoData.begin(); it != histoData.end(); ++it)
		{
			const Json::Value data = *it;
			data_vol[i]=data[info->camps_json.porc].asInt();
			i++;
		}
		if(i!=ndata)
			return FALSE;
	}
	else
	{
		sprintf_s(err_str, "Error al leer info JSON: %s\n",
			jsonReader.getFormattedErrorMessages());
		return FALSE;
	}


	jsonData.clear();

	*data_vol_=data_vol;
	*ndata_=ndata;
#endif
	return TRUE;
}
#endif

