// globalni promenne
var gMapName = "map";
var gGroupName = "group";
var gFilterName = "filter";
var gLegendName = "legend";
var gProjectFilterName = "project_filter";
var gUnitFilterName = "unit_filter";
var gStatesName = "states";

// ITEM
// objekt jednoho markeru (projekt nebo unita)
// reprezentuje jednotlivy projekt nebo unitu
function Item(marker, id, name, description, type, pPictureUrl)
{
	this.marker = marker;
	this.id = id;
	this.name = name;
	this.description = description;
	this.type = type; // -1 = project, 0-5 = unity
	this.pictureUrl = pPictureUrl;

	this.isProject = this.type == "project";
}


// LAYER
// objekt vrstvy projektu//
// reprezentuje jednu oblast na mape, ve ktere jsou obsazeny markery projektu
function Quadrant(zero)
{
	this.content = new Array(); // pole entit (projektu nebo unit - typu Item) v teto vrstve
	this.zero = zero; // souradnice leveho spodniho rohu (s, w) - kvuli identifikaci vrstvy, typu GlanLng
}

Quadrant.prototype.show = function() {
    // zobrazeni vsech markeru
    for (var i = 0; i < this.content.length; i++) {
        if (this.content[i].isProject) {
            if (Filter.showProjects) {
                Map.map.addOverlay(this.content[i].marker);
            }
        } else {
            if (Filter.showUnits) {
                if (Filter.showUnitGroup == -1 || this.content[i].type == Filter.showUnitGroup) {
                    Map.map.addOverlay(this.content[i].marker); // pokud se skupina shoduje nebo je nastavena na vsechny
                }
            }
        }
    }
}

Quadrant.prototype.hide = function()
{
	// skryti vsech markeru
	for (var i=0; i<this.content.length; i++)	{
		Map.map.removeOverlay(this.content[i].marker);
	}
}

Quadrant.prototype.addItem = function(pLat, pLng, pId, pName, pDescription, pUnitType, pThumbUrl) {
	var icon = new GIcon();

	if (gEnableCustomIcons || pUnitType == "project") {
		icon.image = gImagesRoot + "img/googlemaps/marker_" + pUnitType + ".png";
	} else {
		icon.image = gImagesRoot + "img/googlemaps/marker_Other.png";
	}

	icon.shadow = gImagesRoot + "img/googlemaps/shadow.png";
	icon.iconSize = new GSize(21, 34);
	icon.shadowSize = new GSize(48, 34);
	icon.iconAnchor = new GPoint(11, 34);
	icon.infoWindowAnchor = new GPoint(11, 1);

	var marker = new GMarker(new GLatLng(pLat, pLng), icon);

	var lItem = new Item(marker, pId, pName, pDescription, pUnitType);

	GEvent.addListener(marker, "click", function() {
		var lInfoContent = "<div class=\"infoContent\">";
		if (lItem.isProject) {
			lInfoContent += "<a href=\"ProjectView.aspx?projectID=" + lItem.id + "\" class=\"infoContentTitle\">" + lItem.name + "</a>";
		} else {
			lInfoContent += "<a href=\"UnitView.aspx?rt=/application/Pages/Maps.aspx&amp;unitID=" + lItem.id + "\" class=\"infoContentTitle\">" + lItem.name + "</a>";
		}
		if (lItem.isProject && Map.unitQuadrantList.isNeedToZoom()) {
			lInfoContent += " | <a style=\"cursor: pointer; cursor: hand;\" onclick=\"Map.moveToDefaultUnitZoom(" + pLat + ", " + pLng + ")\">" + Translation.getText("ZoomToArea") + "</a>";
		}
		lInfoContent += "<br/>";
		if (lItem.isProject && pThumbUrl != "") {
			lInfoContent += '<img src="' + pThumbUrl + '" alt="" align="left" width="60" height="45" style="margin-right: 5px; margin-top: 5px;" />';
		}
		if (pDescription) {
			lInfoContent += lItem.description;
		}

		lInfoContent += "</div>";

		lItem.marker.openInfoWindowHtml(lInfoContent);
	});

	this.content[this.content.length] = lItem;

	return this.content.length;
}


// LAYERLIST
// objekt seznamu vrstev
// reprezentuje seznam vsech aktualne nactenych oblasti (vrstev)
function QuadrantList(maxSize, isProject, quadrantWidth, quadrantHeight, defaultZoom) {
	this.content = new Array(); // pole jednotlivych vrstev
	this.size = 0;
	this.MAXSIZE = maxSize;
	this.actBegin = 0;
	
	this.isProject = isProject;

	this.quadrantWidth = quadrantWidth; // sirka jedne oblasti pro projekty/unity (ve stupnich)
	this.quadrantHeight = quadrantHeight; // vyska jedne oblasti pro projekty/unity

	this.defaultZoom = defaultZoom; // zalezi na velikosti viewportu, hodne opatrne s tim, v podstate ovlivnije nutnou maximalni velikost fronty
}

QuadrantList.prototype.isNeedToZoom = function() {
	return (Map.map.getZoom() < this.defaultZoom)
}

// nacte data a ulozi si je do sebe
QuadrantList.prototype.loadItems = function(data, pZero) {
	var lXml = GXml.parse(data);

	var lActIndex = this.addQuadrantByParam(pZero); // prida vrstvu do zaznamu

	var lTagName;
	if (this.isProject) lTagName = "project";
	else lTagName = "unit";

	var lItems = lXml.documentElement.getElementsByTagName(lTagName);

	for (var i=0; i<lItems.length; i++) {
		var lLat = parseFloat(lItems[i].getAttribute("lat")); 
		var lLng = parseFloat(lItems[i].getAttribute("lng"));
		var lId = parseInt(lItems[i].getAttribute("id"));
		var lName = lItems[i].getAttribute("name");
		var lDescription = lItems[i].getAttribute("description");
		var lUnitType = lItems[i].getAttribute("type");
		var lPictureUrl = lItems[i].getAttribute("pictureUrl");

		if (this.isProject) lUnitType = "project";
		this.content[lActIndex].addItem(lLat, lLng, lId, lName, lDescription, lUnitType, lPictureUrl);	
	}

	this.content[lActIndex].show();
}

// pridava vytvorenou vrstvu, vraci pod jakym indexem pridala novy quadrant
QuadrantList.prototype.addQuadrant = function(pQuadrant) {
	var lResult;
	
	if (this.size<this.MAXSIZE) { // jeste se tam vejde
		this.content[this.size] = pQuadrant;
		lResult = this.size;
		this.size++;
	} else if (this.MAXSIZE != 0) { // uz se tam nevejde - fronta
		var oldQuadrant = this.content[this.actBegin];

		this.content[this.actBegin] = pQuadrant;
		lResult = this.actBegin;
		this.actBegin++;
		if (this.actBegin>=this.MAXSIZE) this.actBegin = 0;

		oldQuadrant.hide();
	}
	return lResult;
}

// vytvari novou vrstvu ze seznamu markeru a souradnic
QuadrantList.prototype.addQuadrantByParam = function(pZero)
{
	return this.addQuadrant(new Quadrant(pZero));
}

// pWanted je typu GlatLng
QuadrantList.prototype.findQuadrantByZero = function(pWanted) 
{
	var lResult = -1;
	for (var i=0; i<this.size; i++) { // fujky, predelat na nejake lepsi vyhledavani
		if (pWanted.lat() == this.content[i].zero.lat() && pWanted.lng() == this.content[i].zero.lng()) {
			lResult = i;
			break;
		}
	}
   return lResult;
}

// smaze vsechny vrstvy
QuadrantList.prototype.removeAll = function() {
	for (var i=0; i<this.size; i++) {
		this.content[i].hide();
		this.content[i] = 0;
	}
	this.size = 0;
}


// MAP
// shell okolo prace s mapou (handler pohnuti a pridruzene funkce (nacitani z databaze, aritmetika))
function Map() { }

Map.map; // reprezentace mapy
Map.projectQuadrantList; // seznam oblasti projektu
Map.unitQuadrantList;

Map.moveToDefaultUnitZoom = function(pLat, pLng) {
	if (this.unitQuadrantList.isNeedToZoom()) {
		this.map.setZoom(this.unitQuadrantList.defaultZoom); 
	}
	this.map.panTo(new GLatLng(pLat, pLng));
}

// handler pohnuti mapou
Map.moved = function() {
	var lBounds = this.map.getBounds();

	this.computeZeros(lBounds, this.projectQuadrantList); // projekty
	this.computeZeros(lBounds, this.unitQuadrantList); // unity
}

Map.zoomed = function() {
	Map.map.closeInfoWindow();
}

Map.computeZeros = function(pBounds, pQuadrantList) {
	var lMinX = pBounds.getSouthWest().lng();
	var lMinY = pBounds.getSouthWest().lat();
	var lMaxX = pBounds.getNorthEast().lng();
	var lMaxY = pBounds.getNorthEast().lat();
	
	// zjisti zeros aktualniho ctverce
	if (!pQuadrantList.isNeedToZoom()) {
		var lZeros;

		lZeros = this.getQuadrants(lMinX, lMaxX, lMinY, lMaxY, pQuadrantList.quadrantHeight, pQuadrantList.quadrantWidth);
		
		// prida vsechny nalezene ctverce
		for (var i = 0; i<lZeros.length; i++) {
			if (pQuadrantList.findQuadrantByZero(lZeros[i]) == -1) { // jeste nenacteny
				this.getMarkers(lZeros[i], pQuadrantList); // je mozne, ze prepise nejake jiz nactene - OPRAVIT!!!
			}
		}

		if (!pQuadrantList.isProject) Filter.show();
	} else {
		pQuadrantList.removeAll(); // vyrez je moc odzoomovany, smaze se
		
		if (!pQuadrantList.isProject) Filter.hide();
	}
}

Map.getQuadrants = function(pMinX, pMaxX, pMinY, pMaxY, pHeight, pWidth) {
	var lZeros = new Array();
	var lIndex = 0;

	for (var j = this.getQuadrantZero(pMinY, pMinX, pHeight, pWidth); j.lat() < pMaxY; j = new GLatLng(j.lat() + pHeight, j.lng() ) ) {
		for (var i = j; i.lng() < pMaxX; i = new GLatLng(i.lat(), i.lng() + pWidth) ) {
			lZeros[lIndex] = i;
			lIndex++;
		}
	}
	return lZeros;
}

Map.div = function(pNum, pStep)
{
	lModulo = pNum % pStep;
	if (lModulo < 0) lModulo = pStep + lModulo; // jsem v zapornych cislech => posouvam se na druhou stranu
	return (pNum - lModulo);

}

// vrati oblast, do ktere patri bod
Map.getQuadrantZero = function(pLat, pLng, pQuadrantHeight, pQuadrantWidth)
{

	var lLng = this.div(pLng, pQuadrantWidth);
	var lLat = this.div(pLat, pQuadrantHeight);
	var lZero = new GLatLng(lLat, lLng);
	return lZero;
}

// provede dotaz na databazi, naparsuje vysledne xmlko a vytvori zaznamy projektu a unit, zero je typu GLatLng, pProject je booleanovska promenna (true = nacitaji se projekty, false = nacitaji se unity)
Map.getMarkers = function(pZero, pQuadrantList)
{
	var lQuery = "../PagesPublic/MapDataGenerator.aspx";
	var lDefaultProj = pQuadrantList.isProject;
	var lDefaultUnit = !pQuadrantList.isProject;
	var lDefaultUGroup = -1;
	
	var quadrantHeight = pQuadrantList.quadrantHeight;
	var quadrantWidth = pQuadrantList.quadrantWidth;

	lQuery += "?s=" + pZero.lat();
	lQuery += "&w=" + pZero.lng();
	lQuery += "&n=" + (pZero.lat() + quadrantHeight);
	lQuery += "&e=" + (pZero.lng() + quadrantWidth);
	lQuery += "&proj=" + lDefaultProj;
	lQuery += "&unit=" + lDefaultUnit;
	lQuery += "&ugroup=" + lDefaultUGroup;
	lQuery += "&language=" + gCurrentCountry;
	
	//alert(lQuery);
	GDownloadUrl(lQuery, function (data, responseCode)
		{
			// neprovadi se synchronne, provadi se az ve chvili upesneho nacteni xml dokumentu
			if (pQuadrantList.findQuadrantByZero(pZero) == -1) { // jeste jednou overi zda je nenacteny (kvuli asynchonnosti tohoto handleru)
				pQuadrantList.loadItems(data, pZero);
			}
			// falesny kod pro IE (jinak pada;o)
			var lFake = new GMarker(new GLatLng(0,0));
			Map.map.addOverlay(lFake);
			Map.map.removeOverlay(lFake);
		});
}

// FILETR
// shell okolo filtrovani zobrazeni
function Filter() { }

Filter.showFilter = true; // zda se zobrazi filtrovani, zalezi na velikosti zoomu
Filter.showProjects = true; // zda se zobrazi projekty
Filter.showUnits = true;
Filter.showUnitGroup = -1; // jakou zobrazovat skupinu unit

Filter.setUnitGroup = function(pUnitType) {
    this.showUnitGroup = pUnitType;
	for (var i=0; i<Map.unitQuadrantList.size; i++) {
		Map.unitQuadrantList.content[i].hide();
		Map.unitQuadrantList.content[i].show();
	}
}

// nastavi filter na zobrazovani projektu a unit
Filter.set = function() {
	if (document.getElementById(gProjectFilterName).checked) {
		Filter.showProjects = true;
	} else {
		Filter.showProjects = false;
	}
	for (var i = 0; i < Map.projectQuadrantList.size; i++) {
		Map.projectQuadrantList.content[i].hide();
		Map.projectQuadrantList.content[i].show();
	}

	var lFilterByUnits = document.getElementById(gUnitFilterName).checked;

	this.showUnits = lFilterByUnits;
	for (var i = 0; i < gFilterControls.length; i++) {
		document.getElementById(gFilterControls[i]).disabled = !lFilterByUnits;
	}

	for (var i = 0; i < Map.unitQuadrantList.size; i++) {
		Map.unitQuadrantList.content[i].hide();
		Map.unitQuadrantList.content[i].show();
	}
}

Filter.show = function() {
	if (!this.showFilter) { // pokud jeste neni zobrazeno
		document.getElementById(gFilterName).style.display = "block";
		document.getElementById(gLegendName).style.display = "none";
		this.showFilter = true;
	}
}
Filter.hide = function() {
	if (this.showFilter) { // pokud je zobrazeno
		document.getElementById(gFilterName).style.display = "none";		
		document.getElementById(gLegendName).style.display = "block";
		this.showFilter = false;
	}
}

// MAIN
// pri nacteni stranky
function loadMap() {
	var lMapWidth = document.body.clientWidth - 313; // odecita okraje
	if (lMapWidth > 800 || !lMapWidth) lMapWidth = 800; // maximalni sirka
	var lMapHeight = lMapWidth * 0.618; // nasobime zlatym rezem;o)
	
	document.getElementById(gMapName).style.width = lMapWidth.toString() + "px";
	document.getElementById(gMapName).style.height = lMapHeight.toString() + "px";

	if (GBrowserIsCompatible()) {
		Map.map = new GMap2(document.getElementById(gMapName));

		// nastavi vychozi pozici a prida control widgety
		var lCurrentCountry;

		if (gCurrentCountry == "en") lCurrentCountry = Countries.GetCountry("uk");
		else lCurrentCountry = Countries.GetCountry(gCurrentCountry);

		Map.map.setCenter(new GLatLng(lCurrentCountry.latitude, lCurrentCountry.longitude), lCurrentCountry.zoom);
		Map.map.addControl(new GLargeMapControl());
		Map.map.addControl(new GMapTypeControl());

		// spocita
		var lBounds = Map.map.getBounds();
		var lViewportWidth = Math.abs(lBounds.getNorthEast().lng() - lBounds.getSouthWest().lng()); // sirka viewportu ve stupnich
		var lBlockWidth = Map.div(lViewportWidth + 1, 1); // spocita prvni vetsi cele cislo
		
		Map.projectQuadrantList = new QuadrantList(32, true, 10, 10, 6);
		Map.unitQuadrantList = new QuadrantList(32, false, 2, 2, 10);
		
		// init funkce
		State.load();
		Filter.set();
		Filter.setUnitGroup(-1);
		
		Map.moved();
		
		// pripoji handlery
		GEvent.addListener(Map.map, "moveend", function() { Map.moved(); });
		GEvent.addListener(Map.map, "zoomend", function(oldLevel, newLevel) { Map.zoomed(); });
	}
}


// STATE
function State() {}
State.moveTo = function(pCode)
{
	if (pCode != "none") {
		var lState = Countries.GetCountry(pCode);
		Map.map.setZoom(lState.zoom);
		Map.map.panTo(new GLatLng(lState.latitude, lState.longitude));
	}
}
State.load = function() {
	var lStates = Countries.GetList();
	var lContent = "";
	
	lContent += "<select onchange=\"State.moveTo(this.options[this.selectedIndex].value)\">\n";
	lContent += '<option value="none">' + Translation.getText("ChooseCountry") + '</option>';
	
	for (var i in lStates) 
	{
		lContent += "<option value=\"" + lStates[i].code + "\">" + lStates[i].name + "</option>\n";
	}
	lContent += "</select>\n";

	document.getElementById(gStatesName).innerHTML = lContent;
}

window.onload = loadMap;
window.onunload = GUnload;
