var step = {
	ZoomW : 0,
	ZoomH : 0,
	Move : 0,
	Slider : 0
}


function mapDescription(src){
	this.src = src;
};


function mapObject(id,  tag, src, width, height, left, top, title, description, onclickFunc){
	this.height = 0;
	this.width = 0;
	this.top = top;
	this.left = left;
	this.imgW = 0;
	this.imgH = 0;
	this.src = src;
	
	this.init = function(imgW, imgH){
		this.imgH = imgH;
		this.imgW = imgW;
	};
	
	this.getTag = function(currW, currH){ 
		this.makeZoom(currW, currH);
		var style = 'top: ' + this.top + 'px; left: ' + this.left + 'px; height: ' + this.height + 'px; width: ' + this.width + 'px; ';
		if(onclickFunc != '')
			var event = " onclick = \"javascript: " + onclickFunc + "\" "; 
		else if(description != '')
			var event = " onclick = \"javascript: Map.loadDescription('" + description + "');\" ";
		if(title != '')
			var titleO = " title = '" + title + "' ";
		if(tag == 'img')
			var objectTag = '<img src = "' + src + '" id = "' + id + '" class = "MapObject" style = "' + style + '" ' + event + titleO + ' />';
		else if(tag == 'div')
			var objectTag = '<div id = "' + id + '" class = "MapObject" style = "' + style + 'font-size: ' + this.height + 'px;" ' + event + titleO + '>' + src + '</div>';
		return objectTag;
	};
	
	this.updateSrc = function(srcUpd){
		if(document.getElementById(id) != null){
			this.src = srcUpd;
			if(tag == 'img')
				document.getElementById(id).src = srcUpd;
			else if(tag == 'div')
				document.getElementById(id).innerHTML = srcUpd;
		}
	};

	this.updateTitle = function(srcTitle){
		if(document.getElementById(id) != null){
			//this.title = srcTitle;
			document.getElementById(id).title = srcTitle;
		}
	};
	
	this.zoom = function(currW, currH){
		this.makeZoom(currW, currH);
		this.loadZoom();
	};
	
	this.makeZoom = function(currW, currH){
		this.width = currW * width / this.imgW;
		this.height = currH * height / this.imgH;
		this.top = currH * top / this.imgH;
		this.left = currW * left / this.imgW;
	};
	
	this.loadZoom = function(){
		document.getElementById(id).style.width = Math.round(this.width) + 'px';
		document.getElementById(id).style.height = Math.round(this.height) + 'px';
		document.getElementById(id).style.top = Math.round(this.top) + 'px';
		document.getElementById(id).style.left = Math.round(this.left) + 'px';
		if(tag == 'div')
			document.getElementById(id).style.fontSize = Math.round(this.height) + 'px';
	};

};

var Map = {
	id: 'map',
	//scale = 1,
	startWidth : 1000,
	startHeight : 1000,
	startTop : 0,
	startLeft : 0,
	width : 1000,
	height : 1000,
	top : 0,
	left : 0,
	mapClass : 'MapDiv',
	mapImgClass : 'MapImage',
	containerWidth : 800,
	containerHeight : 600,
	containerClass : 'MapContainer',
	image : 0,
	sliderTop : 0,
	zoombarLength : 143,
	grid : 0,
	mapObjects : new Array(),
	//idMapObject : 0,
	
	init : function(src){
		var div = "<div id = 'mapDiscription'></div>";
		div += "<div class = '" + this.containerClass + "' id = '" + this.containerClass + "'>";
		div += "<div id = 'loadingMap' class = 'MapLoading'>Loading map...</div>";
		div += "<div class='MapNavigator'>";
		div += "	<div class='up' onclick = 'javascript: Map.moveDown();'><!-- --></div>";
		div += "	<div class='down' onclick = 'javascript: Map.moveUp();'><!-- --></div>";
		div += "	<div class='left' onclick = 'javascript: Map.moveRight();'><!-- --></div>";
		div += "	<div class='right' onclick = 'javascript: Map.moveLeft();'><!-- --></div>";
		div += "	<div class='default' onclick = 'javascript: Map.zoomDefault();'><!-- --></div>";
		div += "	<div class='zoomin' onclick = 'javascript: Map.zoomIn();'><!-- --></div>";
		div += "	<div class='zoomout' onclick = 'javascript: Map.zoomOut();'><!-- --></div>";
		div += "	<div class='zoombar'><div class='slider' id='slider'><!-- --></div></div>";
		div += "</div>";
		div += "</div>";
		document.write(div);
		this.createImage(src);
		
	},
	
	stepInit : function(){
		this.grid = this.zoombarLength;
		step.Move = this.grid;
		step.ZoomW = (this.image.width - this.containerWidth) / this.grid;
		step.ZoomH = (this.image.height - this.containerHeight) / this.grid;
		step.Slider = this.zoombarLength / this.grid;
	},
	
	createImage : function(src){
		this.image = new Image();
		this.image.src = src;
		//this.image.onload = this.initImage(src);
		this.initImage(src);
	},
	
	initImage : function(src){ 
		if(!this.image.complete)
			window.setTimeout("Map.initImage('" + src + "')", 500);
		else{
			this.containerHeight = this.containerWidth * this.image.height / this.image.width;
			this.stepInit();
			this.changecss('.' + this.mapClass, 'width', Math.round(this.containerWidth) + 'px');
			this.changecss('.' + this.mapClass, 'height', Math.round(this.containerHeight) + 'px');
			this.changecss('.' + this.mapImgClass, 'width', Math.round(this.containerWidth) + 'px');
			this.changecss('.' + this.mapImgClass, 'height', Math.round(this.containerHeight) + 'px');
			this.changecss('.' + this.containerClass, 'width', Math.round(this.containerWidth) + 'px');
			this.changecss('.' + this.containerClass, 'height', Math.round(this.containerHeight) + 'px');
			this.width = this.startWidth = this.containerWidth; 
			this.height = this.startHeight = this.containerHeight;
			var tempInnerHTML = "<div id = '" + this.mapClass + "' class = '" + this.mapClass + "'><img src = '" + src + "' id = '" + this.id + "' class = '" + this.mapImgClass + "' />";
			for(var mapObj in this.mapObjects){
				this.mapObjects[mapObj].init(this.image.width, this.image.height);
				tempInnerHTML += this.mapObjects[mapObj].getTag(this.width, this.height); 
			}
			tempInnerHTML += '</div>';
			document.getElementById(this.containerClass).innerHTML = tempInnerHTML + document.getElementById(this.containerClass).innerHTML;
			
			Drag.init(document.getElementById(this.id));
			Drag.init(document.getElementById('slider'), true);
			this.changecss('.MapNavigator', 'visibility', 'visible');
			this.clearLoading();
		}
	},
	
	clearLoading : function(){
		if(document.getElementById('loadingMap') != null)
			document.getElementById('loadingMap').innerHTML = '';
	},
		
	zoomIn : function(stepSet){
		if (typeof stepSet == "undefined") 
			stepSet = 1;
		this.width += step.ZoomW * stepSet;
		this.height += step.ZoomH * stepSet;
		this.sliderTop += step.Slider * stepSet;
		
		if(this.width > this.image.width || this.height > this.image.height || this.sliderTop > this.zoombarLength){
			this.width = this.image.width;
			this.height = this.image.height;
			this.sliderTop = this.zoombarLength;
			stepSet = 0;
		}
		
		this.moveLeft(step.ZoomW * stepSet / 2);
		this.moveUp(step.ZoomH * stepSet / 2);
		
		this.changecss('.' + this.mapClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapImgClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapClass, 'height', Math.round(this.height) + 'px');
		this.changecss('.' + this.mapImgClass, 'height', Math.round(this.height) + 'px');
		
		this.changecss('.MapNavigator .zoombar .slider', 'top', Math.round(this.sliderTop) + 'px');
		
		for(var mapObj in this.mapObjects)
			this.mapObjects[mapObj].zoom(this.width, this.height); 
	},
	
	zoomOut : function(stepSet){
		if (typeof stepSet == "undefined") 
			stepSet = 1;
		this.width -= step.ZoomW * stepSet;
		this.height -= step.ZoomH * stepSet;
		this.sliderTop -= step.Slider * stepSet;
		
		if(this.width < this.startWidth || this.height < this.startHeight || this.sliderTop < 0){
			this.width = this.startWidth;
			this.height = this.startHeight;
			this.sliderTop = 0;
			stepSet = 0;
		}
		
		this.moveRight(step.ZoomW * stepSet / 2);
		this.moveDown(step.ZoomH * stepSet / 2);
		
		if(this.width + this.left < this.startWidth){
			this.moveRight(this.startWidth - (this.width + this.left));
		}
		
		if(this.height + this.top < this.startHeight){
			this.moveDown(this.startHeight - (this.height + this.top));
		}
		
		this.changecss('.' + this.mapClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapImgClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapClass, 'height', Math.round(this.height) + 'px');
		this.changecss('.' + this.mapImgClass, 'height', Math.round(this.height) + 'px');
		
		this.changecss('.MapNavigator .zoombar .slider', 'top', Math.round(this.sliderTop) + 'px');
		
		for(var mapObj in this.mapObjects)
			this.mapObjects[mapObj].zoom(this.width, this.height);
	},
	
	zoomDefault : function(){
		this.width = this.startWidth;
		this.height = this.startHeight;
		
		this.changecss('.' + this.mapClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapImgClass, 'width', Math.round(this.width) + 'px');
		this.changecss('.' + this.mapClass, 'height', Math.round(this.height) + 'px');
		this.changecss('.' + this.mapImgClass, 'height', Math.round(this.height) + 'px');
		this.left = 0;
		this.changecss('.' + this.mapClass, 'left', Math.round(this.left) + 'px');
		this.top = 0;
		this.changecss('.' + this.mapClass, 'top', Math.round(this.top) + 'px');
		this.sliderTop = 0;
		this.changecss('.MapNavigator .zoombar .slider', 'top', Math.round(this.sliderTop) + 'px');
		
		for(var mapObj in this.mapObjects)
			this.mapObjects[mapObj].zoom(this.width, this.height);
	},
		
	moveLeft : function(stepSet){ 
		if (typeof stepSet == "undefined") 
			stepSet = step.Move;
		this.left -= stepSet;
		if(this.width + this.left < this.startWidth)
			this.left = this.startWidth - this.width;
		this.changecss('.' + this.mapClass, 'left', Math.round(this.left) + 'px');
	},
	
	moveRight : function(stepSet){
		if (typeof stepSet == "undefined") 
			stepSet = step.Move;
		this.left += stepSet;
		if(this.left > 0){
			this.left = 0;
		}
		this.changecss('.' + this.mapClass, 'left', Math.round(this.left) + 'px');
	},
	
	moveUp : function(stepSet){
		if (typeof stepSet == "undefined") 
			stepSet = step.Move;
		this.top -= stepSet;
		if(this.height + this.top < this.startHeight)
			this.top = this.startHeight - this.height;
		this.changecss('.' + this.mapClass, 'top', Math.round(this.top) + 'px');
	},
	
	moveDown : function(stepSet){
		if (typeof stepSet == "undefined") 
			stepSet = step.Move;
		this.top += stepSet;
		if(this.top >= 0)
			this.top = 0;
		this.changecss('.' + this.mapClass, 'top', Math.round(this.top) + 'px');
	},
	
	addObject : function(idMapObject, tag, src, width, height, left, top, title, description, onclickFunc){
		this.mapObjects[idMapObject] = new mapObject(idMapObject, tag, src, width, height, left, top, title, description, onclickFunc);
		//this.idMapObject ++;
	},
	
	changeSrcObject : function(idMapObject, src){
		this.mapObjects[idMapObject].updateSrc(src);
	},
	
	changeTitleObject : function(idMapObject, title){
		this.mapObjects[idMapObject].updateTitle(title);
	},
	
	loadDescription : function(description){
		document.getElementById('mapDiscription').innerHTML = description;
	},
	
	changecss : function (theClass,element,value) {

		 var cssRules;

		 var added = false;
		 for (var S = 0; S < document.styleSheets.length; S++){

	    if (document.styleSheets[S]['rules']) {
		  cssRules = 'rules';
		 } else if (document.styleSheets[S]['cssRules']) {
		  cssRules = 'cssRules';
		 } else {
		  //no rules found... browser unknown
		 }

		  for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) {
		   if (document.styleSheets[S][cssRules][R].selectorText == theClass) {
		    if(document.styleSheets[S][cssRules][R].style[element]){
		    document.styleSheets[S][cssRules][R].style[element] = value;
		    added=true;
			break;
		    }
		   }
		  }
		  if(!added){
		  try{
		  	document.styleSheets[S].insertRule(theClass+' { '+element+': '+value+'; }',document.styleSheets[S][cssRules].length);

		  } catch(err){
		  		try{document.styleSheets[S].addRule(theClass,element+': '+value+';');}catch(err){}

		  }
		  }
		 }
		}
};


var Drag = {

		obj : null,

		init : function(o, slider, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
		{
			o.slider = slider == null ? false : slider;
			
			o.onmousedown	= Drag.start;

			o.hmode			= bSwapHorzRef ? false : true ;
			o.vmode			= bSwapVertRef ? false : true ;

			o.root = oRoot && oRoot != null ? oRoot : o ;

			//if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
			//if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
			//if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
			//if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
			if (o.hmode  && isNaN(parseInt(Drag.left  ))) Drag.left   = 0;
			if (o.vmode  && isNaN(parseInt(Drag.top   ))) Drag.top    = 0;
			if (!o.hmode && isNaN(parseInt(Drag.right ))) Drag.right  = 0;
			if (!o.vmode && isNaN(parseInt(Drag.bottom))) Drag.bottom = 0;

			o.minX	= typeof minX != 'undefined' ? minX : null;
			o.minY	= typeof minY != 'undefined' ? minY : null;
			o.maxX	= typeof maxX != 'undefined' ? maxX : null;
			o.maxY	= typeof maxY != 'undefined' ? maxY : null;

			o.xMapper = fXMapper ? fXMapper : null;
			o.yMapper = fYMapper ? fYMapper : null;

			o.root.onDragStart	= new Function();
			o.root.onDragEnd	= new Function();
			o.root.onDrag		= new Function();
		},

		start : function(e)
		{
			var o = Drag.obj = this;
			e = Drag.fixE(e);
			//var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
			//var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
			//alert(Drag.top+'  : '+Drag.bottom+' : '+Drag.left+' : '+Drag.right);
			var y = parseInt(o.vmode ? Drag.top  : Drag.bottom);
			var x = parseInt(o.hmode ? Drag.left : Drag.right );
			//alert(x + '/' + y);
			o.root.onDragStart(x, y);

			o.lastMouseX	= e.clientX;
			o.lastMouseY	= e.clientY;

			if (o.hmode) {
				if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
				if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
			} else {
				if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
				if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
			}

			if (o.vmode) {
				if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
				if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
			} else {
				if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
				if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
			}

			document.onmousemove	= Drag.drag;
			document.onmouseup		= Drag.end;
			
			return false;
		},

		drag : function(e)
		{
			e = Drag.fixE(e);
			var o = Drag.obj;

			var ey	= e.clientY;
			var ex	= e.clientX;
			//var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
			//var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
			var y = parseInt(o.vmode ? Drag.top  : Drag.bottom);
			var x = parseInt(o.hmode ? Drag.left : Drag.right );
			var nx, ny;

			if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
			if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
			if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
			if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

			//nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
			//ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
			
			nx = ex - o.lastMouseX;
			ny = ey - o.lastMouseY;

			if (o.xMapper)		nx = o.xMapper(y)
			else if (o.yMapper)	ny = o.yMapper(x)

			//Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
			//Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
			//alert(o.slider + '/' + o);
			if(o.slider){
				//alert(nx + '/' + ny);
				if(ny > 0)
					Map.zoomIn(ny);
				else if(ny < 0)
					Map.zoomOut(ny * -1);
			}else{
				if(o.hmode){
					if(nx < 0){ //alert('l:'+nx);
						if(Drag.left != nx){
							Map.moveLeft(nx * -1);
							Drag.left = nx;
						}
					} else if(nx > 0){ //alert('r:'+nx);
						if(Drag.right != nx){
							Map.moveRight(nx);
							Drag.right = nx;
						}
					}
				}
				if(o.vmode){ //alert('u:'+ny);
					if(ny < 0){
						if(Drag.top != ny){
							Map.moveUp(ny * -1);
							Drag.top = ny;
						}
					}else if(ny > 0){
						if(Drag.bottom != ny){
							Map.moveDown(ny);
							Drag.bottom = ny;
						}
					}
				}
			}
			
			Drag.obj.lastMouseX	= ex;
			Drag.obj.lastMouseY	= ey;

			Drag.obj.root.onDrag(nx, ny);
			return false;
		},

		end : function()
		{
			document.onmousemove = null;
			document.onmouseup   = null;
			//Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
			//							parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
			Drag.obj.root.onDragEnd(	Drag.obj.hmode ? Drag.left : Drag.right, 
										Drag.obj.vmode ? Drag.top : Drag.bottom);
			
			Drag.obj = null;
		},

		fixE : function(e)
		{
			if (typeof e == 'undefined') e = window.event;
			if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
			if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
			return e;
		}
	};
