 /***************************************************************
  * @author : Randrianarivelo Tiana
  * @Date ! 10/06/08
  * @version : 0.1
  * @dependencies : sensorinfos,sosrequest
  * SensorChart ..
  * Function lists :
  */

sensorchart = {
	/** Public Attributes **/
	id : "",
	system : "",
	components : [],
	charts : [],
	url : "",
	sampling_time : {},
	
	/** Private Attributes **/
	yinverse : "false",
	months : ["Jan","Fev","Mar","Avr","Mai","Juin","Juil","Aout","Sep","Oct","Nov","Dec"],
	axisDates : {},
	messages : {},
	Yoptions : {},
	
	/** Public Functions **/
	
	/** initializeSensorChart
	 * Initialize the High level Chart for sensor data display management
	 */
	initializeSensorChart : function(){
		this.components  = [];
		this.setUpMessages();
	},
	
	/** setUpMessages
	 * Messages vars
	 */
	setUpMessages : function(){
		this.messages.swe_raw_data = "Donn\u00E9es brutes ";
		this.messages.swe_valid_data = "Donn\u00E9es valid\u00E9es ";
		this.messages.swe_merged_data = "Donn\u00E9es fusionn\u00E9es";
		
	},
	
	/** searchComponent
	 * Return indice of Object Component for a given sensor id
	 * @param sensorid : Id of the sensor
	 * @return j :  indice in the components table
	 */
	searchComponent : function(sensorid){
		var i =0;
		var j =-1;
		while( i < this.components.length){
			if(sensorid==this.components[i].sensorid ){
				var j= i;
				i=this.components.length;
			}
			i++;
		}
		return j;
	},
	/** isYInversed
	 * 
	 * @param sensor.phenomenon :
	 * @return -1 : yinverse else 1
	 */
	isYInversed : function(phenomenon){
		if (phenomenon.indexOf("depth") != -1 ) return -1;
		return 1;
	},
	
	/** addComponent
	 * Add new Component to the Sensor Chart management
	 * @param component : Object Component 
	 */
	addComponent : function(component){
		var i = this.components.length;
		this.components[i]=component;
		this.components[i].id=i;
		var yinverse = this.isYInversed(this.components[i].phenomenon);
		var axisDates = this.processData(component.model,yinverse);
		this.components[i].axisDates=axisDates;	

	},
	
	/** removeComponent
	 * Remove a Component in the Sensor Chart management
	 * @param component : Object Component 
	 */
	removeComponent : function(component){
		this.components[component.id]=null;
		
	},
	
	/** showComponent
	 * Show the given component chart
	 * @param sensorid : Id of the component to show
	 */
	showComponent : function(sensorid){
		this.hideComponent(sensorid);
		var id = this.searchComponent(sensorid);
		dojo.byId("swe_chart_nodata").style.display="none";
		dojo.byId("swe_chart_"+(id+1)).style.display="block";
		dojo.byId("swe_chart_g_"+(id+1)).style.display="block";
		
		if(this.components[id].model.string == ""  &&  this.components[id].model.valid == "" ){
			dojo.byId("swe_chart_nodata").style.display="block";
		}
		else{
			this.createTimeChart(id,this.components[id].axisDates,"swe_chart_g_"+(id+1));
		}
	},
	
	hideComponent : function(sensorid){
		var id = this.searchComponent(sensorid);
		var type=id+1;
		document.getElementById("swe_chart_legend_yaxis_"+type).style.display="none";
		document.getElementById("swe_chart_legend_control_"+type).style.display="none";		
		document.getElementById("swe_chart_g_"+type).style.display="none";
	},
	
	updateComponent : function(component){
		var id = this.searchComponent(component.sensorid);
		var yinverse = this.isYInversed(this.components[id].phenomenon);
		var axisDates = this.processData(component.model,yinverse);
		
		this.components[id].axisDates=axisDates;
		this.showComponent(component.sensorid);
	},
	
	
	isValidObs : function(obs){
		return !(obs==""|| ((obs.split(',')[1])=="---") || (obs.match("T") == null) );
	},
	
	inverseY : function(bool){
		this.yinverse=bool;
	},
	parseStringToDate : function(str){
		var temp = str.split("T");
		var date = temp[0];
		var time = temp[1].split(",");
		time=time[0];
		var objDate = {};
		objDate.year =date.split("-")[0]; objDate.month = date.split("-")[1] -1;objDate.day = date.split("-")[2]; 
		objDate.hour =time.split(":")[0]; objDate.minute = time.split(":")[1]; objDate.second = time.split(":")[2]; 
		return new Date(objDate.year, objDate.month, objDate.day, objDate.hour, objDate.minute, objDate.second);
	},
	
	/** return 0 : equal, 1 : date1>date2 */
	compareDate : function(date1,date2){
		return date1.getTime()-date2.getTime();
	
	},
	validateSamplingTime : function(){
		if (this.compareDate(this.parseStringToDate(this.sampling_time.begin),this.parseStringToDate(this.sampling_time.end))==1){
			var temp = this.sampling_time.begin;
			this.sampling_time.end=this.sampling_time.begin;
			this.sampling_time.begin=temp;
		}	
	},
	getAxisValues  : function(getResultsObj, axisDateTab, isValidSensor,yinverse){
		var values = [];
		var cpt = 0;
		var sum = 0;
		var  n=0;
		var p = 0;
		
		var data = [];
		var datacpt = 0;
		/* Set missing value before first one */
	
		while(this.compareDate(axisDateTab[p],getResultsObj.dates[0]) >0 ){
			values[p]=0;
			p++;
		}

		for(var j = p ; j<axisDateTab.length-1; j++){ // Char points count	
			sum=0;
			n=0;
			while( cpt<getResultsObj.dates.length && this.compareDate(axisDateTab[j+1],getResultsObj.dates[cpt]) > -1 ){
				sum+=parseFloat(getResultsObj.values[cpt]);
				cpt++;
				n++;
			}
			if (sum==0 ){
				values[j]=0;
			}
			else { 
				values[j]= yinverse*(sum/n);		
			}
		}

		return values;
	},
	mergeRawAndValidValues: function(raw_values,valid_values){
		merged={};
		data=[];
		raw=[];
		valid=[];
		rawcpt=0;
		validcpt=0;
		datacpt=0;
		var temp = 0;
		
		var length= 0;
		if (raw_values.length>valid_values.length){
			length = raw_values.length;
			}
		else{
			length = valid_values.length;		
		}
		for(var i=0;i<length;i++){
			if(raw_values[i]!=0 &&   raw_values.length>i ){
				temp=raw_values[i];
				raw[rawcpt] = {};
				raw[rawcpt].x=i;
				raw[rawcpt].y=temp;
				rawcpt++;
			}
			if(valid_values[i]!=0 &&   valid_values.length>i){				
				temp=valid_values[i];
				valid[validcpt] = {};
				valid[validcpt].x=i;
				valid[validcpt].y=temp;
				validcpt++;
			}
			if(temp!=null && temp!=0 && temp!="undefined"){
				data[datacpt] = {};
				data[datacpt].x=i;
				data[datacpt].y=temp;
				datacpt++	;
				temp=null;
			}
		}
		merged.data=data;
		merged.valid=valid;
		merged.raw=raw;
		console.debug("merged : "+merged.data);
		return merged;
	},
	
	
	calculFctLineaire :  function(ptA,ptB,x){
		var a; //coeff directeur
		var b;
		a = (ptA.y-ptB.y)/(ptB.x-ptA.x);
		b = ptA.y - (ptA.x * a);
		//var c = ptB.y - (ptB.x * a);
		/*if ( b != c){
			alert("c la merde");
			return 0;
		}*/
		return (a*x+b);
	},
	
	/**
	 * Create Chart Data 
	 * @param sampling_time : Begin and End Time period
	 * @param model : response from getResult : "time;value@@"
	 * @return : { time , values }
	 */
	createData : function(sampling_time,model){
		var obj = this.parseModel(model);
	
	},
	
	/**
	 * Parse the get Result 
	 * @param model : response from getResult : "time;value@@"
	 * @return : { dates , values }
	 */
	parseModel : function(model){
		var list=model.replace(/[\n\f\r\t\s]/g,'');
		var tab = list.split("@@").sort();
		var obj  = {};
		obj.dates = [];
		obj.values = [];
		var j=0;
		var split = [];
		
		for (var i=0;i<tab.length;i++){
			if(this.isValidObs(tab[i])){
				var split = tab[i].split(',');	
				obj.dates[j]=this.parseStringToDate(split[0]);
				obj.values[j]=split[1];
				j++;
			}
		}
		return obj;
	},
	/**
	 * Create Time Axis 
	 * @return : { dates , labels }
	 */
	createAxisDates : function(begin,end,period){
		console.debug(begin +" et " +end);
		var obj = {};
		obj.dates = [];
		obj.labels =[];
		if(typeof(begin)=="string"){
			var beginDate = 	this.parseStringToDate(begin);
			var endDate = this.parseStringToDate(end);
		}else{
			var beginDate = begin;
			var endDate = end;
		}
		var cpt = 0;
		var lcpt = 0;
		var temp ;
		if(this.compareDate(beginDate,endDate)>-1){
			temp=new Date(beginDate.getFullYear() ,beginDate.getMonth(), beginDate.getDate(),0,0,0);
			beginDate=new Date(endDate.getFullYear() ,endDate.getMonth(), endDate.getDate(),0,0,0);;
			endDate=new Date(temp.getFullYear() ,temp.getMonth(), temp.getDate(),0,0,0);;
		}
		
		var tmpDate = beginDate;
		var year = "";
		endDate.setDate(endDate.getDate()+1);
		//tmpDate=new Date(tmpDate.getFullYear() ,tmpDate.getMonth(),01);
		
		if(period=="P1D"){
			while((tmpDate.getDate() != endDate.getDate()) || (tmpDate.getYear() != endDate.getYear()) || (tmpDate.getMonth() != endDate.getMonth()) ){
				
				obj.dates[cpt] = new Date(tmpDate.getFullYear() ,tmpDate.getMonth(), tmpDate.getDate(),0,0,0);
				tmpDate.setDate(tmpDate.getDate()+1);
				lcpt=cpt;
					obj.labels[lcpt] ={};
					year=""+obj.dates[cpt].getFullYear();
					obj.labels[lcpt].text =obj.dates[cpt].getDate() +" "+this.months[(obj.dates[cpt].getMonth())]+" "+year.substring(2,4);
					obj.labels[lcpt].value = cpt;
					lcpt++;
				cpt++;
			}
		}
		var rcpt=cpt+(10-(cpt%10));
		tmpDate.setDate(tmpDate.getDate()+rcpt);
		
		obj.labels[lcpt] ={};
		obj.labels[lcpt].text =tmpDate.getDate() +" "+this.months[(tmpDate.getMonth()-1)]+" "+tmpDate.getFullYear();
		obj.labels[lcpt].value = rcpt;
		
		return obj;
	},
	custLog : function(x,base) {
		// Created 1997 by Brian Risk.  http://brianrisk.com
		return (Math.log(x))/(Math.log(base));
	},
	
	processData : function(model,yinverse){
		console.debug("process data");
		var period = "P1D";
		//Recuperation des resultats de la requete
		var getResults = {};
		var axisDates = {};
		//Creation de l'axe Temporel
		
		axisDates=this.createAxisDates(this.sampling_time.begin,this.sampling_time.end,period); //.dates[Dates,Dates,...].sort(); 
		//Creation des values de l'axe temporel
		axisDates.values = [];
		if (model.string!=""){
			//Process Raw Data -------------------------------------------------------
			getResults.string=model.string;
			getResults.obj={};
			getResults.obj=this.parseModel(getResults.string);   //.values([string,string,...])valeur respectives des dates
			axisDates.values = this.getAxisValues(getResults.obj, axisDates.dates, 0,yinverse); 
		}
		
		//Process Valid Data -------------------------------------------------------
		axisDates.valid =[];
		if (model.valid!=""){
			getResults.valid=model.valid;
			getResults.obj_valid={};
			getResults.obj_valid=this.parseModel(getResults.valid);   //.values([string,string,...])valeur respectives des dates
			axisDates.valid = this.getAxisValues(getResults.obj_valid, axisDates.dates, 2,yinverse);
		}
		
		// Merge raw and valid
		axisDates.merged={};
		axisDates.merged= this.mergeRawAndValidValues(axisDates.values,axisDates.valid);
		return axisDates;
	},
	nameTonameid : function(name){
		if (name.indexOf("raw_data") != -1 ) return 0;
		if (name.indexOf("valid_data") != -1 ) return 1;
		if (name.indexOf("merged_data") != -1 ) return 2;
		
	},
	idOfChartFromName : function(name){
		if (name.indexOf("1") != -1 ) return 0;
		if (name.indexOf("2") != -1 ) return 1;
		if (name.indexOf("3") != -1 ) return 2;
		
	},
	showSeries : function(name){
		var id = this.idOfChartFromName(name);
		var chart = this.charts[id];
		var nameid = this.nameTonameid(name);
		switch (nameid){
			case 0 : chart.updateSeries("raw_data", this.components[id].axisDates.merged.raw);break;
		
			case 1 :chart.updateSeries("valid_data", this.components[id].axisDates.merged.valid);break;
				
			case 2 : chart.updateSeries("merged_data", this.components[id].axisDates.merged.data);break;
		}
		chart.render();
		
	},
	hideSeries : function(name){
		var id = this.idOfChartFromName(name);
		var chart = this.charts[id];
		var nameid = this.nameTonameid(name);
		switch (nameid){
			case 0 : chart.updateSeries("raw_data", []);break;
		
			case 1 :chart.updateSeries("valid_data", []);break;
				
			case 2 : chart.updateSeries("merged_data",[]);break;
		}
		chart.render();
	},
	
	createTimeChart : function(chartid,axisDates,divid){	
		var period = "PID";
		var Yoptions={};
		var type = chartid+1;
		dojo.byId("swe_chart_fieldset").style.height=(270*type)+"px";
		dojo.byId("swe_chart_g_"+type).innerHTML="";
		switch (type){
			case 1:  Yoptions={		vertical: true, 
									fixLower: "minor", 
									fixUpper: "minor",
									fontColor: "black",	//decalage de l'axe Y : 50 100 (si left) ou -50 -100 (si right)
									htmlLabels:false,
									fixed : true,
									validColor: "red",
									rawColor: "green",
									mergedColor: "blue"
	

								};
					   break;
			case 2:  Yoptions={		vertical: true, 
									fixLower: "minor", 
									fixUpper: "minor",
									fontColor:"black",
									htmlLabels : false,
									validColor: "red",
									rawColor: "green",
									mergedColor: "blue",
									fixed : true									//leftBottom:false,
									//right : 0	//decalage de l'axe Y : 50 100 (si left) ou -50 -100 (si right)
								};
					   break;
			case 3:  Yoptions={		vertical: true, 
									fixLower: "minor", 
									fixUpper: "minor",
									fontColor:"black",
									htmlLabels : false,
									includeZero : true,
									validColor: "red",
									rawColor: "green",
									mergedColor: "blue",
									left : 50	//decalage de l'axe Y : 50 100 (si left) ou -50 -100 (si right)
								};
					   break;
		};
		this.Yoptions = Yoptions;
		document.getElementById("swe_chart_g_"+type).style.display="block";
		chart = new dojox.charting.Chart2D(divid,{fill:"transparent",margins :{l: 0, t: 0, r: 0, b: 0}});
							chart.addAxis("x", {	includeZero : true,
											fixLower: "minor",
											fixUpper: "minor",
											labels: axisDates.labels,
											htmlLabels:false,
											natural: false
										}
					);
		chart.addAxis("y", Yoptions);
		chart.addPlot("default", {type: "Lines",lines:false});
		chart.addPlot("grid", {type: "Grid"});
		chart.addSeries("raw_data", [], {stroke: {color: Yoptions.rawColor, width: 2, style:"dash",fill : "transparent"},outline:{color:"transparent" }});
		chart.addSeries("valid_data", [], {stroke: {color: Yoptions.validColor, width: 2, style:"dash",fill : "transparent"},outline:{color:"transparent" }});
				
		chart.addSeries("merged_data", axisDates.merged.data, {stroke: {color: Yoptions.mergedColor, width: 2, style:"solid",fill : "transparent"},outline:{color:"transparent" }});
		
		chart.render();
		this.charts[chartid]=chart;
		 if(period=="P1D"){
			var tmpB=axisDates.labels[0].text.split("-");
			var tmpE=axisDates.labels[axisDates.labels.length-1].text.split("-");
			tmpE[2]=parseInt(tmpE[2])+2; //car le dernier jour de la requete n'est pas pris en compte vu que les donn?es risque d'etre incomplete sur ce jour a caus ede la periode P1D
			for(var k=1;k<tmpB.length;k++){
				if(tmpB[k]<10)
					tmpB[k]="0"+tmpB[k];
					if(tmpE[k]<10)
						tmpE[k]="0"+tmpE[k];
					if(k!=0){
						tmpB[0]+="-"+tmpB[k];
						tmpE[0]+="-"+tmpE[k];
					}
				}
				    	
				chart.beginPosition=tmpB[0]+"T00:00:00.000-06:00";
					   
				chart.endPosition=tmpE[0]+"T00:00:00.000-06:00";
				if(isValidId == null){}
							//searchDataValid(id,chart.beginPosition,chart.endPosition);
		}	
			var id=1;
					//Affiche les informations relatives au graphe
			if(document.getElementById("swe_chart_legend_yaxis_"+type).style.display=="none"){
				var  yaxis_div = document.getElementById("swe_chart_legend_yaxis_"+type);
				yaxis_div.style.display="block";
				yaxis_div.innerHTML=this.getMessages(this.components[chartid].phenomenon)+" ("+this.components[chartid].units+")";
				
				var control_div = document.getElementById("swe_chart_legend_control_"+type);
				control_div.style.display="block";
				control_div.innerHTML=null;
				control_div.style.color=Yoptions.fontColor;
				
				control_div.innerHTML+=' <input  id="raw_checkbox_'+type+'" dojoType="dijit.form.CheckBox" name="raw'+type+'" value="off" type="checkbox"  onClick="swe_showHideSeries(\'raw_data'+type+'\',this);"/>'+
					' <label for="raw'+type+'" ><font color=\'green\'>'+this.messages.swe_raw_data+'</font></label>';
				control_div.innerHTML+=' <input id="valid_checkbox_'+type+'"  dojoType="dijit.form.CheckBox" name="valid'+type+'"  value="off" type="checkbox"  onClick="swe_showHideSeries(\'valid_data'+type+'\',this);"/>'+
					' <label for="valid'+type+'"><font color=\'red\'>'+this.messages.swe_valid_data +'</font></label>';
				control_div.innerHTML+=' <input id="merged_checkbox_'+type+'"  dojoType="dijit.form.CheckBox" name="merged'+type+'" checked="checked" value="on" type="checkbox"  onClick="swe_showHideSeries(\'merged_data'+type+'\',this);"/>'+
					' <label for="merged'+type+'"><font color=\'blue\'>'+this.messages.swe_merged_data +'</font></label>';
			}

	},
	getMessages : function(msg){
		if(msg.indexOf("depth") !=-1 ) return "Profondeur en c\u00F4te";
		if(msg.indexOf("temperature") !=-1 ) return "Temp\u00E9rature ";
	}

}
