var XMLdoc = null;
var rmarkers = null;
var emarkers = null;
var renderstyle = "restrictive";

function mapEvent(event)
{
	var b=map.getExtent();
	if(b.getWidth()<150000 && b.getHeight()<150000)
	{
		b=b.transform(GooglePrj,WGS84);

		var bw=Math.pow(2,Math.floor(Math.log(b.getWidth())/Math.log(2)));
		var bh=Math.pow(2,Math.floor(Math.log(b.getHeight())/Math.log(2)));

		b.left=Math.floor(b.left/bw)*bw;
		b.bottom=Math.floor(b.bottom/bh)*bh;
		b.right=Math.ceil(b.right/bw)*bw;
		b.top=Math.ceil(b.top/bh)*bh;
		
		if(!bounds.containsBounds(b))
		{
			$("status").innerHTML = "Reading restrictions ...";
			$("status").style.backgroundColor="yellow";
			importXML("restrictions.php?bbox="+b.toBBOX());
			bounds=b;
		}
		else if($("status").innerHTML == "Zoom in to load restrictions!")
		{ 
			$("status").innerHTML = "Ready";
			$("status").style.backgroundColor="green";
		}
	}
	else if($("status").innerHTML != "Reading restrictions ...")
	{ 
		$("status").innerHTML = "Zoom in to load restrictions!";
		$("status").style.backgroundColor="orange";
	}
}

function loadError()
{
	$("status").innerHTML = "Error reading restrictions!";
	$("status").style.backgroundColor="red";
	delete bounds;
	bounds = new OpenLayers.Bounds();
}

function changeStyle(a)
{
	renderstyle = a.options[a.selectedIndex].firstChild.nodeValue;
	showRestrictions();
}

function showRestrictions()
{
	if (!XMLdoc.documentElement) {loadError(); return;}
	if (XMLdoc.documentElement.tagName == 'error') {loadError(); return;}

	var nodes=getNodes();
	var ways=getWays();
	var relations=XMLdoc.getElementsByTagName("relation");

	rmarkers.clearMarkers();
	emarkers.clearMarkers();

	for (var i = 0; i < relations.length; i++)
	{
		var error=false;
		var r = null;
		r=get_restriction(relations[i]);
		if(!r) continue;

		if(r.via.length)
		{
			var node= nodes[r.via[0]];
			if(node)
			{
				var point= new OpenLayers.LonLat(node.lon,node.lat).transform(WGS84, GooglePrj);

				if(r.via.length>1) error = r.via.length + " <i>via</a>-nodes";
				if(r.from.length<1) error = (error? error+"<br>":"") + "no <i>from</i>-way";
				if(r.from.length>1) error = (error? error+"<br>":"") + r.from.length + " <i>from</i>-ways";
				if(r.to.length<1) error = (error? error+"<br>":"") + "no <i>to</i>-way";
				if(r.to.length>1) error = (error? error+"<br>":"") + r.to.length + " <i>to</i>-ways";

				var from=null;
				var to=null;

				if(r.via.length==1)
				{
					if(r.from.length==1) from = get_pt(ways, nodes, r.from[0], r.via[0]);
					if(r.to.length==1) to = get_pt(ways, nodes, r.to[0], r.via[0]);
					if(!error && (!from || !to)) error = "no shared end point";
				}

				if(to) if(to.oneway<0) error = (error? error+"<br>":"") + "to against oneway";
				if(from) if(from.oneway>0) error = (error? error+"<br>":"") + "from against oneway";

				if(!valid_art(r.art)) error = (error? error+"<br>":"") + "undefined restriction";

				var fvec;
				var tvec;

				if(!error)
				{
					var fpoint= new OpenLayers.LonLat(from.lon,from.lat).transform(WGS84, GooglePrj);
					var tpoint= new OpenLayers.LonLat(to.lon,to.lat).transform(WGS84, GooglePrj);

					fvec = norm_vect(fpoint.lon-point.lon,fpoint.lat-point.lat);
					tvec = norm_vect(tpoint.lon-point.lon,tpoint.lat-point.lat);
					
					if(!fvec)  error = (error? error+"<br>":"") + "<i>from</i>-way segment with no length"; 
					if(!tvec)  error = (error? error+"<br>":"") + "<i>to</i>-way segment with no length"; 
				}
				
				if(!error)
				{
					var rec = (fvec.lon*tvec.lat)-(tvec.lon*fvec.lat);
					var par = (fvec.lon*tvec.lon)+(tvec.lat*fvec.lat);

					if((r.art=="no_left_turn" || r.art=="only_left_turn") && rec>0) error="not left";
					if((r.art=="no_right_turn" || r.art=="only_right_turn") && rec<0) error="not right";
					if((r.art=="no_straight_on" || r.art=="only_straight_on") && par>0) error="not straight"
					if(r.art=="no_u_turn" && par<0) error="no u-turn";
				}

				var text = "<b>Relation</b> <a href='http://api.openstreetmap.org/api/0.6/relation/"+ r.id + "' target='browse' title='get osm-xml'>"+ r.id + "</a>";
				text += " [<a href='http://www.openstreetmap.org/browse/relation/"+r.id+"' target='browse' title='browse'>B</a>]";
				text += " [<a href='../history/?type=relation&ref="+r.id+"' target='browse' title='history browser'>H</a>]";
				text += " [<a href='http://www.openstreetmap.org/edit?lat="+node.lat+"&lon="+node.lon+"&zoom=18&relation="+r.id+"' target='_blank' title='edit with Potlatch'>P</a>]";
				text += " [<a href='http://localhost:8111/load_and_zoom?left="+(node.lon-0.002)+"&right="+(Number(node.lon)+0.002)+"&top="+(Number(node.lat)+0.001)+"&bottom="+(node.lat-0.001)+"&select=relation"+r.id+"' target='browse' title='edit with JOSM'>J</a>]";

				text += "<br>" + r.art;
				if(from) text += "<br>from: " + (from.name ? from.name:"") + (from.ref ? "("+from.ref+")":"");
				if(to) text += "<br>to: " + (to.name ? to.name:"") + (to.ref ? "("+to.ref+")":"");

				var pic;
				var offset;
				var size=new OpenLayers.Size(16,16);

				if(error)
				{
					pic='error.png';
					text += "<br><font color='#ff0000'>"+error+"</font>";
					offset = new OpenLayers.Pixel(-(size.w/2), -(size.h/2));
				}

				else
				{
					var w=richtung(fvec,tvec,r.art);
					var w1= -10*Math.floor(w/10.0+0.5);
					pic='image.php?sign='+r.art+'&deg='+w1+'&style='+renderstyle;
					w+=135;
					w*=Math.PI/180;
					offset = new OpenLayers.Pixel((Math.sin(w)*0.71-0.5)*size.w, (Math.cos(w)*0.71+0.5)*-size.h);
				}
				text += "<br><i>last edit: <a href='http://www.openstreetmap.org/user/"+r.user+"' target='browse'>"+r.user+"</a></i>"

				var marker = new OpenLayers.Marker(point,new OpenLayers.Icon(pic,size,offset));
				marker.myid=r.id
				marker.mytext=text;
				marker.events.register('mousedown', marker, function(evt){
						var popup=new OpenLayers.Popup.FramedCloud(this.myid, this.lonlat ,new OpenLayers.Size(150,50), this.mytext, null, true);
						popup.autoSize=true;
						map.addPopup(popup);
						OpenLayers.Event.stop(evt);	});

				if(error) emarkers.addMarker(marker);
				else rmarkers.addMarker(marker);
			}
		}
	}
	$("status").innerHTML = "Ready";
	$("status").style.backgroundColor="green";
}

function importXML(name)
{
	if (document.implementation && document.implementation.createDocument)
	{
		XMLdoc = document.implementation.createDocument("", "", null);
		XMLdoc.onload = showRestrictions;
	}
	else if (window.ActiveXObject)
	{
		XMLdoc = new ActiveXObject("Microsoft.XMLDOM");
		XMLdoc.onreadystatechange = function () { if (XMLdoc.readyState == 4) showRestrictions(); };
 	}
	else
	{
		alert('Your browser can\'t handle this script');
		return;
	}
	XMLdoc.load(name);
}

function getNodes()
{
	var array=XMLdoc.getElementsByTagName("node");
	var nodes= new Object();
	
	for (j = 0; j < array.length; j++)
	{
		var node=new Object();
		var id = array[j].getAttribute("id");
		node.lat = array[j].getAttribute("lat");
		node.lon = array[j].getAttribute("lon");
		nodes[id]=node;
	}
	delete array;
	return nodes;
}

function getWays()
{
	var array=XMLdoc.getElementsByTagName("way");
	var ways= new Object();
	
	for (i = 0; i < array.length; i++)
	{
		var way=new Object();
		var id = array[i].getAttribute("id");
		
		pts=array[i].getElementsByTagName("nd");
		
		way.pt=new Array(pts.length);
		for (var j = 0; j < pts.length; j++)
		{
			way.pt[j]=pts[j].getAttribute("ref");
		}
		delete pts;
		
		var tags=array[i].getElementsByTagName("tag");
		for (var j = 0; j < tags.length; j++)
		{
			switch(tags[j].getAttribute("k"))
			{
			case "ref": way.ref=tags[j].getAttribute("v"); break;
			case "name": way.name=tags[j].getAttribute("v"); break;
			case "oneway": way.oneway=tags[j].getAttribute("v");
			}
		}
		delete tags;
		ways[id]=way;
	}
	delete array;
	return ways;
}

function get_restriction(xml)
{
	var typ="";

	var r = new Object;
	r.from=new Array();
	r.to=new Array();;
	r.via=new Array();;
	r.loc=new Array();;
	r.other=0;
	r.id=xml.getAttribute("id");
	r.user=xml.getAttribute("user");

	var tags=xml.getElementsByTagName("tag");
	for (var j = 0; j < tags.length; j++)
	{
		switch(tags[j].getAttribute("k"))
		{
		case "type":
			typ = tags[j].getAttribute("v"); break;
		case "restriction":
			r.art= tags[j].getAttribute("v"); break;
		}
	}
	delete tags;

	if(typ!="restriction") 
	{
		return null;
	}
	
	var members=xml.getElementsByTagName("member");

	for (j = 0; j < members.length; j++)
	{
		switch(members[j].getAttribute("role"))
		{
		case "from":
			if(members[j].getAttribute("type")=="way")
			{
				r.from.push(members[j].getAttribute("ref"));
			}
			break;

		case "to":
			if(members[j].getAttribute("type")=="way")
			{
				r.to.push(members[j].getAttribute("ref"));
			}
			break;

		case "via":
			if(members[j].getAttribute("type")=="node")
			{
				r.via.push(members[j].getAttribute("ref"));
			}
			break;

		case "location_hint":
			if(members[j].getAttribute("type")=="node")
			{
				r.loc.push(members[j].getAttribute("ref"));
			}
			break;

		default:
			r.other++;
			break;
		}
	}
	delete members;
	return r;
}

function get_pt(ways,nodes, w,via)
{
	var way=ways[w];
	var node=null;
	var dir=0;
	
	if(via==way.pt[0])
	{
		node = nodes[way.pt[1]];
		dir=1;
	}

	else if(via==way.pt[way.pt.length-1])
	{
		node = nodes[way.pt[way.pt.length-2]];
		dir=-1;
	}

	if(!node) return null;
	
	var pt= new Object;
	pt.lat=node.lat;
	pt.lon=node.lon;
	pt.name=way.name;
	pt.ref=way.ref;

	switch(way.oneway)
	{
	case "yes":
	case "true":
	case "1":
		pt.oneway=dir;
		break;
	case "-1":
		pt.oneway=-dir;
		break;
	default:
		pt.oneway=0;
	}
	return pt;
}


function norm_vect(a,b)
{
	var c = Math.sqrt(a*a+b*b);
	if(c==0) return null;
	return new OpenLayers.LonLat(a/c,b/c);
}

function valid_art(art)
{
	switch(art)
	{
	case "no_left_turn":
	case "no_right_turn":
	case "no_straight_on":
	case "no_u_turn":
	case "only_left_turn":
	case "only_right_turn":
	case "only_straight_on":
		return true;
	}
	return false;
}

function richtung(a,b,art)
{
	switch(art)
	{
	case "no_left_turn":
	case "only_left_turn":
		x= b.lat-a.lon;
		y=-b.lon-a.lat;
		break;

	case "no_right_turn":
	case "only_right_turn":
		x=-b.lat-a.lon;
		y= b.lon-a.lat;
		break;

	case "no_straight_on":
	case "only_straight_on":
		x=b.lon-a.lon;
		y=b.lat-a.lat;
		break; 
	
	case "no_u_turn":
		x=-b.lon-a.lon;
		y=-b.lat-a.lat;
	}

	var abs = Math.sqrt(x*x+y*y);
	var w;
	
	if(x>0) w = Math.acos(y/abs)/Math.PI*180;
	else w = 360-Math.acos(y/abs)/Math.PI*180;
	return w;
}

