//
// (C)  Bernhard Zwischenbrugger
// http://datenkueche.com
// bz(at)datenkueche(dot)com
//

//
// mapTypeControl
//

function mapTypeControl(){
	this.map=null;
        this.controlDiv=document.createElement("div");
        this.controlDiv.style.top="5px";
        this.controlDiv.style.left="100px";
        this.controlDiv.style.position="absolute";

/*
	var button=this.createButton("Mapnik");
	Event.attach(button,"mousedown",this.map.mapType("mapnik"),this,false);
	button.style.top="0px";
	button.style.left="00px";
	this.controlDiv.appendChild(button);

	var button=this.createButton("t@h");
	button.style.top="0px";
	button.style.left="120px";
	Event.attach(button,"mousedown",this.map.mapType("osma"),this,false);
	this.controlDiv.appendChild(button);

	var button=this.createButton("bikemap");
	button.style.top="0px";
	button.style.left="240px";
	Event.attach(button,"mousedown",this.map.mapType("bikenet"),this,false);
	this.controlDiv.appendChild(button);
*/
}

mapTypeControl.prototype.initialize=function(map){
	this.map=map;
	map.control.appendChild(this.controlDiv);

}

mapTypeControl.prototype.mapnik=function(){
	this.map.makeURL=this.map.mapnikURL;
	this.map.clearMap();
        this.map.maxZoom=18;
	this.map.draw();
}
mapTypeControl.prototype.osma=function(){
	this.map.server="http://b.tah.openstreetmap.org/Tiles/tile/";
	this.map.clearMap();
       this.map.maxZoom=17;
	this.map.draw();
}
mapTypeControl.prototype.bikemap=function(){
	this.map.server="http://a.andy.sandbox.cloudmade.com/tiles/cycle/";
	this.map.clearMap();
	this.map.maxZoom=18;
	this.map.draw();
}

mapTypeControl.prototype.createButton=function(text){
	var button=document.createElement("div");
	button.style.width="100px";
	button.style.height="20px";
	button.style.backgroundColor="lightgrey";
	button.style.border="1px solid white";
	//button.style.opacity=0.8;
	button.style.position="absolute";
	var textNode=document.createTextNode(text);
	button.appendChild(textNode);
	button.style.textAlign="center";
	button.style.color="white";
	button.style.cursor="pointer";
	return button;
}


//
// mapControl
//

function mapControl(){
	this.map=null;
        this.controlDiv=document.createElement("div");
        this.controlDiv.style.top="5px";
        this.controlDiv.style.left="5px";
        this.controlDiv.style.position="absolute";
	this.moveSpeed=1;
	this.sliding=false;
}


mapControl.prototype.initialize=function(map){
	this.map=map;

	//keyboard
	Event.attach(document,"keydown",this.keyDown,this,false);
	Event.attach(document,"keyup",this.keyUp,this,false);
	

	//zoommoveeleemnt

	map.control.appendChild(this.controlDiv);

	Event.attach(map.control,"mouseup",this.stopMove,this,false);
	var img=this.appendImg("images/west.png",0,20);
	Event.attach(img,"mousedown",this.startMoveWest,this,false);

	var img=this.appendImg("images/east.png",40,20);
	Event.attach(img,"mousedown",this.startMoveEast,this,false);

	var img=this.appendImg("images/north.png",20,0);
	Event.attach(img,"mousedown",this.startMoveNorth,this,false);

	var img=this.appendImg("images/south.png",20,40);
	Event.attach(img,"mousedown",this.startMoveSouth,this,false);
	var img=this.appendImg("images/zoom-plus.png",20,63);
	Event.attach(img,"mousedown",this.startZoomIn,this,false);
	var img=this.appendImg("images/zoom-minus.png",20,278);
	Event.attach(img,"mousedown",this.startZoomOut,this,false);
	var div=document.createElement("div");
	this.slider=div;
	div.style.position="absolute";
	div.style.top="0px";
	div.style.left="0px";
	this.controlDiv.appendChild(div);
	var img=this.appendImg("images/zoombar.png",20,80);
	div.appendChild(img);
	var img=this.appendImg("images/slider.png",19,100);
	div.appendChild(img);
	Event.attach(div,"mousedown",this.startSlider,this,false);
	Event.attach(div.parentNode.parentNode.parentNode,"mousemove",this.moveSlider,this,false);
	Event.attach(div.parentNode.parentNode.parentNode,"mouseup",this.endSlider,this,false);

}

mapControl.prototype.keyDown=function(evt){
	//if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	switch(evt.keyCode){
//		document.location.href="#"+evt.keyCode;
		case 39:this.startMoveEast();
			break; 
		case 37:this.startMoveWest();
			break; 
		case 38:this.startMoveNorth();
			break; 
		case 40:this.startMoveSouth();
			break; 
		case 187:
		case 61:this.startZoomIn();
			break; 
		case 189:
		case 109:this.startZoomOut();
			break; 
		case 13:this.map.snap();
			break; 
		default:
		//	alert(evt.keyCode);
	}
}

mapControl.prototype.keyUp=function(evt){
	this.stopMove();
}

mapControl.prototype.startSlider=function(evt){
	if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	this.sliding=true;
	var z=(-evt.clientY + this.map.origworld.offsetTop +80 +200)/11.12 ;
	if(z < 0)z=0;
	if(z > this.map.maxZoom)z=this.map.maxZoom;
	this.map.zoom=z;
	this.map.draw();
}

mapControl.prototype.moveSlider=function(evt){
	if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	if(this.sliding){
		var z=(-evt.clientY + this.map.origworld.offsetTop +80 +200)/11.12 ;
		if(z < 0)z=0;
		if(z > this.map.maxZoom)z=this.map.maxZoom;
		this.map.zoom=z;
		this.map.draw();
	}
}

mapControl.prototype.callback=function(){
	var mover=this.slider.childNodes.item(1);
	var top=-this.map.zoom*11.11 + this.map.origworld.offsetTop  +225;
	mover.style.top=top+"px";
}

mapControl.prototype.endSlider=function(evt){
	if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	this.sliding=false;
}

mapControl.prototype.startMoveEast=function(){
	this.move(1,0);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startMoveEast()",20);
}
mapControl.prototype.startMoveWest=function(){
	this.move(-1,0);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startMoveWest()",20);
}
mapControl.prototype.startMoveSouth=function(){
	this.move(0,1);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startMoveSouth()",20);
}
mapControl.prototype.startMoveNorth=function(){
	this.move(0,-1);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startMoveNorth()",20);
}

mapControl.prototype.startZoomIn=function(){
	//this.move(0,-1);
	this.zoom(+1);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startZoomIn()",20);
}
mapControl.prototype.startZoomOut=function(){
	//this.move(0,-1);
	this.zoom(-1);
	this.moveSpeed=this.moveSpeed+0.2;
	thisObject=this;
	thisObject.moveTimer=setTimeout("thisObject.startZoomOut()",20);
}




mapControl.prototype.stopMove=function(){
	this.moveSpeed=1;
	clearTimeout(this.moveTimer);
}

mapControl.prototype.move=function(x,y){
	this.map.x=this.map.x+x*this.moveSpeed;	
	this.map.y=this.map.y+y*this.moveSpeed;	
	this.map.latlng();
	this.map.draw();
}

mapControl.prototype.zoom=function(z){
	z=this.map.zoom+0.01*z*this.moveSpeed/4+z*0.01;
	if(z<0)z=0;
	if(z>this.map.maxZoom)z=this.map.maxZoom;
	this.map.zoom=z;
	this.map.draw();
}

mapControl.prototype.appendImg=function(src,left,top){
	var img=document.createElement("img");
	img.setAttribute("src",src);
	img.style.top=top+"px";
	img.style.left=left+"px";
	img.style.position="absolute";
	this.controlDiv.appendChild(img);
	return img;
}




function kMap(world){
	this.origworld=world;

	this.eventtarget=document.createElement("div");
	this.eventtarget.style.position="absolute";
	this.eventtarget.style.top="0px";
	this.eventtarget.style.left="0px";
	this.eventtarget.style.width=this.origworld.offsetWidth+"px";
	this.eventtarget.style.height=this.origworld.offsetHeight+"px";
	this.origworld.appendChild(this.eventtarget);

	this.world=document.createElement("div");
	this.world.style.position="absolute";
	this.world.style.top=0+"px";
	this.world.style.left=0+"px";
	this.eventtarget.appendChild(this.world);

	this.control=document.createElement("div");
	this.control.style.position="absolute";
	this.control.style.top="0px";
	this.control.style.left="0px";
	world.appendChild(this.control);

	//constants
	this.server="http://b.tile.openstreetmap.org/";
	//this.server="http://b.tah.openstreetmap.org/Tiles/tile/";
	this.maxZoom=18;
	this.minZoom=0;
	this.wx=256;
	this.wy=256;
	//variables
	this.makeURL=this.mapnikURL;
	this.snaping=true;
	this.clicked=false;
	this.visibleLayer=null;
	this.downX=0;
	this.downY=0;
	this.clientX=0;
	this.clientY=0;
	this.dx=0;
	this.dy=0;
	this.x=0;
	this.y=0;
	this.zoomspeed=0.01;
	this.loadStatArray=new Array(this.maxZoom - this.minZoom);
	for(var i=this.minZoom; i <= this.maxZoom;i++){this.loadStatArray[i]=0}
	this.frames=0;
	this.xydrawBlocked=false;
	this.moveBlocked=false;
	this.doubleClick=false;
	this.snapTimer=null;
	this.selectArea=null;
	//this.world=world;
	world.style.overflow="hidden";
	this.getSize(world);
	/*
        window.attach(this,"resize",this.getSize,false);
        this.world.attach(this,"DOMMouseScroll",this.wheel,false);
	*/
	Event.attach(window,"resize",this.getSize,this,false);
	Event.attach(this.eventtarget,"DOMMouseScroll",this.wheel,this,false);
	Event.attach(this.eventtarget,"mousedown",this.down,this,false);
	Event.attach(this.eventtarget,"dblclick",this.doubledown,this,false);
	Event.attach(this.eventtarget,"mouseup",this.up,this,false);
	Event.attach(this.eventtarget,"mousemove",this.move,this,false);

	while(this.world.firstChild){this.world.removeChild(this.world.firstChild)}
	//this.xydraw(1000,800,3,3);


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



kMap.prototype.getSize=function(){
	this.width=this.origworld.offsetWidth;
	this.height=this.origworld.offsetHeight;
	this.top=this.origworld.offsetTop;
	this.left=this.origworld.offsetLeft;
	this.clientX=this.width/2;
	this.clientY=this.height/2;
	//alert(this.width);
}

kMap.prototype.down=function(evt){
	if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	clearTimeout(this.snapTimer);
	this.downX=parseInt(evt.clientX);
	this.downY=parseInt(evt.clientY);
	if(this.doubleClick){
		this.zoomIn(evt);	
	}else{
		if(evt.shiftKey){
			this.selectArea=document.createElement("div");
			this.eventtarget.appendChild(this.selectArea);
			this.selectArea.style.position="absolute";
			/*
			this.selectArea.style.top=parseFloat(evt.clientY)-this.top+"px";
			this.selectArea.style.left=parseFloat(evt.clientX)-this.left+"px";
			*/
			if(!document.all){
				this.selectArea.style.backgroundColor="white";
			}
			this.selectArea.style.border="1px solid grey";
			this.selectArea.style.opacity=0.4;
			//this.selectArea.style.filter="alpha(opacity=20)";
		}else{
			this.doubleClick=true;
			thisObject=this;
			setTimeout("thisObject.doubleClick=false",300);	
			this.clicked=true;
			this.moving=true;
		}
	}
}

kMap.prototype.doubledown=function(evt){
	if(evt.preventDefault){ evt.preventDefault( ); }else{ evt.returnValue = false;}
	this.downX=parseInt(evt.clientX);
	this.downY=parseInt(evt.clientY);
	this.zoomIn(evt);	
}
	

kMap.prototype.zoomIn=function(evt){
	var steps=20;
	var force="no";
	//var ddx=this.downX-evt.clientX;
	//var ddy=this.downY-evt.clientY;
	ddx=this.clientX - this.left - this.width/2;
	ddy=this.clientY - this.top - this.height/2;
	for(var i=0;i<=steps;i++){
		var dx=ddx*(1 - i / steps);
		var dy=ddy*(1 - i / steps);
		var z=this.zoom+(Math.floor(this.zoom+1) - this.zoom)*( i / steps);
		thisObject=this;
		if(i==steps){
			//alert(z);
			z=Math.round(z) 
			force="yes";
		}
		if(z>this.maxZoom)z=this.maxZoom;
		var cmd="thisObject.dx="+dx+";thisObject.dy="+dy+";thisObject.zoom="+z+";thisObject.draw('"+force+"')";
		//console.log(cmd);
		setTimeout(cmd,20*i);	
		//var cmd="thisObject.dx="+dx+";thisObject.dy="+dy+";thisObject.zoom="+Math.round(z)+";thisObject.draw()";
	}
	
}

kMap.prototype.snap=function(){
	var z=Math.round(this.zoom);
	this.zoom=z;
	this.draw("yes");
}

kMap.prototype.autosnap=function(){
	if(this.snaping){
		thisObject=this;
		window.clearTimeout(this.snapTimer);
		if(typeof(thisObject.snap)=="function"){ //now idea but keyboard action ...
			thisObject.snapTimer=setTimeout( function () {thisObject.snap();},500);
		}
	}
}

kMap.prototype.snapZoom=function(sn){
	this.snaping=sn;
}

kMap.prototype.imgLoaded=function(evt,intZoom){
	/*
	if(evt.target){
	//	evt.target.style.visibility="";
	}else{
		try{
		evt.srcElement.style.visibility="";
		}catch(e){}
	}
	*/
		try{
		evt.srcElement.style.visibility="";
		}catch(e){}
	//alert("hi ie");
	//console.log("z: "+intZoom);
	this.loadStatArray[intZoom]--;	
	if(this.loadStatArray[intZoom]==0){
		if(intZoom > this.visibleLayer){
			this.visibleLayer=intZoom;
		}
		this.draw();
	}
}
/*
function debug(a,intZoom,visibleLayer){
	var t=document.getElementById("debug");
	while(t.firstChild){
		t.removeChild(t.firstChild);
	}
	for(var i=0; i < a.length;i++){
		var d=document.createElement("div");
		//d.setAttribute("id","debug"+i);
		d.style.fontSize="12px";
		if(i==intZoom){
			d.style.color="red";
		}
		if(i==visibleLayer){
			d.style.backgroundColor="lightgreen";
		}
		document.getElementById("debug").appendChild(d);
		var textNode=document.createTextNode(a[i]);
		d.appendChild(textNode);
	}

}
*/
kMap.prototype.draw=function(force){
//	console.log(this.dx,this.dy,this.clientX,this.clientY);
	this.x= (this.lng / 360 +0.5) *Math.pow(2,this.zoom) *this.wx - this.dx ;
	this.y=  (this.lat2y(-this.lat) / 360 +0.5) *Math.pow(2,this.zoom) *this.wy -this.dy ;
/*	
	document.getElementById("lat").firstChild.nodeValue=this.lng+":"+this.zoom+":"+this.wy+":"+this.dx;
	document.getElementById("lng").firstChild.nodeValue=this.y;
*/

	//console.log("--"+this.x+":"+this.y);
	this.xydraw(this.x,this.y,this.zoom,Math.floor(this.zoom),force);
}



/*
        GMap2.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();
        }
*/

kMap.prototype.xydraw=function(middleX,middleY,zoom,intZoom,force){
	if(this.xydrawBlocked && (force!='yes')){
		return;
	}
	this.xydrawBlocked=true;

	this.realXYdraw(middleX,middleY,zoom,intZoom);

	if(this.loadStatArray[intZoom]==0){
		this.visibleLayer=intZoom;	
	}else{
		//debug(this.loadStatArray,intZoom,this.visibleLayer);

		if(this.loadStatArray[intZoom]!=0){
			if(intZoom > this.visibleLayer){
				this.realXYdraw(middleX,middleY,zoom,this.visibleLayer);
			}
		}
	}

	var thisObject=this;
	this.autosnap();  
}


kMap.prototype.move=function(evt){
	if(evt.preventDefault){ evt.preventDefault( );
	}else{ evt.returnValue = false;}
	this.doubleClick=false;
	this.clientX=parseInt(evt.clientX);
	this.clientY=parseInt(evt.clientY);
	if(this.moving){
		if(this.moveBlocked){
			return;
		}
		var dx=this.downX-this.clientX;
		var dy=this.downY-this.clientY;
		var x=this.x+dx;
		var y=this.y+dy;
		/*
		this.visualDiv.style.top=y;
		this.visualDiv.style.left=x;
		*/

		this.moveBlocked=true;
		this.world.style.top=-dy+"px";	
		this.world.style.left=-dx+"px";
		thisObject=this;	
		setTimeout( function () {thisObject.moveBlocked=false;},1);
		if(Math.abs(dx) > 100 || Math.abs(dy) > 100 ){
			this.world.style.top=0+"px";	
			this.world.style.left=0+"px";
			this.x=x;
			this.y=y;
			this.downX=parseInt(evt.clientX);
			this.downY=parseInt(evt.clientY);
			this.latlng();
			this.xydraw(x,y,this.zoom,Math.floor(this.zoom));
		}
	}
	if(this.selectArea!=null){
		/*
		this.selectArea.style.width=parseFloat(evt.clientX) - this.left - parseFloat(this.selectArea.style.left)+"px";
		this.selectArea.style.height=parseFloat(evt.clientY) - this.top - parseFloat(this.selectArea.style.top)+"px";
		*/
		var width=parseFloat(evt.clientX) -  this.downX;
		var height=parseFloat(evt.clientY) -  this.downY;
		if(width > 0){
			var left=this.downX - this.left;
		}else{
			var left=evt.clientX - this.left;
			width=width*-1;
		}
		if(height > 0){
			var top=this.downY - this.top;
		}else{
			var top=evt.clientY - this.top;
			height=height*-1;
		}
		this.selectArea.style.top=top+"px";
		this.selectArea.style.left=left+"px";
		this.selectArea.style.width=width+"px";
		this.selectArea.style.height=height+"px";
	}
}

kMap.prototype.up=function(evt){
	if(this.moving){
		this.x=this.x+this.downX-parseInt(evt.clientX);	
		this.y=this.y+this.downY-parseInt(evt.clientY);
		this.moving=false;

		//GPS (WGS84) Koordinaten berechnen

		this.world.style.top=0+"px";	
		this.world.style.left=0;
	//	this.lng=(this.x/Math.pow(2,this.zoom) /this.wx -0.5)*(360);
	//	this.lat=this.y2lat((this.y/Math.pow(2,this.zoom) /this.wy -0.5)*(-360));
		this.latlng();
		this.draw();
	}
	if(this.selectArea!=null){
		this.areaSelect();
		this.selectArea.parentNode.removeChild(this.selectArea);
		this.selectArea=null;
	}
}

kMap.prototype.areaSelect=function(){
	
	var top=parseFloat(this.selectArea.style.top);
	var left=parseFloat(this.selectArea.style.left);
	var width=parseFloat(this.selectArea.style.width);
	var height=parseFloat(this.selectArea.style.height);
	x=left+width/2;
	y=top+height/2;
	this.latlng();
	var deltaz1=parseFloat(this.width) /width;
	var deltaz2=parseFloat(this.height) /height;
	if(deltaz1 < deltaz2){
		deltaz=deltaz1;
	}else{
		deltaz=deltaz2;
	}
	/*
	deltaz=2^deltazoom;
	deltazoom=ln(deltaz);
	*/
	deltazoom=Math.log(deltaz)/Math.log(2);
	this.clientX=x +this.left;
	this.clientY=y +this.top;
	//console.log(this.clientX+":"+this.clientY);
	this.latlng();
	//console.log(this.lat+":"+this.lng);
	/*
	this.x=x -this.left;// - this.width/2;
	this.y=y -this.top;// - this.height/2;
	*/
	
	
	this.zoom=Math.floor(this.zoom+deltazoom);
	this.dx=0;
	this.dy=0;
	this.draw();
}

//show lat, lng
kMap.prototype.latlng=function(){
	this.dx=this.clientX - this.left - this.width/2;
	this.dy=this.clientY - this.top - this.height/2;
	this.lng=((this.x+this.dx)/Math.pow(2,this.zoom) /this.wx -0.5)*(360);
	this.lat=this.y2lat(((this.y+this.dy)/Math.pow(2,this.zoom) /this.wy -0.5)*(-360));
	/*
	document.getElementById("lat").firstChild.nodeValue=this.dx+":"+this.clientX+":"+this.left+":"+this.width;
	document.getElementById("lng").firstChild.nodeValue=this.lng;
	*/
}


kMap.prototype.setCenter=function(lat,lng,z){
	this.zoom=z;
	this.lat=lat;
	this.lng=lng;
	//this.xydraw(x,y,z,Math.floor(z));
	if(this.visibleLayer==null){
		this.visibleLayer=Math.floor(this.zoom)
	}
	this.dx=0;
	this.dy=0;
	this.draw();
}

kMap.prototype.wheel=function(evt){

	this.latlng();
        var delta = 0;
        if (!evt) /* For IE. */
                evt = window.event;
        if (evt.wheelDelta) { /* IE/Opera. */
                delta = evt.wheelDelta/60;
                if (window.opera){
                        delta = delta/4;
		}
	} else if (evt.detail) { /** Mozilla case. */
		delta = -evt.detail/3;
	}

        if (navigator.userAgent.match("Safari") ){
		delta = evt.wheelDelta/150;
	}
	 // var normal = e.detail ? e.detail * -1 : e.wheelDelta / 120;
	if(evt.altKey){
		extraspeed=1;
	}else{
		extraspeed=10;
	}

	this.zoom=this.zoom+this.zoomspeed*delta*extraspeed;

	this.zoomspeed=this.zoomspeed+0.01;
	if(this.zoom >this.maxZoom) this.zoom=this.maxZoom;
	if(this.zoom <0) this.zoom=0;
	var cmd="this.zoomspeed=this.zoomspeed -0.01";
	thisObject=this;
            setTimeout( function () {thisObject.zoomspeed=thisObject.zoomspeed -0.01;},100);




//	this.xydraw(this.x,this.y,this.zoom,Math.floor(this.zoom));
	this.draw();
}

kMap.prototype.imgLoaded=function(evt,intZoom){
	/*
	if(evt.target){
	//	evt.target.style.visibility="";
	}else{
		try{
		evt.srcElement.style.visibility="";
		}catch(e){}
	}
	*/
		try{
		evt.srcElement.style.visibility="";
		}catch(e){}
	//alert("hi ie");
	//console.log("z: "+intZoom);
	this.loadStatArray[intZoom]--;	
	if(this.loadStatArray[intZoom]==0){
		this.visibleLayer=intZoom;
		this.draw();
	}
}
/*
function debug(a,intZoom,visibleLayer){
	var t=document.getElementById("debug");
	while(t.firstChild){
		t.removeChild(t.firstChild);
	}
	for(var i=0; i < a.length;i++){
		var d=document.createElement("div");
		//d.setAttribute("id","debug"+i);
		d.style.fontSize="12px";
		if(i==intZoom){
			d.style.color="red";
		}
		if(i==visibleLayer){
			d.style.backgroundColor="lightgreen";
		}
		document.getElementById("debug").appendChild(d);
		var textNode=document.createTextNode(a[i]);
		d.appendChild(textNode);
	}

}
*/
kMap.prototype.draw=function(force){
//	console.log(this.dx,this.dy,this.clientX,this.clientY);
	this.x= (this.lng / 360 +0.5) *Math.pow(2,this.zoom) *this.wx - this.dx ;
	this.y=  (this.lat2y(-this.lat) / 360 +0.5) *Math.pow(2,this.zoom) *this.wy -this.dy ;
/*	
	document.getElementById("lat").firstChild.nodeValue=this.lng+":"+this.zoom+":"+this.wy+":"+this.dx;
	document.getElementById("lng").firstChild.nodeValue=this.y;
*/

	//console.log("--"+this.x+":"+this.y);
	this.xydraw(this.x,this.y,this.zoom,Math.floor(this.zoom),force);
}



/*
        GMap2.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();
        }
*/

kMap.prototype.xydraw=function(middleX,middleY,zoom,intZoom,force){
	if(this.xydrawBlocked && (force!='yes')){
		return;
	}
	this.xydrawBlocked=true;

	this.realXYdraw(middleX,middleY,zoom,intZoom);

	if(this.loadStatArray[intZoom]==0){
		this.visibleLayer=intZoom;	
	}else{
		//debug(this.loadStatArray,intZoom,this.visibleLayer);

		if(this.loadStatArray[intZoom]!=0){
			if(intZoom > this.visibleLayer){
				this.realXYdraw(middleX,middleY,zoom,this.visibleLayer);
			}
		}
	}

	var thisObject=this;
            setTimeout( function () {thisObject.xydrawBlocked=false;},1);
	this.autosnap();
}


kMap.prototype.clearMap=function(){
	var divs=this.world.childNodes;
	for(var i=0; i < divs.length; i++){
		this.world.removeChild(divs.item(i));
	}
	for(var i=this.minZoom; i <= this.maxZoom;i++){this.loadStatArray[i]=0}
}

kMap.prototype.realXYdraw=function(middleX,middleY,zoom,intZoom){

	this.frames++;
	var faktor=Math.pow(2,(zoom-intZoom));

	//this.world.style.border="3px solid red";
	var divs=this.world.childNodes;
	for(var i=0; i < divs.length; i++){
                if(divs.item(i).getAttribute("zoomlevel") != intZoom){
                        divs.item(i).style.display="none";
                }
		if(divs.item(i).getAttribute("zoomlevel")==intZoom){
			var div=divs.item(i);
		}
	}	
	//create div for zoomlevel if not existing
	if(!div){
		var div=document.createElement("div");
                div.setAttribute("zoomlevel",intZoom);
                //div.style.opacity=0.2;
                div.style.position="absolute";
                this.world.appendChild(div);
        }
	this.visualDiv=div;
	div.setAttribute("notLoaded",0);
	//set div coordinates to the middle of the world
        div.style.top=this.height/2+"px";
        div.style.left=this.width/2+"px";
        div.style.display="none";

        var startX=Math.floor(middleX/this.wx/faktor)-Math.ceil(this.width/this.wx/2/faktor);
        var startY=Math.floor(middleY/this.wy/faktor)-Math.ceil(this.height/this.wy/2/faktor);

        var endX=Math.floor(middleX/this.wx/faktor)+Math.ceil(this.width/this.wx/2/faktor)+1;
        var endY=Math.floor(middleY/this.wy/faktor)+Math.ceil(this.height/this.wy/2/faktor)+1;

	//document.getElementById("zoom").firstChild.nodeValue=this.frames+" : "+startX+" : "+endX+" : "+intZoom+":"+this.zoom;
        var anz=Math.pow(2,intZoom);  //available openstreetmap images for zoomlevel
	//console.log(startX);
        for(var x=startX;x<endX;x++){
                for(var y=startY;y<endY;y++){
                        //make world recursive
                        var imgX=x % anz;
                        var imgY=y % anz;
                        if(imgX < 0) imgX=imgX+anz;  //modulo function gives negative value for negative numbers
                        if(imgY < 0) imgY=imgY+anz;
                        //place the images
                        //var url=this.server+intZoom+"/"+imgX+"/"+imgY+".png";
			var url=this.makeURL(imgX,imgY,intZoom);
                        var id="img"+intZoom+":"+x+":"+y;
                        //if(document.getElementById(id)){
                        //      var img=document.getElementById(id);
                        var img=null;
			
                        var imgs=div.getElementsByTagName("img");
                        for(var i=0;i < imgs.length;i++){
                                if(imgs.item(i).getAttribute("theid")==id){
                                        img=imgs.item(i);
                                        break;
                                }

                        }
			

			//img=document.getElementById(id);

                        if(img==null){
				//console.log("new pic");
                                var img=document.createElement("img");
				//load events handling
				Event.attach(img,"load",this.imgLoaded,this,false,intZoom);
				this.loadStatArray[intZoom]++;


                                img.setAttribute("theid",id);
                                img.setAttribute("onload","this.style.visibility=''");

                                img.style.visibility="hidden";

				img.style.position="absolute";

				img.setAttribute("src",url);
                                div.appendChild(img);
                        }
			img.setAttribute("keep","yes");
                        var top=(y*this.wy*faktor -middleY);
                        var left=(x *this.wx*faktor -middleX);
                        img.style.top=Math.round(top)+"px";
                        img.style.left=Math.round(left)+"px";
                        img.style.width=Math.round(this.wx *faktor +left)- Math.round(left)+"px";
                        img.style.height=Math.round(this.wx *faktor +top)- Math.round(top)+"px";
                }
        }
	//if(this.clicked){
		//console.log("loadstat: "+this.loadStatArray[intZoom]);
		var imgs=div.getElementsByTagName("img");
		for(var i=imgs.length-1;i >=0;i--){
			var img=imgs.item(i);		
			if(img.getAttribute("keep")!="yes"){
				if(img.complete==false){
					if(window.opera){
					this.loadStatArray[intZoom]--;
					}
				}
				img.parentNode.removeChild(img);
				
			}
			img.setAttribute("keep","no");
		}
		this.clicked=false;
	//}
//	if(intZoom==this.visibleLayer){
		div.style.display="";
//	}

	// call all callback things
	for(var i=0; i <  this.callbackHandlers.length;i++){
		this.callbackHandlers[i].callback();
	}	
}

kMap.prototype.mapType=function(type) {
	this.clearMap();
	switch(type){
		case "mapnik":this.makeURL=this.mapnikURL;
			this.maxZoom=18;
			break;
		case "osma":this.makeURL=this.osmaURL;
			this.maxZoom=17;
			break;
		case "bikemap":this.makeURL=this.bikemapURL;
			this.maxZoom=18;
			break;
		default:
			alert("unknown maptype");
	}
	this.draw();
}

kMap.prototype.osmaURL=function(imgX,imgY,intZoom) {
	var serverNum=(imgX+imgY) % 3 +1;
	switch(serverNum){
		case 1: server="a";break;
		case 2: server="b";break;
		case 3: server="c";break;
	}
	var url="http://"+server+".tah.openstreetmap.org/Tiles/tile/"+intZoom+"/"+imgX+"/"+imgY+".png";
	return(url);
}

kMap.prototype.mapnikURL=function(imgX,imgY,intZoom) {
        var serverNum=(imgX+imgY) % 3 +1;
        switch(serverNum){
                case 1: server="a";break;
                case 2: server="b";break;
                case 3: server="c";break;
        }
	var url="http://"+server+".tile.openstreetmap.org/"+intZoom+"/"+imgX+"/"+imgY+".png";
	return(url);
}

kMap.prototype.bikemapURL=function(imgX,imgY,intZoom) {
        var serverNum=(imgX+imgY) % 3 +1;
        switch(serverNum){
                case 1: server="a";break;
                case 2: server="b";break;
                case 3: server="c";break;
        }
	var url="http://"+server+".andy.sandbox.cloudmade.com/tiles/cycle/"+intZoom+"/"+imgX+"/"+imgY+".png";
	return(url);
}

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


kMap.prototype.addControl=function(control){
	control.initialize(this);
	if((typeof control.callback)=="function"){
		this.callbackHandlers.push(control);
	}
}



//
//
//
//
//
//
// 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;
} 

// Creates an object called "Event" if one doesn't already exist (IE).
if (!Event) {
   var Event = {};
}

/***
<member name="Event.attach" type="static method">
   <summary>Attach an event listener to an object.</summary>
   <param name="o">Object whose event to attach.</param>
   <param name="t">Type of event.</param>
   <param name="f">Method to fire when event is raised.</param>
   <param name="fc">Context of called method f. Defaults to object o.</param>
   <param name="c">Use capture (not available in IE).</param>
   <param name="*">Arguments to pass to function f.</param>
</member>
***/
Event.attach = function (o, t, f, fc, c) {
   var a = (arguments.length > 5 ? $a(arguments).slice(5, arguments.length) : new Array());
   var fn = function(e) {
      a.unshift(e || window.event);
      return f.apply((fc ? fc : o), a);
   }
   if (o.addEventListener) {
        if (navigator.appName.indexOf("Netscape") == -1){
                if(t=="DOMMouseScroll"){
                        t="mousewheel";
                }
        }
        if (navigator.userAgent.indexOf("Safari")!=-1 ){
                if(t=="DOMMouseScroll"){
                       	o.onmousewheel=fn; 
                }else{
			o.addEventListener(t, fn, c);
		}
	}else{
		o.addEventListener(t, fn, c);
	}
   } else {
        if(t=="DOMMouseScroll"){
                o.attachEvent("onmousewheel",fn);
        }else{
              o.attachEvent("on" + t, fn);
        }
   }

};
