/** Trida pro zobrazeni mapy
* @author Jaroslav Sevcik <jaroslav.sevcik@stringdata.cz>
* @abstract Trida se stara o zobrazeni mapy a ovladacich prvku pro jeji posun.
**/

/** trida suplijici associativni pole, !!!zatim se nepouziva a asi to bude dost pomaly!!! **/
function assocArray() {
	this.keys = new Array();
	this.values = new Array();
	this.count = 0;
	
	this.set = function(key, value) {
		this.keys[this.count] = key;
		this.values[this.count] = value;
		this.count++;
	}
	
	this.get = function(key) {
		alert(key);
		for(i = 0; i < this.count; i++) {
			if (this.keys[i] == key) {
				return this.values[i];
				break;
			}
		}
		return false;
	}
	
	this.keyExists = function(key) {
		var found = false;
		for(i = 0; i < this.count; i++) {
			if (this.keys[i] == key) found = true;
		}
		return found;
	}
//	alert('konstructor assoc array');
} // konec tridy assocArray


/** konstruktor mapoveho prohlizece 
 * stara se o nacteni vychozich ctvercu mapy, na to vola fci LoadVisibleImages
 * **/

function Map(displayWidth, displayHeight, partWidth, partHeight, partExt, mapPartPath, mapWidth, mapHeight, mapSize, imagePHP, near) {
	this.displayWidth = displayWidth; // sirka zobrazovaci oblasti px
	this.displayHeight = displayHeight; // vyska zobrazovaci oblasti px
	this.partWidth = partWidth; // sirka ctverce mapy px
	this.partHeight = partHeight; // vyska ctvetce mapy px
	this.partExt = partExt; // koncovka obrazku
	this.mapPartPath = mapPartPath; // cesta k obrazkum
	this.mapWidth = mapWidth; // sirka mapy v poctu ctvercu
	this.mapHeight = mapHeight; // vyska mapy v poctu ctvercu
	this.mapSize = mapSize; // jmeno velikosti mapy (predava se jako parametr pri zmene velikosti)
	this.imagePHP = imagePHP; // cesta k php, pres ktere se zobrazuji obrazky
	this.mapDiv = document.getElementById('mapa'); // pointer na div id="mapa"
	this.container = document.getElementById('container'); // pointer na div id="container"
	this.containerStyle = this.container.style; // container.style
	this.infoBox = document.getElementById('infoBox');
	this.imagesCount = 0;
	this.objects = new Array();
	this.nearObjects = new Array();
	this.near = near // vzdalenost v pixelech, ktera znaci je ne neco blizko
//	this.undo = new assocArray();
	this.nearObjectsIDs = new Array(); // pole objektu, ktere jsou zrovna aktivni
	this.oldNearObjectsIDs = new Array(); // pole objektu, ktere byly aktivni pred kliknutim do mapy (musime je zhasnout)
	this.descriptionVisible = 'true';  // POZOR, jelikoz fce get cookie vraci textove hodnoty, ukladame taktez textove hodnoty

	var tmp = getCookie('descriptionVisible');
	if (tmp != null) {
		this.descriptionVisible = tmp;
	}
//	alert(this.descriptionVisible);
	/** Zjisti souradnice obrazku, ktere maji byt na mape videt (jsou to fiktivni souradnice) 
	* vola render map, takze zajisti i prekresleni mapy
	*/
	this.loadVisibleImages = function() {
		var view_x = parseInt(this.mapDiv.scrollLeft);
		var view_y = parseInt(this.mapDiv.scrollTop);
		
		this.infoBox.innerHTML = "Aktualni souradnice stredu mapy "+view_x+"px : "+view_y+'px<br>Pocet aktivnich ctvercu: '+this.imagesCount;
		
		var fromCols = (Math.floor((view_x - this.displayWidth / 2) / this.partWidth ));
		var toCols = (Math.floor((view_x + this.displayWidth / 2) / this.partWidth));
		var fromRows = (Math.floor((view_y - this.displayHeight / 2)/ this.partHeight ));
		var toRows = (Math.floor((view_y + this.displayHeight / 2) / this.partHeight));
	
		this.renderMap(fromCols, toCols, fromRows, toRows);
	}

	/** posune mapu o x a y pixelu v horizontalnim a verticalnim smeru.
	 * prijma pochopitelne i zaporne hodnoty
	 * vola loadVisibileImages a tim se postara o vykresleni ctvercu ktere na mape muzou chybet 
	 */  
	this.mapMove = function(x, y) {
		var old_x = parseInt(this.mapDiv.scrollLeft);
		var old_y = parseInt(this.mapDiv.scrollTop);
		var new_x = old_x + parseInt(x);
		var new_y = old_y + parseInt(y);
		this.mapDiv.scrollLeft = new_x;
		this.mapDiv.scrollTop = new_y;
		setTimeout("Mapa.loadVisibleImages();", 100);
//		this.loadVisibleImages(new_x, new_y); // prekresleni ctvercu mapy
	}
	
	/** prida obrazek na zadane souradnice **/
	this.addImage = function(colNum, rowNum) {
		// pokud je jiz obrazek vykreslen, nebo je mimo mapu, tak ho nekreslime
		if (this.isRenderedImage(colNum, rowNum) || (colNum < 0 || colNum > this.mapWidth || rowNum < 0 || rowNum >  this.mapHeight)) {
			return;
		} else {
			/* verze s pouzitim DOM */			
			var positionLeft = colNum * this.partWidth;
			var positionTop = rowNum * this.partHeight;
			var imgStyle = 'position: absolute; left: '+positionLeft+'px; top: '+positionTop+'px;';
			
			var newImage = document.createElement("img");
			newImage.setAttribute('src', this.getImageUrl(colNum, rowNum));
			newImage.setAttribute('id', 'part_'+colNum+'_'+rowNum);
			newImage.setAttribute('width', this.partWidth);
			newImage.setAttribute('height', this.partHeight);
			newImage.style.cssText = imgStyle;
			this.container.appendChild(newImage);
			this.imagesCount++;
		}
	}
	
	/** Renderuje mapu, vstupem jsou souradnice (cisla) ctvercu, takze napr 1,1,3,3 vykresli ctverec o strane 3 **/
	this.renderMap = function(fromCols, toCols, fromRows, toRows) {
		//alert("Render: "+fromCols+' '+toCols+' '+fromRows+' '+toRows);
		for(rowNum = fromRows; rowNum < toRows + 1; rowNum++) {
			for(colNum = fromCols; colNum < toCols + 1; colNum++) {
				this.addImage(colNum, rowNum);
			}
		}
	}
	
	/** funkce pro sestaveni jmena obrazku na zaklade souradnic **/
	this.getImageUrl = function(colNum, rowNum) {
	    // tady je podminka jen pro jistotu
		if (colNum < 0 || colNum > this.mapWidth || rowNum < 0 || rowNum >  this.mapHeight) { // kontrola, zdali je obrazek platny
			return 'default';
		} else {
			//alert('image.php?img=' + escape(this.mapPartPath + 'm_' + colNum + "x"+ rowNum + this.partExt));
			return  this.imagePHP + '?img=' + escape(this.mapPartPath + 'm_' + colNum + "x"+ rowNum + this.partExt);
		}
	}
	
	/** kontroluje, zdali byl obrazek na zadanych souradnicich jiz vykreslen **/
	this.isRenderedImage = function (x,y) {
		return document.getElementById("part_"+x+"_"+y);
	}
	
	/** Zoom, zmena layeru **/
	this.ChangeLayer = function(layer) {
		document.forms['changeLayer'].elements['mapLayer'].value = layer;
		document.forms['changeLayer'].elements['mapSize'].value = this.mapSize;
		document.forms['changeLayer'].elements['px_x'].value = parseInt(this.mapDiv.scrollLeft);
		document.forms['changeLayer'].elements['px_y'].value = parseInt(this.mapDiv.scrollTop);
		document.forms['changeLayer'].submit();
	}
	
	/** zmena velikosti mapy **/
	this.changeSize = function(size) {
		document.forms['changeLayer'].elements['mapLayer'].value = document.forms['changeLayer'].elements['oldMapLayer'].value;
		document.forms['changeLayer'].elements['mapSize'].value = size;
		document.forms['changeLayer'].elements['px_x'].value = parseInt(this.mapDiv.scrollLeft);
		document.forms['changeLayer'].elements['px_y'].value = parseInt(this.mapDiv.scrollTop);
		document.forms['changeLayer'].submit();
	}
	/* nasmerujeme mapu na dane souradnice v pixelech */
	this.pointTo = function(x,y) {
		this.mapDiv.scrollTop = parseInt(y);
		this.mapDiv.scrollLeft = parseInt(x);
		
	}

	/** nacteni informaci o objektech od javascriptu **/	
	this.loadObjectsInfo = function() {
		var mylist=document.getElementById("objects");
		var x = 0;
		var y = 0;
		var objectCount = 0;
		var hlaska = "";
		for (i=0; i<mylist.childNodes.length; i++){
			if (mylist.childNodes[i].nodeName=="DIV"){
				var tmp = mylist.childNodes[i].childNodes[0].style;
				x = Math.round((parseInt(mylist.childNodes[i].style.left) + parseInt(tmp.width) / 2));
				y = Math.round((parseInt(mylist.childNodes[i].style.top) + parseInt(tmp.height) / 2));
				desc = mylist.childNodes[i].childNodes[1].innerHTML;
				this.objects[objectCount++] = new Array(mylist.childNodes[i].id,x,y,desc);
			}
		}
	}
	
	/** kontrola, zdali jsme v blizkosti nejakeho objektu **/
	this.checkNearObject = function(posX, posY) {
		this.nearObjects = Array();
		this.oldNearObjectsIDs = this.nearObjectsIDs;
		this.nearObjectsIDs = Array();
		var found = false;
		var distance = 0;
		for(i=0; i < this.objects.length; i++) {
			// spocitame vzdalenost podle pythagorovi vety
			distance = Math.sqrt(Math.abs((this.objects[i][1] - posX) * (this.objects[i][1] - posX) + (this.objects[i][2] - posY) * (this.objects[i][2] - posY)));
			if (distance < this.near) { // objekt je blizko
				found = true;
				this.nearObjects.push(i); // ulozime si index v poli objects
				this.nearObjectsIDs.push(this.objects[i][0]); // a ulozime si i ID
			} 
		}
		this.markObjects();
		return found;
	}
	
	/** akce, ktera se provede po kliknuti v blizkosti nejakeho objektu **/
	this.nearClick = function(posX, posY) {
		this.mapObjectInfo = document.getElementById('mapObjectInfo'); // 
		var hlaska = "";
		for(i=0; i < this.nearObjects.length; i++) {
			hlaska += "\n<p>"+this.objects[this.nearObjects[i]][3]+"</p>";
		}
		this.mapObjectInfo.innerHTML = hlaska;
	}
	
	/** oznaci blizke objekty, vstupen je pole indexu this.objects, ktere maji byti zvyrazneny
	 ** fce predpoklada, ze objekty ktere se maji zvyraznit jsou ulozeny v poli nearObjectsIDs, 
	 ** objekty, ktere jsou aktualne zvyrazneny a maji zhasnout jsou v poli oldNearObjectsIDs **/
	this.markObjects = function() {
		var objID;
//		alert('old boys: '+this.oldNearObjectsIDs+'\nnew: '+this.nearObjectsIDs);
		for(i = 0; i < this.oldNearObjectsIDs.length; i++) {
			this.lowLight(this.oldNearObjectsIDs[i]); // zhasneme ostatni objekty
		}
		for(i = 0; i < this.nearObjectsIDs.length; i++) {
			this.highLight(this.nearObjectsIDs[i]);
		}
	}
	
	/** verejne pristupna fce, ktera zpusobi rozsiceni urciteho objektu **/
	this.markObj = function(objID) {
		this.oldNearObjectsIDs = this.nearObjectsIDs;
		this.nearObjectsIDs = Array(objID);
		this.markObjects();
/*		for(i=0; i < this.objects.length; i++) {
			if (this.objects[i][0] == objID) {
				this.highLight(this.objects[i][0]); // posleme id objektu
			} else {
				this.lowLight(this.objects[i][0]); // zhasneme ostatni objekty
			}
		}*/
	}
	// nastavi objektu vyraznejsi barvu
	this.highLight = function(objID) {
		// zmenime z index
		var style = document.getElementById(objID).style;
	//	this.undo.set('zindex_'+objID, style.zIndex);
		style.zIndex = 15;
		
		// a zmenime src obrazku, pridame parametr highlight, php uz se s tim poradi
		var e = document.getElementById(objID).childNodes[0].id;
		var img = document.getElementById(e);
		img.src += '&highlight=1';
	}

	this.lowLight = function(objID) {
		var e = document.getElementById(objID).childNodes[0].id;
		var img = document.getElementById(e);
		var style = document.getElementById(objID).style;
		var pos = img.src.indexOf('&highlight=1');
		if (pos != -1) {
			img.src = img.src.substring(0, pos);
		}
		style.zIndex = 9;
	}
	
	/** zobrazuje a skryva popisky k objektum 
	* parametr init pokud je nastaven na 1, zpusobi to, ze jen dojde k zobrazeni stavu, ktery je ulozen v cookies
	* pokud neni zadan, dojde ke zmene stavu (coz je funkcnost tlacitka 'popisky'
	**/
	this.showDescription = function(init) {
		var e;
		var id;
		var theRules = new Array();
		if (document.styleSheets[1].cssRules)
			theRules = document.styleSheets[1].cssRules
		else if (document.styleSheets[1].rules)
			theRules = document.styleSheets[1].rules
		
		if (!init) { // pokud se nejedna o inicializaci popisek, zmeni stav zobrazeni popisek
			if (this.descriptionVisible == 'true') // budem objekty schovavat
				this.descriptionVisible = 'false';
			else
				this.descriptionVisible = 'true';
		}
		
		// podle toho jaky je stav, (ne)zobrazime popisky
		if (this.descriptionVisible == 'true') { // budem objekty schovavat
			theRules[theRules.length-1].style.display = 'block';
		} else {
			theRules[theRules.length-1].style.display = 'none';
		}
		
		// a novy stav ulozime do cookie
		setCookie('descriptionVisible', this.descriptionVisible);
	}
	
	/************** KONSTRUCTOR ***************/
	/* je to az tady, jelikoz funkce jsou volat az v momente, kdy byly definovany */
	this.loadVisibleImages(); // vykreslime visitelne ctverce mapy
	this.loadObjectsInfo(); // ziskame informace o objektech
	this.container.onclick = mapClick; // priradime event handler pro container
	this.showDescription(1); // poresi, zdali se maji zobrazit popisky ci nikoliv
	
} /** Konec tridy Map **/


/****************** obecne funkce, daji se volat odkudkoliv ***********/
	/** Handler eventu click **/
	function mapClick(e){
		var posx = 0;
		var posy = 0;
		if (!e) var e = window.event;
		if (e.pageX || e.pageY)
		{
			posx = e.pageX;
			posy = e.pageY;
		}
		else if (e.clientX || e.clientY)
		{
			posx = e.clientX + document.body.scrollLeft;
			posy = e.clientY + document.body.scrollTop;
		}
		var mapDiv = document.getElementById('mapa');
		var cont = document.getElementById('container');
		var resArr = getTotaloffset('container');
		posx = posx - resArr[0] + mapDiv.scrollLeft;
		posy = posy - resArr[1] + mapDiv.scrollTop;

		res = Mapa.checkNearObject(posx, posy);
		if (!res) {
			Mapa.pointTo(posx, posy); 
		} else {
			Mapa.nearClick(posx,posy);
		}
	}
	
	/** funkce pro ziskani aktualniho odsazeni elementu na strance **/
	function getTotaloffset(id){
		totalX = document.getElementById(id).offsetLeft;
		totalY = document.getElementById(id).offsetTop;
		var deep = 0;
		while(id = document.getElementById(id).offsetParent.id) {
			deep++;
			//alert(id);
			totalX += document.getElementById(id).offsetLeft;
			totalY += document.getElementById(id).offsetTop;
			if (deep == 2) {
				totalY += 92; // tato cislo vzniklo manualni kalibraci
				totalX += 8; // a todle taky, je mozne odkomentovat v class.maps.php
			}
		}
		return new Array(totalX, totalY);
	}
	
	function setCookie(name, value, expires, path, domain, secure) {
	  var curCookie = name + "=" + escape(value) +
	      ((expires) ? "; expires=" + expires.toGMTString() : "") +
	      ((path) ? "; path=" + path : "") +
	      ((domain) ? "; domain=" + domain : "") +
	      ((secure) ? "; secure" : "");
	  document.cookie = curCookie;
	}	
	function getCookie(name) {
	  var dc = document.cookie;
	  var prefix = name + "=";
	  var begin = dc.indexOf("; " + prefix);
	  if (begin == -1) {
	    begin = dc.indexOf(prefix);
	    if (begin != 0) return null;
	  } else
	    begin += 2;
	  var end = document.cookie.indexOf(";", begin);
	  if (end == -1)
	    end = dc.length;
	  return unescape(dc.substring(begin + prefix.length, end));
	}	

