/*		NOT USED
 function direction(A,B,m){
       	var res="left";
       	var MAX_M=2;
       	var MIN_M=0.5;
       	var right=false;
	       	if(B.x>A.x) {right=true;res="right";}
       		
       		if(Math.abs(m)>MAX_M){
	   			if((m>0 && right) || (m<0 && !right)){
	   				res="up";
	   			}else{
	   				res="down";
	   			}
       		}else {
       			if(m>=MIN_M && m<MAX_M){
					if(right) {
						res+="_up";
					}else{
						res+="_down";
					}
				}else if(m<=-MIN_M && m>-MAX_M){
					if(right) {
						res+="_down";
					}else{
						res+="_up";
					}
				}	
       		}
       		return res;
       }
       
function alignment(direction){
	var res;
	switch(direction){
		case "right":
		res=ALIGN_MID_VERT+ALIGN_RIGHT;
		break;
		
		case "right_up":
		res=ALIGN_TOP+ALIGN_RIGHT;
		break;
		
		case "right_down":
		res=ALIGN_BOTTOM+ALIGN_RIGHT;
		break;
		
		case "left":
		res=ALIGN_MID_VERT+ALIGN_LEFT;
		break;
		
		case "left_up":
		res=ALIGN_TOP+ALIGN_LEFT;
		break;
		
		case "left_down":
		res=ALIGN_BOTTOM+ALIGN_LEFT;
		break;
		
		case "down":
		res=ALIGN_MID_HORIZ+ALIGN_BOTTOM;
		break;
		
		case "up":
		res=ALIGN_MID_HORIZ+ALIGN_TOP;
		break;
	}
	return res;
}
*/

var PEDESTRIAN_ROUTE_SCRIPT="/timetable/pedestrian_route.php";

var ALIGN_LEFT=1;
var ALIGN_MID_HORIZ=2;
var ALIGN_RIGHT=4;
var ALIGN_TOP=16;
var ALIGN_MID_VERT=32;
var ALIGN_BOTTOM=64;


var START_INFO_BOX_CONTENT;
var STOP_INFO_BOPX_CONTENT;


function sgn(n){
	if(n>=0) return 1;
	return -1;
}

function rad2deg(T){
	return (T*360)/(2*Math.PI);
}

function normalize_teta(T){
	var s=sgn(T);
	var i;
	T=Math.abs(T);
	if(T>360){
		i=Math.floor(T/360);
		T-=i*360;
	}
	T=s*T;
	
	if(T<0) T+=360;
	return T;
}



var debug=false;
    	function point(xVal,yVal,desc){
    		var p = { x:xVal, y:yVal, description:desc};
    		return p;
    	}

        function req_route(A,B,result,callback,args){
        	//var coords=new Array();
        	data="X1="+A.x+"&Y1="+A.y+"&X2="+B.x+"&Y2="+B.y;
        	var res=getXMLHttp();
			res.open("GET",PEDESTRIAN_ROUTE_SCRIPT+"?"+data,true);
			res.onreadystatechange=function(){
				if(res.readyState==4){
					if(res.status==200){
						xml=res.responseXML;
						var i=0,j=0,c;
						result.append(A);
						while(c=xml.getElementsByTagName("P"+i)[0]){
							c=c.firstChild.nodeValue;
							c=c.split(";");
							
							if(Number(c[0])==NaN){
								alert(i);
								alert(c[0]);
								return 0;
							}
							
							if(Number(c[1])==NaN){
								alert(i);
								alert(c[1]);
								return 0;
							}
							result.append(Number(c[0]),Number(c[1]));
							i++;
						}
						result.append(B);
						result.duration=xml.getElementsByTagName("duration")[0].firstChild.nodeValue;
						callback.routeCompleted(args);

					}	
				}
			}
			res.send(null);
        }


      
       function distance(A,B){
       		return Math.sqrt(Math.pow((B.x-A.x),2)+Math.pow(B.y-A.y,2));
       }
       
       function inclination(A,B){
       		var den=0.00001;
       		if((B.x-A.x)!=0) den=B.x-A.x;
       		return ((B.y-A.y)/den);
       }
       

        function mk_link(A,B,r_factor,debug){
        	var teta,teta_step,X,Y,X0,Y0,p,O,O_su,r,tmp,B0;
        	var l_spezzata=500;
        	var a,b;
			var cs=new coord_set("geodecimal");
        	var reverse=true;
        	cs.direction="orario";
        	if(r_factor==null) r_factor=1.5;
        	if(debug==null) debug=false;

        	//B.x>A.x
        	if(A.x>B.x) {
        		tmp=A;
        		A=B;
        		B=tmp;
        		reverse=false;
        		cs.direction="antiorario";
        	}
        	d=distance(A,B);
        	r=r_factor*d;
			
			var A0=new point(0,0,"");
			var B0=new point(B.x-A.x,B.y-A.y,"");
        	
        	a=B0.y-A0.y;
        	b=B0.x-A0.x;

        	h=Math.sqrt((4*Math.pow(r,2))-Math.pow(d,2))/2;
        	X0=(d/2);
        	Y0=-h;
      	
        	X=((b/d)*X0)-((a/d)*Y0);//ruoto
        	Y=((a/d)*X0)+((b/d)*Y0);
        	X+=A.x;//traslo
        	Y+=A.y;

        	O=new point(X,Y,"");
        	O0=new point(X0,Y0,"");
        	
        	teta0=Math.asin((B.y-O.y)/r);
        	teta1=Math.asin((A.y-O.y)/r);
        	
        	if(B.x<O.x) teta0=Math.PI-teta0;
        	if(A.x<O.x) teta1=Math.PI-teta1;
        	
			cs.append(B);			
			
			//invariante rispetto a d...mhmm...trovare di meglio
			//teta_step=l_spezzata/r;
			teta_step=0.05;
        	for(teta=teta0;teta<teta1;teta+=teta_step){
        		X=O.x+(r*Math.cos(teta));
        		Y=O.y+(r*Math.sin(teta));
        		p=new point(X,Y,"xy");
        		cs.append(p);
        	}

			cs.append(A);

			if(debug){
				var db=new debug_board();
	        	db.append("d="+d.toString());
	        	db.append("a="+a.toString());
	        	db.append("b="+b.toString());
				db.append("teta0="+teta0);
				db.append("By-Oy="+(B.y-O.y));
				db.append("teta1="+teta1);
				db.append("Ay-Oy="+(A.y-O.y));
				db.append("r="+r);
				db.append("dist_OA="+distance(O,A));
				db.append("dist_OB="+distance(O,B));
			}

			if(reverse) {
				cs.reverse_coords();
			}
			
			var tmp_m;
			var teta;
			var i;
			var l=cs.coords.length;
			
			B=cs.point(-1);
						
			tmp_m=-(1/inclination(O,B));
			teta=rad2deg(Math.atan(tmp_m));
	
			cs.teta00=teta;
			cs.m=tmp_m;
			
			if((cs.direction=="antiorario" && B.y>O.y) || (cs.direction=="orario" && B.y<O.y)) teta+=180;
			
			cs.teta_dir=teta;
			cs.teta=normalize_teta(teta);
			cs.R=r;
			cs.teta_step=teta_step;
			cs.inclination=tmp_m;
			return {O:O,cs:cs};
        }


function coord_set(format){
	this.debug=false;
	this.format=format;
	this.teta=0;
	this.coords=new Array();
	
	this.inclination;
	
	this.reverse_coords=function(){
		var i,tmp;
		this.coords.reverse();
		
		for(i=0;i<this.coords.length;i+=2){
			tmp=this.coords[i];
			this.coords[i]=this.coords[i+1];
			this.coords[i+1]=tmp;
		}
	}
	
	this.clear=function(){
		this.coords=new Array();
	}
	
	this.ciao=function(){
		alert("ciao");
	}
	
	this.append=function(X,Y){
		var last=this.point(-1);
		if(arguments.length==2){
			if((last.x!=X) || (last.y!=Y)){
				this.coords.push(Number(X));
				this.coords.push(Number(Y));
			}
		}else{
			if((last.x!=X.x) || (last.y!=X.y)){
				this.coords.push(Number(X.x));
				this.coords.push(Number(X.y));
			}else{
				//alert("uguale");
			}
		}

	}
	
	this.insert=function (X,Y){
		var first=this.point(0);
		if(arguments.length==2){
			if((first.x!=X) || (first.y!=Y)){
				this.coords.unshift(Number(Y));
				this.coords.unshift(Number(X));
			}
		}else{
			if((first.x!=X.x) || (first.y!=X.y)){
				this.coords.unshift(Number(X.y));
				this.coords.unshift(Number(X.x));
			}
		}
	}
	
	this.point=function(i){
		i=i*2;
		if(i<0){
			var l=this.coords.length;
			var res=new point(this.coords[l+i],this.coords[l+(i+1)]);
		}else{
			var res=new point(this.coords[i],this.coords[i+1]);
		}
		if(res.x===undefined || res.y===undefined) return false;
		return res;
	}
	
	this.set_format=function(format){
		switch(format){
			case "geodecimal":this.coords=this.toGeoDecimal();break;
			case "mercator":this.coords=this.toMercator();break;
			case "smartunit":this.coords=this.toSmartUnit();break;
		}
		this.format=format;
	}
	
	this.toGeoDecimal=function (){
		switch(this.format){
			case "geodecimal":return this.coords;
			case "mercator":return this.convert_coords(CoordUtil.mercator2GeoDecimal);
			case "smartunit":return this.convert_coords(CoordUtil.smartUnit2GeoDecimal);
		}
	}
	
	this.toSmartUnit=function (){
		switch(this.format){
			case "geodecimal":return this.convert_coords(CoordUtil.geoDecimal2SmartUnit);
			case "mercator":return this.convert_coords(CoordUtil.mercator2SmartUnit);
			case "smartunit":return this.coords;
		}
	}
	
	this.toMercator=function (){
		switch(this.format){
			case "geodecimal":return this.convert_coords(CoordUtil.geoDecimal2Mercator);
			case "mercator":return this.coords;				
			case "smartunit":return this.convert_coords(CoordUtil.smartUnit2Mercator);
		}
	}
	
	this.convert_coords=function(function_name){
			var res=new Array();
        	var i,p;
        	for(i=0;i<this.coords.length;i+=2){
        		p=new point(this.coords[i],this.coords[i+1],"");
        		p=function_name(p);
        		res.push(p.x);
        		res.push(p.y)
        	}
        	return res;
        }
}


        
        
		function debug_board(X,Y){
			this.debug_div=document.createElement("div");
			this.debug_div.style.position="absolute";
			this.debug_div.style.borderWidth="1px";
			this.debug_div.style.borderStyle="solid";
			this.debug_div.style.borderColor="red";
			this.debug_div.style.width="200px";
			this.debug_div.style.height="auto";
			this.debug_div.style.backgroundColor="white";
			if(arguments.length==2){
				this.debug_div.style.left=X+"px";
				this.debug_div.style.top=Y+"px";
			}else{
				this.debug_div.style.left="80%";
				this.debug_div.style.top="50px";
			}
			this.debug_div=document.getElementsByTagName("body")[0].appendChild(this.debug_div);
			
			
			this.append=function (str){
				this.debug_div.innerHTML+=str+"<br>";
			}
		}

 
        


function SolutionsSet(){
	this.solutions=new Array();
	this.clear=function(){
		var i;
		for(i=0;i<this.solutions.length;i++) if(this.solutions[i].selected) this.solutions[i].hide();
		this.solutions=new Array();
	}
	this.select=function(index){
		var i;
		for(i=0;i<this.solutions.length;i++) {
			if(this.solutions[i].selected) this.solutions[i].hide();
			this.solutions[i].selected=false;
		}
		
		this.solutions[index].selected=true;
		this.solutions[index].refreshMap();
		//draw
	}
	//function draw(index): hide_all; draw(index)
	this.append=function(){
		var id="SOL_"+this.solutions.length;
		this.solutions.push(new Solution(id));
		return this.solutions.length-1;
	}
	
	this.process_all=function(){
		var i;
		for(i=0;i<this.solutions.length;i++) {this.solutions[i].process();}
	}
}

function close_info_box(which){
	var i=0;
	l=SolSET.solutions.length;
	while(!SolSET.solutions[i].selected && i<l) i++;
	if(i<l)	SolSET.solutions[i].close_info_box(which);
}

function zoom_start_stop(which){
	var i=0;
	l=SolSET.solutions.length;
	while(!SolSET.solutions[i].selected && i<l) i++;
	if(i<l){
		switch(which){
			case "start":
			SolSET.solutions[i].start_part.zoom();
			break;
			
			case "stop":
			SolSET.solutions[i].stop_part.zoom();
			break;
		}
	}
}

function Solution(id){
	this.parts=new Array();
	this.readyToDraw=false;
	this.start_part=new Part("P");
	this.stop_part=new Part("P");
	this.id=id;
	this.selected=false;
	this.duration;
	this.start_location;
	this.stop_location;
	this.start_time;
	this.stop_time;
	this.start_imagemarker="/timetable/img/play.png";
	this.stop_imagemarker="/timetable/img/stop.png";
	this.change_infobox_content;
	
	this.fares=new Fares();
	
	this.start_infobox_content=function(){
		var res;
		res="<div class=\"map_info_box\">\n"+
			"<span class=\"map_info_box_close\"><a href=\"javascript:void(0);\" onclick=\"javascript:zoom_start_stop('start');\">\n"+
			"<img src=\"/timetable/img/zoom.jpg\" width=\"15\"></a>"+
			"<a href=\"javascript:void(0);\" onclick=\"javascript:close_info_box('start');\">\n"+
			"<img src=\"/img/close.gif\" width=\"15\"></a>"+
			"</span>"+
			"<div class=\"map_info_box_text\">"+
			this.start_part.start_location+"<br>"+
			this.start_part.start_address
			"</div>\n"+
			"</div>";
		
		return res;
	}
	
	this.stop_infobox_content=function(){
		var res;
		res="<div class=\"map_info_box\">\n"+
			"<span class=\"map_info_box_close\"><a href=\"javascript:void(0);\" onclick=\"javascript:zoom_start_stop('stop');\">\n"+
			"<img src=\"/timetable/img/zoom.jpg\" width=\"15\"></a>"+
			"<a href=\"javascript:void(0);\" onclick=\"javascript:close_info_box('stop');\">\n"+
			"<img src=\"/img/close.gif\" width=\"15\"></a>"+
			"</span>"+
			"<div class=\"map_info_box_text\">"+
			this.stop_part.stop_location+"<br>"+
			this.stop_part.stop_address+
			"</div>\n"+
			"</div>";
		
		return res;
	}
	
	this.close_info_box=function(which){
		var id;
		switch(which){
			case "start":
				this.start_part.hide_start_info_box();				
				break;
			
			case "stop":
				this.stop_part.hide_stop_info_box();				
				break;

		}
	}
	
	
	this.append=function(type){
		this.parts.push(new Part(type));
		return this.parts.length-1;
	}
	
	this.fill_startstop_parts=function(){
		this.start_part.stop_location=this.parts[0].start_location;
		var P=this.parts[0].cs.point(0);
		this.start_part.cs.append(this.parts[0].cs.point(0));
		
		this.stop_part.start_location=this.parts[this.parts.length-1].stop_location;
		this.stop_part.cs.insert(this.parts[this.parts.length-1].cs.point(-1));
	}
	
	this.process_startstop=function(){
		if(this.start_part.cs.coords.length>2){
			A=this.start_part.cs.point(0);
			B=this.start_part.cs.point(1);
			this.start_part.cs.clear();
			req_route(A,B,this.start_part.cs,this,"start");
		}else{
			this.routeCompleted("start");
		}
		
		this.start_part.id=this.id+"_start";
		
		if(this.stop_part.cs.coords.length>2){
			A=this.stop_part.cs.point(0);
			B=this.stop_part.cs.point(1);
			this.stop_part.cs.clear();
			req_route(A,B,this.stop_part.cs,this,"stop");
		}else{
			this.routeCompleted("stop");
		}
		this.stop_part.id=this.id+"_stop";
	}
	
	this.process=function(){
		var i;
		for(i=0;i<this.parts.length;i++) {
			
			var A,B;
			
			//this.parts[i].process();
			switch(this.parts[i].type){
			case "B"://BUS =>link
				//alert("Part "+i+" Bus");
				this.parts[i].cs.set_format("geodecimal");
				A=new point(this.parts[i].cs.coords[0],this.parts[i].cs.coords[1],"");
				B=new point(this.parts[i].cs.coords[2],this.parts[i].cs.coords[3],"");
				this.parts[i].cs=mk_link(A,B).cs;
				this.parts[i].cs_Mercator=this.parts[i].cs.toMercator();
				this.parts[i].cs.set_format("smartunit");
				this.parts[i].readyToDraw=true;
				//alert("Part "+i+" Bus -> COMPLETED");
				break;

			case "T"://BUS =>link
				this.parts[i].cs.set_format("geodecimal");
				A=new point(this.parts[i].cs.coords[0],this.parts[i].cs.coords[1],"");
				B=new point(this.parts[i].cs.coords[2],this.parts[i].cs.coords[3],"");
				this.parts[i].cs=mk_link(A,B).cs;
				this.parts[i].cs_Mercator=this.parts[i].cs.toMercator();
				this.parts[i].cs.set_format("smartunit");
				this.parts[i].readyToDraw=true;
				break;

			case "P"://PEDESTRIAN =>route
				//alert("Part "+i+" Ped");
				if(this.parts[i].cs.coords.length==4){
					A=new point(this.parts[i].cs.coords[0],this.parts[i].cs.coords[1],"");
					B=new point(this.parts[i].cs.coords[2],this.parts[i].cs.coords[3],"");
					this.parts[i].cs.clear();
					req_route(A,B,this.parts[i].cs,this,i);
				}else{
					this.routeCompleted(i);
				}
				//alert("Part "+i+" Ped -> COMPLETED");
				break;
			}
			this.parts[i].id=this.id+"_"+i;
		}
		this.process_startstop();
		
	}
	
	this.routeCompleted=function(i_part){
		var i;
		switch(i_part){
			case "start":
				this.start_part.cs.set_format("smartunit");
				this.start_part.readyToDraw=true;
				//this.start_part.cs.set_format("mercator");
				
				break;
			
			case "stop":
				this.stop_part.cs.set_format("smartunit");
				this.stop_part.readyToDraw=true;
				//this.stop_part.cs.set_format("mercator");
				break;
			
			default:
				this.parts[i_part].cs.set_format("smartunit");
				this.parts[i_part].readyToDraw=true;
				break;
		}

		this.refreshMap();
	}
	
	this.refreshMap=function(){
		var ready=true;
		var i;
		var allcs=new Array();
		for(i=0;i<this.parts.length;i++){
			ready=ready && this.parts[i].readyToDraw;
			allcs=allcs.concat(this.parts[i].cs.coords);
		}
		
		ready=ready && this.start_part.readyToDraw;
		allcs=allcs.concat(this.start_part.cs.coords);
		ready=ready && this.stop_part.readyToDraw;
		allcs=allcs.concat(this.stop_part.cs.coords);
		
		if(this.selected && ready) {
			
			this.draw();
			
			map.setViewToPoints(allcs,false,false);
		}
	}
	
	this.draw=function(){
		var i,startinfo,stopinfo;
		//while(!this.ready){}
		for(i=0;i<this.parts.length;i++) {
			startinfo=stopinfo=false;
//			if(i==0) startinfo=this.start_infobox_content;//START
//			if(i==(this.parts.length-1)) stopinfo=this.stop_infobox_content;//END
			if(debug)alert("i="+i+",startinfo="+startinfo+",stopinfo="+stopinfo);
			this.parts[i].draw(startinfo,stopinfo);
		}
		//start_part  +  stop_part
		this.start_part.draw(this.start_infobox_content(),false);
		this.stop_part.draw(false,this.stop_infobox_content());
	}	
	this.hide=function(){
		var i;
		for(i=0;i<this.parts.length;i++) {
			this.parts[i].hide();
		}
		this.start_part.hide();
		this.stop_part.hide();
	}
}

function Fares(){
	this.urban=new Array();
	this.noturban=new Array();
	
}

function FareSection(){
	this.fromStoppointid=0;
	this.toStoppointid=0;
	this.fromStoppointName="";
	this.toStoppointName="";
	this.farerangecode=0;
	this.farerangeid=0;
	this.fareTypes=new Array();
}

function FareType(){
	this.description="";
	this.price=0;
}

function Part(type){
	this.cs=new coord_set("mercator");
	this.type=type;
	this.start_address="";
	this.stop_address="";
	this.start_location;
	this.stop_location;
	this.start_nodeid;
	this.stop_nodeid;	
	this.start_time;
	this.stop_time;
	this.duration;
	this.linename;
	this.operatorname;
	this.id;
	this.readyToDraw=false;
	this.start_info_prefix_id="START_INFO_BOX_";
	this.stop_info_prefix_id="STOP_INFO_BOX_";
	this.start_img_prefix_id="START_IMG_";
	this.stop_img_prefix_id="STOP_IMG_";
	this.spike_bus_prefix_id="SPIKE_BUS_";
	this.spike_train_prefix_id="SPIKE_TRAIN_";
	
	this.check_cs=function(){
		var i;
		for(i=0;i<this.cs.coords.length;i++) if(isNaN(Number(this.cs.coords[i]))) {alert("bad "+this.id+" index "+i);return false}
		return true;
	}
	
	this.draw=function(start_infoBox,stop_infoBox,start_imageMarker,stop_imageMarker){
		if(debug) alert("draw "+this.type+" ID="+this.id);
		if(!this.check_cs()) alert("bad cs");
		switch(this.type){
			case "B"://BUS =>link
				var layer = map.getLayer('vector');
				layer.showImageMarker(this.cs.point(-1).x,this.cs.point(-1).y,"/timetable/get_spike.php?teta="+this.cs.teta,ALIGN_MID_VERT+ALIGN_MID_HORIZ,0,this.spike_bus_prefix_id+this.id,false);
				layer.showLine("red",3,this.cs.coords,null,this.id);
				break;
			
			case "T"://TRAIN =>link
				var layer = map.getLayer('vector');
				layer.showImageMarker(this.cs.point(-1).x,this.cs.point(-1).y,"/timetable/get_spike.php?teta="+this.cs.teta+"&color=train",ALIGN_MID_VERT+ALIGN_MID_HORIZ,0,this.spike_bus_prefix_id+this.id,false);
				layer.showLine("blue",3,this.cs.coords,null,this.id);
				break;

			case "P"://PEDESTRIAN =>route
				var layer = map.getLayer('vector');
				layer.showLine("rgba(0,100,0,0.7)",3,this.cs.coords,null,this.id);
				break;
		}
		//INFO BOX
		if(start_infoBox) layer.showInfoBox(this.cs.point(0).x, this.cs.point(0).y, start_infoBox, null, null, this.start_info_prefix_id+this.id);
		if(stop_infoBox) layer.showInfoBox(this.cs.point(-1).x,this.cs.point(-1).y, stop_infoBox, null, null, this.stop_info_prefix_id+this.id);
		//-------
		
		//IMG MARKER
		if(start_imageMarker) layer.showImageMarker(this.cs.point(0).x, this.cs.point(0).y, start_imageMarker,ALIGN_MID_VERT+ALIGN_MID_HORIZ,0, this.start_img_prefix_id+this.id);
		if(stop_imageMarker) layer.showImageMarker(this.cs.point(-1).x,this.cs.point(-1).y, stop_imageMarker, ALIGN_MID_VERT+ALIGN_MID_HORIZ, 0, this.stop_img_prefix_id+this.id);
		//------
		
		if(debug) map.setViewToPoints(this.cs.coords,false,false);
		if(debug) alert("drawen");
	}
	
	this.zoom=function(){
		map.setViewToPoints(this.cs.coords,false,false);
	}
	
	this.hide=function(){
		if(debug) alert("hide ID="+this.id);
		var layer = map.getLayer('vector');
		layer.hideElement(this.id);
		layer.hideElement(this.start_info_prefix_id+this.id);
		layer.hideElement(this.stop_info_prefix_id+this.id);
		layer.hideElement(this.start_img_prefix_id+this.id);
		layer.hideElement(this.stop_img_prefix_id+this.id);
		layer.hideElement(this.spike_bus_prefix_id+this.id);
	}
	
	this.hide_start_info_box=function(){
		var layer = map.getLayer('vector');
		layer.hideElement(this.start_info_prefix_id+this.id);
	}
	
	this.hide_stop_info_box=function(){
		var layer = map.getLayer('vector');
		layer.hideElement(this.stop_info_prefix_id+this.id);
	}
}



