/*
   Copyright 2005-2006 Vladimir Koutny <vlado@blava.ksp.sk>
   
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version
   2 of the License, or (at your option) any later version.


*/
	       
/*
 *  mapovy objekt
 */
var map;
var icon_ap, icon_client;
var net;

var networkName = "blava.net";
var mapURL = "data/blava.net.xml.php";
var defLon = 17.111;
var defLat = 48.126;
var defZoom = 12;
var selectedPoint = null;
var selectingAllowed = false;


// map resizing
var MAP_WIDTH_LARGE = 70;
var MAP_WIDTH_SMALL = 30;
var MapWidth = MAP_WIDTH_LARGE;

function createMarker(point,nazov) {
   var typ;
   if (nazov=="") typ = icon_client;
   else typ = icon_ap;
   var marker = new GMarker(point,typ);
   marker.tooltip = '<div class="tooltip">'+nazov+'</div>';
   if (typ==icon_ap) {
   GEvent.addListener(marker,"mouseover", function(){
	showTooltip(marker);
	});
   GEvent.addListener(marker,"mouseout", function(){
	tooltip.style.visibility="hidden";
	});
   }
   else {
	GEvent.addListener(marker,"click", function(){
	marker.openInfoWindowHtml("GPS: E"+point.lat()+" N"+point.lng());
	});
   }
   return marker;
   }

// tooltips - thanks to tubejp & Mike's tutorial
var tooltip = document.createElement("div");
tooltip.setAttribute("id","div_marker_tooltip");
tooltip.style.visibility="hidden";

function showTooltip(marker) {
    tooltip.innerHTML = marker.tooltip;
    var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
    var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),map.getZoom());
    var anchor=marker.getIcon().iconAnchor;
    var width=marker.getIcon().iconSize.width;
    var height=tooltip.clientHeight;
    var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y -height)); 
    pos.apply(tooltip);
    tooltip.style.visibility="visible";
}								

function coordNorm(v,scale) {
    scale=Math.pow(10,scale);
    return Math.round(v*scale)/scale;
}

function msg(txt) {
//    document.getElementByIt("msgs").firstChild.data=txt;
}

/* 
 * vyrob mapu, zakladne nastavenia
 */
function mapInit(element, mapType) {
    map = new GMap2(document.getElementById(element));


    // ====== Restricting the range of Zoom Levels =====
    // Get the list of map types      
    var mt = map.getMapTypes();
    // Overwrite the getMinimumResolution() and getMaximumResolution() methods
    for (var i=0; i<mt.length; i++) {
        // mt[i].getMinimumResolution = function() {return 11;}
        mt[i].getMaximumResolution = function() {return 18;}
    }

    map.addControl(new GLargeMapControl());
    map.addControl(new GScaleControl());
    map.addControl(new GMapTypeControl());
    map.getPane(G_MAP_FLOAT_PANE).appendChild(tooltip);
    
    map.setCenter(new GLatLng(defLat, defLon), defZoom);
    map.setMapType(mapType);
    
/*    GEvent.addListener(map, "click", function(overlay, point) {	
*		alert("You have clicked the map " +" E"+coordNorm(point.x,8)+" N"+coordNorm(point.y,8));
*    }); 
*/

}

/*
 * nastav stred mapy a zoom
 */
function mapCenter(point, zoom) {
    map.centerAndZoom(point, zoom);
}


function mapCreateIcon(url, w,h,ax,ay) {
    var icon = new GIcon();
    icon.image = url;
    icon.shadpw = null;
    // icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(w, h);
    // icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(ax, ay);
    icon.infoWindowAnchor = new GPoint(7, 7);
    
    return icon;
}


function netNode( xmlNode ) {
    this.point = new GLatLng( parseFloat( xmlNode.getAttribute("lat")),
    	    	    	      parseFloat( xmlNode.getAttribute("lon") ) );
    this.name = xmlNode.getAttribute( "name" );
    this.type = xmlNode.getAttribute("type");
    this.network = xmlNode.getAttribute("network");

    this.icon = icon_ap;
    if (this.type=="ap") this.icon=icon_ap;
    if (this.type=="client") this.icon=icon_client;
    
    this.marker = function() {
    	return new GMarker( this.point, this.icon );
    }
    
    this.addToMap = function( map ) {
	var marker = this.marker();
	var nets=this.network;
	var label=this.name;
	
        GEvent.addListener(marker, "click", function() {
	    marker.openInfoWindowHtml("<div class=\"floatinfo\">"+nets+"&nbsp;&ndash;&nbsp;<b>"+label+"</b><br>(N+"+coordNorm(marker.getPoint().lat(),5)+",&nbsp;E+"+coordNorm(marker.getPoint().lng(),5)+")</div>");
	});

	marker.tooltip = '<div class="tooltip">'+this.name+'</div>';
        GEvent.addListener(marker,"mouseover", function() {
	    showTooltip(marker);
	});
	GEvent.addListener(marker,"mouseout", function() {
	    tooltip.style.visibility="hidden"
	});

//        GEvent.addListener(marker, "mouseover", function() {
//	    marker.openInfoWindowHtml("<font size=-1>"+networkName+"<br><b>"+label+"</b> (N+"+coordNorm(this.point.y,5)+", E+"+coordNorm(this.point.x,5)+")");
//	});
	map.addOverlay( marker );
    }
}

function netNodes( xmlNodes ) {
    if (!xmlNodes) {
    	// msg( "No nodes given");
	return
    }

    this.nodeElements = xmlNodes.getElementsByTagName( "node" );
    // this.nodes = new Array(this.nodeElements.length);
    this.nodes = [];
    for( var i=0; i< this.nodeElements.length; i++) {
    	this.nodes[i] = new netNode( this.nodeElements[i] );
    }

    this.addToMap = function(map) {
    	for( var i=0; i<this.nodes.length; i++ )
    		this.nodes[i].addToMap( map );
    }

    this.getNodeByName = function( name ) {
    	var i=0;
    	while( (i<this.nodes.length) && (this.nodes[i].name!=name) ) i++;
    	if (i<this.nodes.length) return this.nodes[i];
    	else return null;
    }
}

function netLink( xmlLink ) {
// return;
//    if (xmlLink.getAttribute==null) return;
    
    this.from = xmlLink.getAttribute( "from" );
    this.to = xmlLink.getAttribute( "to" );
    this.type = xmlLink.getAttribute( "type" );
    this.quality = parseFloat( xmlLink.getAttribute( "qual" ) );
    this.traffic = parseFloat( xmlLink.getAttribute( "traff" ) );
    this.via =  xmlLink.getAttribute( "via" );
    this.viaPoint = null;
    this.fromPoint = null;
    this.toPoint = null;
    this.associated = false;
    if (this.via!=null) {
    	this.viaPoint = new GPoint( parseFloat( this.via.split(',')[0] ),
				    parseFloat( this.via.split(',')[1] ) );
    }
    
    this.associate = function( nodes ){
	var n = nodes.getNodeByName( this.from );
	if (n==null) { msg( "Unassociated from: "+this.from );  return 1; }
	this.fromPoint = n.point;
	var n = nodes.getNodeByName( this.to );
	if (n==null) { msg( "Unassociated to: "+this.to ); return 1; }
	this.toPoint = n.point;
	this.associated = true;
	return 0;
    }


    this.setColor = function() {    
    	switch (this.type) {
	    case "802.11b":
	    case "802.11g": this.color="#ff4444"; this.width=2; this.opacity=0.7; break;
	    case "802.11a": this.color="#44ff44"; this.width=2; this.opacity=0.7; break;
	    case "Ronja":   this.color="#ffff44"; this.width=2; this.opacity=0.5; break;
	    default:	    this.color="#ffffff"; this.width=2; this.opacity=1; break;
	}		    
	
    }

    this.addToMap = function( map ) {
	if (!this.associated) return;
	map.addOverlay( this.polyLine() );
    }
}


function netLinks( xmlLinks ){
// return;
    if (!xmlLinks) {
    	// msg( "No links given" );
	return;
    }
    this.linkElements = xmlLinks.getElementsByTagName( "link" );
    this.links = [];
    for( var i=0; i< this.linkElements.length; i++) {
    	this.links[i] = new netLink( this.linkElements[i] );
	this.links[i].setColor();
    }

    this.addToMap = function(map) {
    	for( var i=0; i<this.links.length; i++ )
	    this.links[i].addToMap( map );
    }

    this.associate = function( nodes ){
    	var a = 0;
    	for( var i=0; i<this.links.length; i++ ) {
    		a += this.links[i].associate( nodes );
    	}
    	return a;
    }
}

function netNet( xmlNet ) {
    if (!xmlNet) {
	// msg( "no net given" );
	return;
    }
    this.nodes = new netNodes( xmlNet.getElementsByTagName( "nodes" )[0] );
    this.links = new netLinks( xmlNet.getElementsByTagName( "links" )[0] );

    this.centerPoint = null
    this.zoom = -1;
    
    var p = this.links.associate( this.nodes );
//	msg( "unassociated links: "+p+" of "+this.links.links.length );

    this.getCenter = function() {
	var c = xmlNet.getElementsByTagName( "start" );
	if (c.length) {
	    alert("1");
    	    this.centerPoint = new GLatLng( parseFloat(c[0].getAttribute("lat")),
    				    	    parseFloat(c[0].getAttribute("lon")) );
    	    var z = c[0].getAttribute("zoom");
    	    if (parseInt(z)||parseInt(z)==0) this.zoom = parseInt(z);
	}
        else 	// spocitaj tazisko bodov
        {
	    var midN=0, midX=0, midY=0;
    	    for (var i=0; i<this.nodes.nodes.length; i++) {
		midX += this.nodes.nodes[i].point.x;
	        midY += this.nodes.nodes[i].point.y;
	        midN++;
	    }
	    if (midN>0) {
		this.centerPoint = new GLatLng(midY/midN, midX/midN);
		this.zoom = 13;
	    }
	}
    }

    this.createPoints = function(map, pan, zoom) {
    	this.nodes.addToMap(map);
	
	this.getCenter();
	if ((pan) && (this.centerPoint)) map.setCenter( this.centerPoint );
	if ((zoom) && (this.zoom>=0)) map.setZoom( this.zoom );
    }
    
    
    this.createLinks = function(map) {
	// vytvor graf, aby sa dal lahko prehladavat
	var graph = {};
	
	for (var i=0; i<this.links.links.length; i++) {
	    var l = this.links.links[i];

	    if (graph[l.from]==null) graph[l.from]={};
	    if (graph[l.to]==null)   graph[l.to]={};
	    
	    graph[l.from][l.to]=[ l.color, l.width, l.opacity ];
	    graph[l.to][l.from]=[ l.color, l.width, l.opacity ];
	}
	
	var polyline = null;
	var markEdge = {};
	var cnt=0;
	
	this.doSearch = function(from, color) {
	    // pre vsetky neoznacene hrany tejto farby
	    for (var to in graph[from]) {
		if ((graph[from][to][0]==color) && (markEdge[from+":"+to]!=1)) {
		    // pridaj do polyline -->
		    polyline[cnt++]=to;
			
		    // oznac
		    markEdge[from+":"+to]=1;
		    markEdge[to+":"+from]=1;
			
		    // rekurzia
		    this.doSearch(to, color);
			
		    // pridaj do polyline <--
		    polyline[cnt++]=from;
		}
	    }
	}
	
	for (var node=0; node<this.nodes.nodes.length; node++) {
	    var s=this.nodes.nodes[node].name;
	    var colors={};
	    
	    // zoznam farieb
	    for (var ss in graph[s]) {
		if (colors[ graph[s][ss][0] ]==null) {
		    colors[ graph[s][ss][0] ] = graph[s][ss];
		}
	    }
	    
	    // pre vsetky farby
	    for (var color in colors) {
		// spocitaj komponent
		polyline=new Array(s); cnt=1;
		this.doSearch(s,color);
		
		// alert(polyline);
		
		// skonvertuj na GPolyline
		if (cnt>2) {
		    var q=0;
		    var p = new Array();
		    for (var i=0; i<cnt; i++) {
			var n = this.nodes.getNodeByName( polyline[i] );
		        if (n!=null) p[q++] = n.point;
		    }
		    
		    // nakresli
		    map.addOverlay( new GPolyline( p, colors[color][0], colors[color][1], colors[color][2] ));
		}
	    }
	}
    }
}

function mapLoadTopology(url,pan,zoom) {
    var request = GXmlHttp.create();
    request.open( "GET", url+"?q="+Math.round(Math.random()*100000), true );
    request.onreadystatechange = function() {
	if (request.readyState == 4 ) {
	    var xmlDoc = request.responseXML;
	    if (!xmlDoc) {
	    	msg( "bad xml");
	    	return;
	    }
	    net = new netNet( xmlDoc.documentElement );
	    net.createPoints(map, pan, zoom);
	    net.createLinks(map);
	}
    }
    request.send(null);
}

// callbacks from options window
function mapReload(pan, zoom) {
    map.clearOverlays();
    mapLoadTopology(mapURL, pan, zoom);
}

function mapResize() {
    var mW,iL,iW;
    if (MapWidth==MAP_WIDTH_LARGE) {
	mW=MAP_WIDTH_SMALL;
	iL=MAP_WIDTH_SMALL;
    } else {
	mW=MAP_WIDTH_LARGE;
	iL=MAP_WIDTH_LARGE;
    }    

    iW=100-iL;
    MapWidth=mW;

    document.getElementById("map").style.width=mW+"%";
    
    // recenter map
    var cen=map.getCenter();
    map.checkResize();
    map.setCenter(cen);
    
    document.getElementById("info").style.left=iL+"%";
    document.getElementById("info").style.width=iW+"%";
}

function mapResizeIf(mode) {
    if (mode==1) { if (MapWidth==MAP_WIDTH_LARGE) mapResize(); }	// shrink map, if needed
    if (mode==2) { if (MapWidth!=MAP_WIDTH_LARGE) mapResize(); }	// expand map, if needed
}

