//
// Google maps API Clone for Open Street Map
// Version 0.01
//

function LargeMapControl(){
	var controls=new Array(8);
	controls[0]=new Array("west",0,20,"panDirection(-1, 0)");
	controls[1]=new Array("east",40,20,"panDirection(1, 0)");
	controls[2]=new Array("north",20,0,"panDirection(0, -1)");
	controls[3]=new Array("south",20,40,"panDirection(0, 1)");
	controls[4]=new Array("zoom-plus",20,63,"zoomIn()");
	controls[5]=new Array("zoom-minus",20,278,"zoomOut()");
	controls[6]=new Array("zoombar",20,80,"setZoom(26 - Math.round((parseInt(evt.clientY) - parseInt(evt.target.parentNode.parentNode.offsetTop))/11))");
	//controls[6]=new Array("zoombar",20,80,"alert(( parseInt(evt.target.parentNode.parentNode.offsetTop)))");
	controls[7]=new Array("slider",19,100,"nop()");
	this.controlDiv=document.createElement("div");
	for(var i=0; i < controls.length; i++){
		var img=document.createElement("img");
		img.setAttribute("src","images/"+controls[i][0]+".png");
		img.setAttribute("action",controls[i][3]);
		img.style.top=controls[i][2]+"px";
		img.style.left=controls[i][1]+"px";
		img.style.position="absolute";
		this.controlDiv.appendChild(img);	
	}
}

LargeMapControl.prototype.callback=function(obj){
	var zoom=obj.getZoom();
	var slider=this.controlDiv.lastChild;
	slider.style.top=279 - zoom*11;
}

function LatLng(latValue,lngValue){
	this.latValue=latValue;
	this.lngValue=lngValue;

	this.lat=function(){
		return this.latValue;
	}
	this.lng=function(){
		return this.lngValue;
	}
}

//
//  osmMap
//


function Map2(origworld){
	this.el=null;
	this.dx=0;
	this.dy=0;
	this.downX=0;
	this.downY=0;
	this.zoomlevel=1;
	this.floatzoomlevel=1;
	this.wy=256;
	this.wx=256;
	this.moved=false;
	this.LatLng=null;

	this.world=document.createElement("div");
	this.world.style.backgroundColor="#efefef";
	this.world.style.overflow="hidden";
	this.world.style.top=origworld.offsetTop;
	this.world.style.left=origworld.offsetLeft;
	this.world.style.width=origworld.offsetWidth;
	this.world.style.height=origworld.offsetHeight;
	this.world.style.border=origworld.style.border;
	this.world=origworld;
	this.world.style.position="relative";
	this.world.style.overflow="hidden";
	//document.body.appendChild(this.world);
	this.moveable=document.createElement("div");	
	this.world.appendChild(this.moveable);
	this.moveable.style.top=0;
	this.moveable.style.left=0;
	this.moveable.style.position="absolute";

	//strange thing for wheel clientX,clientY
	this.clientX=0;
	this.clientY=0;

	//callback handlers;
	this.callbackHandlers=new Array();

	this.world.attach(this,"mousedown",this.down,false);
	this.world.attach(this,"mousemove",this.move,false);
	this.world.attach(this,"DOMMouseScroll",this.wheel,false);
	window.attach(this,"mouseup",this.up,false);
//	this.world.attach(this,"mouseout",this.up,true);
	window.attach(this,"resize",this.init,false);
	this.init();
}


//onmousedown="down(event)" onmousemove="move(event)" onmouseup="up(event)" 	

	Map2.prototype.alert=function(x){alert(x)};

	Map2.prototype.init=function(){
		/*
		while(this.moveable.firstChild){
			this.moveable.removeChild(this.moveable.firstChild);
		}
		*/
		var left=-parseFloat(this.moveable.style.left);
		var top=-parseFloat(this.moveable.style.top);
		
		var startX=Math.floor(left / this.wx);
		var startY=Math.floor(top / this.wy);
		var endX=startX + Math.ceil(parseFloat(this.world.offsetWidth) / this.wx);
		var endY=startY + Math.ceil(parseFloat(this.world.offsetHeight) / this.wy);

		for(x=startX -1;x < endX +1; x++){
			for(y=startY -1;y < endY +1; y++){
				var anz=Math.pow(2,this.zoomlevel);
				var imgX=x % anz;
				var imgY=y % anz;
				if(imgX < 0) imgX=imgX+anz;
				if(imgY < 0) imgY=imgY+anz;
				var url="http://c.tile.openstreetmap.org/"+this.zoomlevel+"/"+imgX+"/"+imgY+".png";
				//var url="http://b.tah.openstreetmap.org/Tiles/tile/"+this.zoomlevel+"/"+imgX+"/"+imgY+".png";
				var img=document.createElement("img");
				img.setAttribute("src",url);
				img.style.top=y*this.wy;
				img.style.left=x*this.wx;
				img.style.width=this.wx;
				img.style.height=this.wy;
				img.style.position="absolute";
				this.moveable.appendChild(img);		
			}
			//if(x = 0) break;	
		}
		uuu=0;//breakpoint
		for(var i=0; i <  this.callbackHandlers.length;i++){
			this.callbackHandlers[i].callback(this);
		}
	}

	Map2.prototype.addControl=function(control){
		this.world.appendChild(control.controlDiv);	
		control.controlDiv.attach(this,"mousedown",this.eventHandler,false,control);
		if((typeof control.callback)=="function"){
			this.callbackHandlers.push(control);	
		}
	}
	Map2.prototype.eventHandler=function(control,evt){
		//evt.preventDefault();
		var target=evt.target;
		var action=target.getAttribute("action");
		funcName="this."+action;
		eval(funcName);
		evt.stopPropagation();
		return false;
	}

	Map2.prototype.down=function(evt){
		evt.preventDefault();
		this.el=this.moveable;
		this.dx=parseFloat(this.el.style.left) - parseFloat(evt.clientX);
		this.dy=parseFloat(this.el.style.top) - parseFloat(evt.clientY);

		//für nachladen beim moven
		this.downX= parseFloat(evt.clientX);
		this.downY= parseFloat(evt.clientY);
		this.moved=false;
	}

	Map2.prototype.move=function(evt){
		if(this.el!=null){
			this.el.style.top=parseFloat(evt.clientY)+this.dy;
			this.el.style.left=parseFloat(evt.clientX)+this.dx;
			this.moved=true;
			if((Math.abs(parseFloat(evt.clientX) - this.downX) > this.wx) || (Math.abs(parseFloat(evt.clientY) - this.downY) > this.wy)){
				this.downX=parseFloat(evt.clientX);
				this.downY=parseFloat(evt.clientY);
				this.init();
			}
		}
		//makeGPS(evt);
		this.clientX=evt.clientX;
		this.clientY=evt.clientY;
	}

	Map2.prototype.up=function(evt){
		if(this.el!=null){
			if(this.moved==false){
				var oL=parseFloat(this.world.offsetLeft);
				var oT=parseFloat(this.world.offsetTop);
				this.el.style.top=(parseFloat(this.el.style.top) +oT) *2 - evt.clientY - oT;
				this.el.style.left=(parseFloat(this.el.style.left) +oL) *2 - evt.clientX - oL;
				this.zoomlevel++;
			}
			this.LatLng=this.screenToWGS(parseFloat(this.el.style.left)-this.world.offsetWidth /2,parseFloat(this.el.style.top)-this.world.offsetHeight /2);
			this.init();
			this.el=null;
		}
		/*
		document.getElementById("zoom").firstChild.nodeValue="zoom: "+this.floatzoomlevel+" : " +this.zoomlevel;
		document.getElementById("top").firstChild.nodeValue=this.moveable.style.top;
		document.getElementById("left").firstChild.nodeValue=this.moveable.style.left;
		*/
	}

	Map2.prototype.wheel=function(evt){
		if(this.clientX==0){
			alert("not ready");
			return;
		}
		if(this.clientY==0){
			alert("not ready");
			return;
		}
		if(evt.detail > 0){
			var faktor=1.090507732665257659;
			var faktor=1.04427378242741384
			//this.zoomlevel=this.zoomlevel+1;
			this.floatzoomlevel=this.floatzoomlevel+0.0625;
		}else{
			var faktor=0.9170040432046712318;
			var faktor=0.957603280698573647;
			//var faktor=2;
			//this.zoomlevel=this.zoomlevel-1;
			this.floatzoomlevel=this.floatzoomlevel-0.0625;
		}

		var left=parseFloat(this.moveable.style.left);
		var top =parseFloat(this.moveable.style.top);

		var mouseX=-parseFloat(this.clientX)+left;
		var mouseY=-parseFloat(this.clientY)+top;

		this.moveable.style.left=mouseX *faktor +parseFloat(this.clientX);
		this.moveable.style.top= mouseY *faktor +parseFloat(this.clientY);
		document.getElementById("zoom").firstChild.nodeValue="zoom2 :"+this.floatzoomlevel+" : "+this.zoomlevel;
		document.getElementById("top").firstChild.nodeValue=this.moveable.style.top;
		document.getElementById("left").firstChild.nodeValue=this.moveable.style.left;

		allImg=this.moveable.getElementsByTagName("img");
		for(var i=0; i < allImg.length;i++){
			var img=allImg.item(i);
			img.style.left=parseFloat(img.style.left)*faktor;
			img.style.top=parseFloat(img.style.top)*faktor;
			img.style.width=parseFloat(img.style.width)*faktor;
			img.style.height=parseFloat(img.style.height)*faktor;
		}
//		this.LatLng=this.screenToWGS(parseFloat(this.moveable.style.left)-this.world.offsetWidth /2,parseFloat(this.moveable.style.top)-this.world.offsetHeight /2);
		if(Math.abs(this.floatzoomlevel - this.zoomlevel) >= 1){
			this.zoomlevel=Math.floor(this.floatzoomlevel);
			//this.floatzoomlevel=this.zoomlevel;
			thisObject=this;
			setTimeout( function () {thisObject.superzoom();},500);	
		}
//		this.init();
	}

	Map2.prototype.superzoom=function(){
			if(this.zoomlevel < this.floatzoomlevel){
				this.zoomlevel=Math.ceil(this.floatzoomlevel);
			}else{
				this.zoomlevel=Math.floor(this.floatzoomlevel);
			}
			this.setZoom(this.zoomlevel);

	}
	
	Map2.prototype.screenToWGS=function(left,top){
		var anz=Math.pow(2,this.zoomlevel);
		var y=top / 256 / anz;
		var x=left / -256 / anz;

		//GPS (WGS84) Koordinaten berechnen
		var lng=(x - Math.floor(x) -0.5)*360;
		var lat=this.y2lat((y - Math.floor(y) -0.5)*360);
		//alert(lng+":"+lat);
		var a=new GLatLng(lat, lng);
		return a;
	}

	Map2.prototype.setCenter=function(point,zoom){
		this.LatLng=point;
		latVal=point.lat();
		lngVal=point.lng();
		this.floatzoomlevel=zoom;
		this.zoomlevel=zoom;
		var x= parseFloat(this.world.offsetWidth) /2 + (lngVal / -360 +0.5) *Math.pow(2,this.zoomlevel) *this.wx;
		var y= parseFloat(this.world.offsetHeight) /2 + (this.lat2y(latVal) / 360 +0.5) *Math.pow(2,this.zoomlevel) *this.wy;
		this.moveable.style.left=x;
		this.moveable.style.top=y;
		//alert(this.moveable.style.left);
		this.init();
	}

	Map2.prototype.getZoom=function(){
		return this.zoomlevel;
	}
	
	Map2.prototype.zoomIn=function(){
		this.zoomlevel++;
		this.setCenter(this.LatLng, this.zoomlevel);
	}
	Map2.prototype.zoomOut=function(){
		this.zoomlevel--;
		this.setCenter(this.LatLng, this.zoomlevel);
	}
	Map2.prototype.setZoom=function(zoomlevel){
		this.zoomlevel=zoomlevel;
		this.floatzoomlevel=zoomlevel;
		this.setCenter(this.LatLng, this.zoomlevel);
	}

	Map2.prototype.y2lat=function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); }
	Map2.prototype.lat2y=function(a) { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); }










// Rest of Code ist a Copy from
//http://hiveminds.org.hiveminds.co.uk/phpBB/viewtopic6b81.html?t=2930
//
// Ab hier wird nur die Methode "attach" definiert. Am besten einfach ignorieren.
//
//

/***
<member name="$a" type="global static method">
   <summary>Loops through each argument in the supplied argument object and puts it into an array.</summary>
   <param name="a">Argument object to loop through.</param>
   <returns>Array</returns>
</member>
***/
function $a(a) {
   var r = new Array();
   for (var i = 0, l = a.length; i < l; i++) {
      r.push(a[i]);
   }
   return r;
}

/***
<member name="Function.bind" type="method">
   <summary>Calls this function using the context of supplied object o.</summary>
   <param name="o">Context of this function.</param>
   <param name="*">Arguments to pass to this function when called.</param>
   <returns>Function</returns>
</member>
***/
Function.prototype.bind = function(o) {
   var a;
   if (arguments.length > 1) {
      // turn arguments into an array and remove the argument 'o'
      a = $a(arguments).slice(1, arguments.length);
   } else {
      a = new Array();
   }

   var f = this;
   return function(e) {
      return f.apply(o, a.concat(e || window.event));
   }
};

/***
<member name="Object.attach" type="method">
   <summary>Attach an event listener to an object.</summary>
   <param name="o">Context of called method f.</param>
   <param name="t">Type of event.</param>
   <param name="f">Method to fire when event is raised.</param>
   <param name="c">Use capture (not available in IE).</param>
   <param name="*">Arguments to pass to function f.</param>
</member>
***/







Object.prototype.attach = function(o, t, f, c) {
   var a;
   // turn arguments into an array and remove the argument 'o'
   if (arguments.length > 4) {
      a = $a(arguments).slice(4, arguments.length);
   } else {
      a = new Array();
   }
   // prepend context to be passed to bind()
   a.unshift(o ? o : this);
   
   if (this.addEventListener) {
      this.addEventListener(t, f.bind.apply(f, a), c);
   } else {
      this.attachEvent("on" + t, f.bind.apply(f, a));
   }
}




