var GridMap = function(container,parameter,options){
   this.container = container;
   this.parameter = {
	    layerWidth: 1600,
		layerHeight: 1067,
	    layerTop: 0,
		layerLeft: 0,
		imgWidth: 1600,
		imgHeight: 1067,
		imgSrc: "test.jpg",
		moveStep:50,
		zoomStep:0.1,
		jwLeftBottom: {x:1,y:1},
		jwRightTop: {x:1480,y:1658}
	};
	Object.extend(this.parameter, parameter || {});
	
	this.options = {
	    enableDrag: true,
		enableDblClick: true
	}
	Object.extend(this.options, options || {});

	this.onDragStart = new Function();
	this.onDrag = new Function();
	this.onDragEnd = new Function();
	this.onDblClick = new Function();
	this.onInit = new Function();
	this.onDisplay = new Function();

	this.destroy = function(){
		if(this.imgLayerContainer) this.imgLayerContainer.removeNode(true);
	    if(this.layerContainer) this.layerContainer.removeNode(true);
	}
	this._layerContainerDragStartEvent =function (ele,x,y){
		this.onDragStart(this,x,y);
	}
	this._layerContainerDragEvent =function (ele,x,y){
        xMoveTo(ele, xLeft(ele) + x, xTop(ele) + y);
		this.onDrag(this,x,y);	
	}	
	this._layerContainerDragEndEvent =function (ele,x,y){
		this.display();
		this.onDragEnd(this,x,y)	
	}
	this._layerContainerDblClickEvent =function (evt){
        var e = new xEvent(evt);
        var offsetX = Math.ceil(e.pageX-(xWidth(this.container)/2));
		var offsetY = Math.ceil(e.pageY-(xHeight(this.container)/2));
        this.moveTo(xLeft(this.layerContainer)-offsetX,xTop(this.layerContainer)-offsetY);	
		this.onDblClick(this,e.pageX,e.pageY);
	}	
    this._initFrame = function(){
        this.destroy();

		this.layerContainer = document.createElement("span");
		this.layerContainer.className = "layerContainer";
		this.container.appendChild(this.layerContainer);

		this.imgLayerContainer = document.createElement("span");
		this.imgLayerContainer.className = "imgLayerContainer";
		this.layerContainer.appendChild(this.imgLayerContainer);
		        
        if(this.options.enableDrag==true){
			xEnableDrag(this.layerContainer,
				this._layerContainerDragStartEvent.bind(this),
				this._layerContainerDragEvent.bind(this),
				this._layerContainerDragEndEvent.bind(this));	
		}
		if(this.options.enableDblClick==true){
		    this.layerContainer.ondblclick = this._layerContainerDblClickEvent.bindAsEventListener(this);
		}
		
        if(this.imgLayerContainer) this.imgLayerContainer.innerHTML ="";
		this.layerContainer.style.width = this.parameter.layerWidth;
		this.layerContainer.style.height = this.parameter.layerHeight;
		
		var img = document.createElement("img");
		img.style.top = "0px";
		img.style.left = "0px";
		img.style.width ="100%";
		img.style.height="100%";
          //img.style.width ="auto";
		  //img.style.height="auto";		
		img.src = this.parameter.imgSrc;
        this.imgLayerContainer.appendChild(img);
        this.image = img;		
		this.onInit(this);	

		this.loading = document.createElement("span");
		this.loading.className = "loadingPanel";
		this.loading.innerHTML="loading...";
		this.layerContainer.appendChild(this.loading);
	}

    this.showLoading = function(visible,text){
		if(text) this.loading.innerHTML=text;
		if(visible){
			xMoveTo(this.loading,Math.ceil((xWidth(this.container)-this.parameter.layerWidth)/2),
			Math.ceil((xHeight(this.container)-this.parameter.layerHeight)/2));
			this.loading.style.display = "";
		}else this.loading.style.display = "none";
	}

    this.changeImage = function(src,width,height){
		this.showLoading(true);
        this.parameter.layerWidth = width;
        this.parameter.layerHeight = height;
        this.layerContainer.style.width = this.parameter.layerWidth;
		this.layerContainer.style.height = this.parameter.layerHeight;
		this.image.src = src;
		var mapobj = this;
		this.image.onload = function(){
			mapobj.showLoading(false);
		}
		this.moveCenter();
    }
    
	this._initFrame();

	this.display = function(){
        this.onDisplay(this);
	}
    this.moveTo = function(left,top){
		//alert(left+"|"+top);
		xMoveTo(this.layerContainer,Math.ceil(left),Math.ceil(top));
		this.display();
	}
	this.moveUp = function(){	
		xTop(this.layerContainer,xTop(this.layerContainer)+this.parameter.moveStep);
		this.display();
	}
	this.moveDown = function(){
		xTop(this.layerContainer,xTop(this.layerContainer)-this.parameter.moveStep)
		this.display();
	}
	this.moveLeft = function(){
		xLeft(this.layerContainer,xLeft(this.layerContainer)+this.parameter.moveStep);
		this.display();
	}
	this.moveRight = function(){
	    xLeft(this.layerContainer,xLeft(this.layerContainer)-this.parameter.moveStep);
		this.display();
	}
	this.moveCenter = function(){
		this.moveTo(Math.ceil((xWidth(this.container)-this.parameter.layerWidth)/2),
			Math.ceil((xHeight(this.container)-this.parameter.layerHeight)/2));
	}
	this.zoomIn = function(level){
	    if(level){
	        this.zoomTo(Math.ceil(xWidth(this.layerContainer)*(Math.pow(1+this.parameter.zoomStep,level))),
		    			Math.ceil(xHeight(this.layerContainer)*(Math.pow(1+this.parameter.zoomStep,level))));
	    }else{
		    this.zoomTo(Math.ceil(xWidth(this.layerContainer)*(1+this.parameter.zoomStep)),
		    			Math.ceil(xHeight(this.layerContainer)*(1+this.parameter.zoomStep)));
	    }			
	}
	this.zoomOut = function(level){
	    if(level){
		    this.zoomTo(Math.ceil(xWidth(this.layerContainer)*(Math.pow(1-this.parameter.zoomStep,level))),
		    			Math.ceil(xHeight(this.layerContainer)*(Math.pow(1-this.parameter.zoomStep,level))));	    
	    }else{
		    this.zoomTo(Math.ceil(xWidth(this.layerContainer)*(1-this.parameter.zoomStep)),
		    			Math.ceil(xHeight(this.layerContainer)*(1-this.parameter.zoomStep)));	    
	    }
	}
	this.zoomTo = function(wid,hei){
	    var posx = Math.ceil(xWidth(this.container)/2-xLeft(this.layerContainer));
	    var posy = Math.ceil(xHeight(this.container)/2-xTop(this.layerContainer));
	    var cjw = this.getJwByPos(posx,posy);
	    
		this.layerContainer.style.width = wid;
		this.layerContainer.style.height = hei;	
	  
		var cpos2 = this.getPosByJw(cjw.x,cjw.y);
		this.moveTo(xLeft(this.layerContainer)-(cpos2.x-posx),xTop(this.layerContainer)-(cpos2.y-posy));
	}
	this.zoomReset = function(){
	    this.layerContainer.style.width = this.parameter.layerWidth;
		this.layerContainer.style.height = this.parameter.layerHeight;
	}
	this.getJwByPos = function(x,y){
		var xDiff = this.parameter.jwRightTop.x - this.parameter.jwLeftBottom.x; 
		var yDiff = this.parameter.jwRightTop.y - this.parameter.jwLeftBottom.y;
		var jwX = (x * xDiff) / xWidth(this.layerContainer) + this.parameter.jwLeftBottom.x;
		var jwY = (y * yDiff) / xHeight(this.layerContainer) + this.parameter.jwLeftBottom.y; 
		return {x:jwX,y:jwY};
	}
	this.getPosByJw = function(x,y){
		var xDis = x -  this.parameter.jwLeftBottom.x; 
		var yDis = y -  this.parameter.jwLeftBottom.y; 
		var xDiff = this.parameter.jwRightTop.x - this.parameter.jwLeftBottom.x; 
		var yDiff = this.parameter.jwRightTop.y - this.parameter.jwLeftBottom.y;
		var posX = Math.ceil((xDis * xWidth(this.layerContainer))/xDiff);
		var posY = Math.ceil((yDis * xHeight(this.layerContainer))/yDiff);
		return {x:posX,y:posY};
	}	
}

var GridMiniMap = function(container,parameter){
	 this.container = container;
	 this.parameter={
		 width:100,
		 height:100,
		 rangeWidth:20,
		 rangeHeight:20,
		 imgSrc:'test.jpg',
		 left:0,
		 top:false,
		 right:false,
		 bottom:0
	 }
	 Object.extend(this.parameter, parameter || {});
	 
	 this.changeImage = function(src,width,height){
        this.parameter.width = width;
        this.parameter.height = height;
        this.parameter.rangeWidth = Math.ceil(width/5);
        this.parameter.rangeHeight = Math.ceil(height/5);
        
		xWidth(this.mapBox,this.parameter.width);
		xHeight(this.mapBox,this.parameter.height);
		xWidth(this.mapRangeBox,this.parameter.rangeWidth);
		xHeight(this.mapRangeBox,this.parameter.rangeHeight);	
		this.image.src = src;
		this.moveCenter();
    }
	 
	 this.onRangeChange = new Function();

	 this._mapRangeBoxDragEvent = function(ele,x,y){
		 this.moveTo(xLeft(ele)+x,xTop(ele)+y);  
	 }
	 this._mapRangeBoxDragEndEvent = function(ele,x,y){
		 this.onRangeChange(this);	     
	 }
	 this.moveTo = function(left,top){
		 if(left<0) left = 0;
		 else if(left+xWidth(this.mapRangeBox)>xWidth(this.mapBox)) left = xWidth(this.mapBox)-xWidth(this.mapRangeBox);
		 if(top<0) top = 0;
		 else if(top+xHeight(this.mapRangeBox)>xHeight(this.mapBox)) top = xHeight(this.mapBox)-xHeight(this.mapRangeBox);
		 xMoveTo(this.mapRangeBox,left,top);	 
	 }
	 this.moveCenter = function(){
		 xMoveTo(this.mapRangeBox, (xWidth(this.mapBox)-xWidth(this.mapRangeBox))/2, (xHeight(this.mapBox)-xHeight(this.mapRangeBox))/2);	 
	 }
	 this._mapBoxClickEvent = function(evt){
		 var e = new xEvent(evt);
		 this.moveTo(Math.ceil(e.offsetX-xWidth(this.mapRangeBox)/2),Math.ceil(e.offsetY-xHeight(this.mapRangeBox)/2));
		 this.onRangeChange(this);
	 }
 	 this.destroy = function(){
		if(this.mapRangBox) this.mapRangeBox.removeNode(true);
	    if(this.mapBox) this.mapBox.removeNode(true);
	 }
	 this._initFrame = function(){
		this.destroy();

		this.mapBox = document.createElement("span");
		this.mapBox.className ="miniMapBox";
		this.container.appendChild(this.mapBox);
		this.mapBox.onclick = this._mapBoxClickEvent.bindAsEventListener(this);
		this.mapBox.innerHTML="<img src='"+this.parameter.imgSrc+"' style='width:100%;height:100%;'/>";
		this.mapRangeBox = document.createElement("span");
		this.mapRangeBox.className = "miniMapRangeBox";
		this.mapRangeBox.onclick = function(evt){ xStopPropagation(evt);}
		this.mapBox.appendChild(this.mapRangeBox);
        this.image = this.mapBox.childNodes[0];
        
		xEnableDrag(this.mapRangeBox,null,this._mapRangeBoxDragEvent.bind(this),this._mapRangeBoxDragEndEvent.bind(this));	
		
		xWidth(this.mapBox,this.parameter.width);
		xHeight(this.mapBox,this.parameter.height);
		xWidth(this.mapRangeBox,this.parameter.rangeWidth);
		xHeight(this.mapRangeBox,this.parameter.rangeHeight);	 
	 }
	 this._initFrame();
}

var GridMapFactory = new Object();
GridMapFactory.createMap = function(container){
	var obj = new Object();
	obj.container = container;
	obj.map = new GridMap(container);
	obj._mapMoveEnd = function(map){
		var left = -Math.ceil(xLeft(map.layerContainer)*xWidth(this.miniMap.mapBox)/xWidth(map.layerContainer));
		var top = -Math.ceil(xTop(map.layerContainer)*xHeight(this.miniMap.mapBox)/xHeight(map.layerContainer));
		this.miniMap.moveTo(left,top);	
	}
	obj.map.onDragEnd = obj._mapMoveEnd.bind(obj);
	obj._mapDisplay = function(map){
	
	}
	obj.map.onDisplay = obj._mapDisplay.bind(this);

	var rootWidth = xWidth(obj.map.container);
	var rootHeight = xHeight(obj.map.container);
	var layerWidth = xWidth(obj.map.layerContainer);
	var layerHeight = xHeight(obj.map.layerContainer);
	var zoomLevel = xWidth(obj.map.layerContainer) / xWidth(obj.map.container);
	var width = 50;
	var height = Math.ceil((layerHeight * width) / layerWidth);
	var rangeWidth = Math.ceil( width / zoomLevel);
	var rangeHeight = Math.ceil((rootHeight * rangeWidth) / rootWidth);
    var miniMapParameter = {
        width:width,
        height:height,
        rangeWidth:rangeWidth,
        rangeHeight:rangeHeight,
        imgSrc:"test.gif"    
    }
	obj.miniMap = new GridMiniMap(container,miniMapParameter);
	obj._miniMapRangeChange = function(mini){
	    var left = Math.ceil( -(xLeft(mini.mapRangeBox) *  xWidth(this.map.layerContainer)) / xWidth(mini.mapBox));
		var top =  Math.ceil( -(xTop(mini.mapRangeBox) * xHeight(this.map.layerContainer)) / xHeight(mini.mapBox));
	    this.map.moveTo(left,top);
	}
	obj.miniMap.onRangeChange = obj._miniMapRangeChange.bind(obj);

	obj.moveUp = function(){this.map.moveUp();this._mapMoveEnd(this.map);}
	obj.moveDown = function(){this.map.moveDown();this._mapMoveEnd(this.map);}
	obj.moveLeft = function(){this.map.moveLeft();this._mapMoveEnd(this.map);}
	obj.moveRight = function(){this.map.moveRight();this._mapMoveEnd(this.map);}
	obj.moveCenter = function(){this.map.moveCenter();this._mapMoveEnd(this.map);}
    obj.zoomIn = function(level){this.map.zoomIn(level);}
    obj.zoomOut = function(level){this.map.zoomOut(level);}
    obj.zoomReset = function(){this.map.zoomReset();}
    obj.changeImage = function(src,wid,hei){
         this.map.changeImage(src,wid,hei); 
         var tw= 80;
         var th = 80;      
         if(wid>hei){
             th = Math.ceil(tw*hei/wid);
         }else if(hei>wid){
             tw = Math.ceil(th*wid/hei);
         }
         this.miniMap.changeImage(src,tw,th);
    }
    obj.moveCenter();
	return obj;
}

GridMapFactory.createMap2 = function(container){
	var obj = new Object();
	obj.container = container;
	obj.map = new GridMap(container);
	obj._mapMoveEnd = function(map){}
	obj.map.onDragEnd = obj._mapMoveEnd.bind(obj);
	obj._mapDisplay = function(map){}
	obj.map.onDisplay = obj._mapDisplay.bind(this);

	var rootWidth = xWidth(obj.map.container);
	var rootHeight = xHeight(obj.map.container);
	var layerWidth = xWidth(obj.map.layerContainer);
	var layerHeight = xHeight(obj.map.layerContainer);
	var zoomLevel = xWidth(obj.map.layerContainer) / xWidth(obj.map.container);

	obj.moveUp = function(){this.map.moveUp();this._mapMoveEnd(this.map);}
	obj.moveDown = function(){this.map.moveDown();this._mapMoveEnd(this.map);}
	obj.moveLeft = function(){this.map.moveLeft();this._mapMoveEnd(this.map);}
	obj.moveRight = function(){this.map.moveRight();this._mapMoveEnd(this.map);}
	obj.moveCenter = function(){this.map.moveCenter();this._mapMoveEnd(this.map);}
    obj.zoomIn = function(level){this.map.zoomIn(level);}
    obj.zoomOut = function(level){this.map.zoomOut(level);}
    obj.zoomReset = function(){this.map.zoomReset();}
    obj.changeImage = function(src,wid,hei){
         this.map.changeImage(src,wid,hei); 
    }
    obj.moveCenter();
	return obj;
}


//view
GridMapFactory.createViewMap = function(container){
	var obj = GridMapFactory.createMap(container);
    obj.zoomIn = function(level){this.map.zoomIn(level); }
    obj.zoomOut = function(level){this.map.zoomOut(level); }
    obj.moveCenter();
	return obj;
}
