var PARAM_TCamera_popupWidth = 320 + 20;
var PARAM_TCamera_popupHeight = 240 + 25;

var MSIE  = document.all;
var oldNS = document.layers;
var newNS = !document.all && document.getElementById;
var opera = window.opera;

var bMenuSel = true;

var lMenuVis = [];
var lMenuSel = [];

function e (f,  a,b) { return new f(a,b); }
function dA(x,  a  ) { return x.getAttribute(a); }
function dE(x,  a  ) { return x.getElementsByTagName(a); }
function dF(f,p,a,b) { return e(f,p(a),p(b)); }
function dL(x,  a,b) { return dF(GLatLng,parseFloat,dA(x,a),dA(x,b)); }
function dS(x,  a,b) { return dF(GSize  ,parseInt  ,dA(x,a),dA(x,b)); }

GMap2.prototype.checkBounds = function(){
	if (this.globalBounds.containsBounds(this.getBounds())) {
		this.prevCenter=this.getCenter();
	}
	else {
	    if (this.prevCenter) {
//	    	this.setCenter(this.prevCenter);
	    }
	}
}

/*
GMap2.prototype.checkBoundsOLD = function(){
    var center = this.getCenter();
    var tgb = this.globalBounds;
    if (tgb.contains(center)) return;
    var centerX = center.lng();
    var centerY = center.lat();
    var AmaxX = tgb.getNorthEast().lng();
    var AmaxY = tgb.getNorthEast().lat();
    var AminX = tgb.getSouthWest().lng();
    var AminY = tgb.getSouthWest().lat();
    jslog.debug("checkbounds. tl:"+AmaxX+","+AmaxY+" br:"+AminX+","+AminY)

    if (centerX < AminX) {centerX = AminX+0.001;}
    if (centerX > AmaxX) {centerX = AmaxX-0.001;}
    if (centerY < AminY) {centerY = AminY+0.001;}
    if (centerY > AmaxY) {centerY = AmaxY-0.001;}
//    this.setCenter(new GLatLng(centerY,centerX));
}
*/

GMap2.prototype.checkInfoBounds = function(){
    var x = this.getInfoWindow();
    if (!x.isHidden() && !this.getBounds().contains(x.getPoint())) this.closeInfoWindow();
}


// TMarker v0.0.0

TMarker.dI  = new GIcon();
function TMarker(pos, size, img, title, text, _uname) {
    TMarker.dI.iconSize         = size;
    TMarker.dI.iconAnchor       = e(GPoint,size.width/2,size.height/2);
    TMarker.dI.infoWindowAnchor = e(GPoint,size.width/2,size.height  );

// deprecated
//    GMarker.call(this, pos, new GIcon(TMarker.dI, img));
    var options = { 
    	title: _uname,
    	icon: new GIcon(TMarker.dI, img)
    };
    GMarker.call(this, pos, options);

    this.name = title;
    this.icon   = img;
    this.uname = _uname
    if (text) {
  	//adds click event to marker to open popup window
        var pW = function() { this.openInfoWindowHtml('<div class="hinweis">'+text+'</div>',{suppressMapPan:false});  }
        GEvent.addListener(this, "click", pW);
        this.doOpenWindow = pW;
    }
}

TMarker.prototype = new GMarker(new GLatLng(0,0));

TMarker.prototype.myshow = function(m) {
    m.addOverlay(this);
    if (m.OpenedInfoWindowPos && m.OpenedInfoWindowPos.equals(this.getPoint())) {
  	this.doOpenWindow();
  	m.OpenedInfoWindowPos = false;
    }
}
TMarker.prototype.myhide = function(m) {
    if (m.OpenedInfoWindowPos && m.OpenedInfoWindowPos.equals(this.getPoint()))
    {
  	m.OpenedInfoWindowPos = false;
  	m.closeInfoWindow();
    }
    m.removeOverlay(this);
}

TMarker.CacheEstilos = [];
TMarker.CacheInfos = [];
TMarker.load = function (f,c) {
    if (c[f]) {
  	return c[f];
    }
    if (MSIE) {
        var i=new ActiveXObject("Microsoft.XMLDOM");
        i.async=false;
        i.load(f);
    } else {
        var r = new XMLHttpRequest();
        r.open("GET",f,false);
        r.send(null);
        var i = r.responseXML;
    }
    c[f] = i;
    return i;
}
  
TMarker.loadXSL = function (f) { t = this;return t.load(f,t.CacheEstilos); }
TMarker.loadXML = function (f) { t = this;return t.load(f,t.CacheInfos); }

TMarker.doHTML = function (xsl,xml) {
    if (MSIE) {
        return xml.transformNode(xsl);
    } else {
        var p = new XSLTProcessor();
   	    p.importStylesheet(xsl);
      	var d = document.createElement('div');
       	d.appendChild(p.transformToFragment(xml,window.document));
       	return d.innerHTML;
    }
    return null;
}

TMarker.doXML = function (m) {
    if (MSIE) {
        var x=new ActiveXObject("Microsoft.XMLDOM");
    } else {
        var x=document.implementation.createDocument("", "", null);
    }
    for ( i = 0; i < m.length; i++) {
        x.appendChild(m.item(i).cloneNode(true));
    }
    return x;
}

TMarker.Xml = function (m) {
    t = this;
    TMarker.CacheInfos = [];
    for (var l=new Array(),i = 0; i < m.length; i++) {
	sf = dA(m[i],"style");
  	mf = dA(m[i],"info");
	md = dE(m[i],"info");
	ml = md.length;
        var h = ( sf && ( mf || ml ) ) ? t.doHTML(t.loadXSL(sf),ml?t.doXML(md):t.loadXML(mf+'?'+now.getTime())) : null;
        l.push(new TMarker(dL(m[i],"lat","lng"), dS(m[i],"width","height"), dA(m[i],"icon"), dA(m[i],"name"), h, dA(m[i],"uname")));
    }
    return l;
}

// TCamera v0.0.0

TCamera.pW = false;
function TCamera(pos, size, icon, title, uname, text, time, opts) {
    f = opts.cameraOnWindowInfo;
    TMarker.call(this, pos, size, icon, title, f?text:false, uname);

    if (text && !f) {
        if (TCamera.pW && TCamera.pW.closed) TCamera.pW = false;

        GEvent.addListener(this, "click", function() {
            config  = 'toolbar=no,location=no,directories=no,status=no,menubar=no,width='+PARAM_TCamera_popupWidth+',height='+PARAM_TCamera_popupHeight;
            config += ',scrollbars=no,resizable=no';
            if (TCamera.pW && TCamera.pW.closed) {
                TCamera.pW = false;
            }
            if (TCamera.pW) {
                //        if (TCamera.pW.name == (title+'-'+uname) ) return;
                TCamera.pW.close();
            }

            var _now = new Date().getTime();
            title2=title.replace(" ", "_");
//if (jslog) jslog.debug("TCamera: title="+title+" config="+config);
            TCamera.pW = window.open ("",title2,config);
            TCamera.pW.document.writeln('<head>');
            TCamera.pW.document.writeln('<title>'+title+'-'+uname+'</title>');
            TCamera.pW.document.writeln('<script type="text/javascript">');
            TCamera.pW.document.writeln('var a = new Image();');
            TCamera.pW.document.writeln('a.src = "'+text+'?'+now+'";');
            TCamera.pW.document.writeln('function updateSource(time,_now){');
            TCamera.pW.document.writeln('  a = new Image();');
            TCamera.pW.document.writeln('  a.src = "'+text+'?"+_now;');
            TCamera.pW.document.writeln('}');
            TCamera.pW.document.writeln('function updateData(){');
            TCamera.pW.document.writeln('  if (a && a.complete)  {');
            TCamera.pW.document.writeln('    document.getElementById("_i").src   = a.src;');
            TCamera.pW.document.writeln('  }');
            TCamera.pW.document.writeln('}');
            TCamera.pW.document.writeln('window.setInterval("updateData()",1000);');
            TCamera.pW.document.writeln('</script>');
            TCamera.pW.document.writeln('</head>');
            TCamera.pW.document.writeln('<body><img id="_i" src="dev/images/camara_load.jpg" width="320" ></img></body>');
        });
//        if (jslog) jslog.debug("TCamera.pW.name="+TCamera.pW.name);
        if (TCamera.pW && TCamera.pW.name == title2) TCamera.pW.updateSource(time,new Date().getTime());
    }
}

TCamera.prototype = new TMarker(new GLatLng(0,0), new GSize(0,0),'',null,false,null);

TCamera.Xml = function (m,opts) {
    for (var l = new Array(),i = 0; i < m.length; i++) {
        var c = dA(m[i],"img");
        if (opts.cameraOnWindowInfo) c = c?"<img src='"+c+"?"+now.getTime()+"' width='352' height='288'></img>":false;
        l.push(new TCamera(dL(m[i],"lat","lng"), dS(m[i],"width","height"), dA(m[i],"icon"), dA(m[i],"name"), dA(m[i],"uname"), c,new Date().toGMTString(),opts));
    }
    return l;
}


// TPanell v0.0.0

TPanell.iconSize = e(GSize,98, 26);

function TPanell(pos, img, title, uname, line) {
    TMarker.call(this, pos, TPanell.iconSize,img, title, false, uname);
    var l = (isNaN(line.lng()) || isNaN(line.lat()))? null :new GPolyline(new Array(line,pos),'#000000',2,1);
    this.getLine = function() { return l; }
}

TPanell.prototype = new TMarker(new GLatLng(0,0),TPanell.iconSize,null,false,null);

TPanell.prototype.myshow = function(m) {
    var l  = this.getLine();
    TMarker.prototype.myshow.call(this,m);
    if ( l ) m.addOverlay(l);
}
TPanell.prototype.myhide = function(m) {
    var l  = this.getLine();
    if ( l ) m.removeOverlay(l);
    TMarker.prototype.myhide.call(this,m);
}

TPanell.Xml = function (m) {
    for (var l  = new Array(),i = 0; i < m.length; i++)
        l.push(new TPanell(dL(m[i],"lat","lng"),dA(m[i],"icon")+"?"+now.getTime(),dA(m[i],"name"),dA(m[i],"uname"),dL(m[i],"llat","llng")));
    return l;
}


// TRoute v0.0.0

// TRoute.opacity = 0.6;
TRoute.opacity = 1.0;

function TRoute(points_array, color, weight, title) {
    GPolyline.call(this, points_array, color, weight, TRoute.opacity);
    this.name = title;
    this.l = new Array();
}

TRoute.prototype = new GPolyline();
TRoute.prototype.getPoint = function() { return this.getVertex(0); }

TRoute.prototype.addMarker = function(pos, size, img, title, text) {
//    jslog.debug("TRoute.addMarker="+title+", text="+text);
    var m = (pos.constructor == TMarker.prototype.constructor)?pos:new TMarker(pos, size, img, title, text, title);
    this.l.push(m);
    return m;
}

TRoute.prototype.myshow = function( m ) {
//    jslog.debug("TRoute.myshow="+this.name+", l.len="+this.l.length);
    m.addOverlay(this);
    for(var i = 0; i < this.l.length; ++i) m.addOverlay(this.l[i]);
}
TRoute.prototype.myhide = function( m ) {
    for(var i = 0; i < this.l.length; ++i) m.removeOverlay(this.l[i]);
    m.removeOverlay(this);
}

// parsea el xml para obtener um array de TRoutes
TRoute.Xml = function (m,o) {
//    jslog.debug("TRoute.Xml="+m.length);
    var res = new Array();
    for (i = 0; i < m.length; i++){
        d = dE(m[i],"DEF");
        var points = new Array()
        for(j = 0; j < d.length; j++) points.push(dL(d[j],"lat","lng"));
        res.push(new TRoute(points,dA(m[i],"color"),parseInt(dA(m[i],"width")),dA(m[i],"name")));
    }
    return res;
}

function TLayer(n,id, icon, clase, tag, zoom, flag, xmltag) {
    this.sublayerList=new Array();
    this.hasSublayers = n==0;
    this.hasAncestor = n==2;
    this.nom      = id;
    this.icon     = icon;
    this.tag      = tag;
    this.flag     = flag;
    this.hasMarkers = !this.hasSublayers;
    this.selectable = (xmltag!="NONE")
    if (xmltag=="NONE") this.hasMarkers=false;
    if (xmltag=="LNK") this.hasMarkers=true;
//    if (xmltag=="INC") this.hasMarkers=true;

/*    if (jslog) jslog.debug("TLayer.name="+id+", xmltag="+xmltag+", hasMarkers="+this.hasMarkers+
                           ", n="+n+", hasSublayers="+this.hasSublayers+", flag="+flag+
                           ", hasAncerstor="+this.hasAncestor+
                           ", tag="+tag);
*/
    if (!this.hasMarkers)
        this.lElems = new Array();
    else
        this.lMarkers = new Array();

    if (!this.hasMarkers) return;

    this.clase    = clase;
    this.zoom     = zoom;
    this.xmltag   = xmltag;
    this.state    = false;
}

TLayer.prototype.setMarkers = function(l) {
    if (!this.hasMarkers)
  	this.lElems = l;
    else
  	this.lMarkers = l;
    return l;
}

TLayer.prototype.getVisHTML = function(callback,i) {
    var msg = "<tr id=\"tr_"+this.tag+"\">";
    msg+= "<td width=\"180\" height=\"20\" valign=\"top\" class=\"tdMenu2\" >";
    msg+= "<input alt=\"Muesta/Oculta "+this.nom+"\" ";
    if (!this.hasMarkers)
        msg+="DISABLED ";
    else if (this.flag)
        msg+="CHECKED ";
    msg+= "onclick=\"javascript:"+callback+"(event,"+i+",'"+this.tag+"');\" type=\"checkbox\" class=\"checkbox\" id='"+this.tag+"' style=\"cursor:pointer;";
    if (this.hasAncestor) 
        msg+="margin-left:40pt;";
    msg+= "\" >";
    msg+= "<label for=\""+this.tag+"\" style=\"cursor:pointer;\">"+this.nom+"</label>";
    msg+= "</td></tr>";
    return msg;
}

TLayer.prototype.getSelHTML = function(i) {
    var msg =  "<option id='"+this.tag+"' value=\""+i+"\">";
    msg+= "<label for=\""+this.tag+"\" style=\"cursor:pointer;\">"+this.nom+"</label>";
    msg+= "</option>";
    return msg;
}

TLayer.prototype.show = function(m,r) {
    this.state &= !r;
    var b = this.flag && (this.zoom < m.getZoom());
    if (this.state != b) {
  	if (b) {
            for (var i = 0; i < this.lMarkers.length; i++) this.lMarkers[i].myshow(m);
        } else {
            for (var i = 0; i < this.lMarkers.length; i++) this.lMarkers[i].myhide(m);
        }
        this.state = b;
    }
}


function TMap(data) {
    var maxZoom =  17;
    var minZoom =  12;
    var dLat    =   0.05;
    var dLng    =   0.05;
 
    var disableWindowInfoWhenOut = true;
    var cameraOnWindowInfo       = false;
 
    this.id     = dA(data,"id");
    var mapObj  = document.getElementById(this.id);
    var map     = new GMap2(mapObj);
    this.map    = map;
    mapObj.TMap = this;
    map   .TMap = this;
    map   .OpenedInfoWindowPos      = false;
    var mt     = map.getMapTypes();
    for (var i=0; i<mt.length; i++) {
        mt[i].getMinimumResolution = function() {return minZoom;}
        mt[i].getMaximumResolution = function() {return maxZoom;}
    }

    map.addControl(new GOverviewMapControl());
    map.addControl(new GLargeMapControl());
    map.enableInfoWindow();
    map.enableDoubleClickZoom();
    //  map.enableContinuousZoom();  // Can't run due Polyline not removed when doubleClickZoomOut &  removeOverlay

    this.file = dA(data,'file')
    var rc = new TElemControl ( false,false);
    var rs = new TElemSelector( false,false);

    // Paulo Veiga           this.loadControl=new TControlLoading();
    // Paulo Veiga           this.map.addControl(this.loadControl);    

    for(var m=dE(data,"ELEM"),i = 0; i<m.length; i++) {
  	var s=dE(m[i],"SUBELEM");
  	var layer=TMap.getNewLayer(s.length?0:1,m[i],this.id);
  	rc.addElem(layer);
  	var sublayers = new Array();
   	for(var j = 0; j< s.length; j++) {
            sublayers.push(rc.addElem(TMap.getNewLayer(2,s[j],this.id)));
	}
	rs.addElem(layer,sublayers);
	layer.sublayerList=sublayers;
    }
    rs.updateData();
  
    // generación OPCIONAL de un menú de control
    // de visualizacion de capas EXTERNO al mapa
    var TmenuVis = document.getElementById(dA(data,"idMenuVis"));
    if (TmenuVis) {
        rc.setMap(map);
        lMenuVis[this.id] = rc;
        msg = "<TABLE id='taMenuTable1' cellSpacing=0 cellPadding=0 width=\"100%\" border=0 ><TBODY>";
        for(var i=0; i<rc.l.length;i++)
            msg+=rc.l[i].getVisHTML("lMenuVis['"+this.id+"\'].selectElem",i);
        msg+= "</TBODY></TABLE>";
        TmenuVis.innerHTML = msg;
    } else {
        map.addControl(rc);
    }

    if (bMenuSel)
    {
        var TmenuSel = document.getElementById(dA(data,"idMenuSel"));
        if (TmenuSel) {
            rs.setMap(map);
            lMenuSel[this.id] = rs;
            msg = "<SELECT id='"+this.id+"_ElemSelector' onchange=\"javascript:lMenuSel['"+this.id+"\'].selectElem('"+this.id+"_ElemSelector');\">";
            for(var i=0; i<rs.l.length;i++)
                msg+=rs.l[i].getSelHTML(i);
            msg+= "</SELECT>";
            msg+= "<DIV id = '"+this.id+"_ElemList'></DIV>";
            TmenuSel.innerHTML = msg;
        } else {
            map.addControl(rs);
        }


        if (rc.anchorable && rs.anchorable) {
            rc.addAnchoredControl(rs,T_VERTICAL_ANCHOR);
        }
    }

    var pLat = parseFloat(dA(data,"lat"));
    var pLng = parseFloat(dA(data,"lng"));
    map.setCenter(new GLatLng(pLat,pLng),parseInt(dA(data,"zoom")));
//    map.globalBounds = new GLatLngBounds(new GLatLng(pLat-dLat,pLng-dLng),new GLatLng(pLat+dLat,pLng+dLng));
    var northeast=new GLatLng(-19.751194, -43.846436);
    var southwest=new GLatLng(-19.988836, -44.115601);
    map.globalBounds = new GLatLngBounds(southwest, northeast);

/*    jslog.debug(" swlat:"+map.globalBounds.getSouthWest().lat());
    jslog.debug(" swlng:"+map.globalBounds.getSouthWest().lng());
    jslog.debug(" nelat:"+map.globalBounds.getNorthEast().lat());
    jslog.debug(" nelng:"+map.globalBounds.getNorthEast().lng());
*/
    doWheelZoom = function(event) { 
        if(event.cancelable) event.preventDefault();
        if((event.detail || -event.wheelDelta) < 0) {map.zoomIn();} else {map.zoomOut();}
        return false;
    }

    lControl = [rc,rs];
    this.lControl = [rc,rs];
  
//    GEvent.addDomListener(mapObj, "DOMMouseScroll", doWheelZoom); 
//    GEvent.addDomListener(mapObj, "mousewheel",     doWheelZoom); 
    GEvent.addListener   (map,    "move",           map   .checkBounds);
    GEvent.addListener   (map,    "zoomend",        function (a,b) { var l = lControl;for(var i=0; i<l.length; i++)  l[i].updateData(false); });

    if (disableWindowInfoWhenOut)  {
        GEvent.addListener (map,    "moveend",        map   .checkInfoBounds);
    }
  
    this.UpdateInterval = 60;
    this.UpdateRemain   = this.UpdateInterval - 1;
}

TMap.prototype = new Object();

TMap.prototype.updateData = function () {
    this.UpdateRemain = (this.UpdateRemain+1)%this.UpdateInterval;
    //     Paulo  Veiga  if (this.UpdateRemain+1==this.UpdateInterval) this.map.addControl(this.loadControl);
    if (this.UpdateRemain) return;
    if (!this.lControl.length) return;

    // aqui se baja el xml de datos y se parsea por la funcion Xml
    // de cada una de las clases definidas en conf.xml
    
    // actualizamos la base de tiempos para todos los procedimientos
    now = new Date();
    
    var self = this;
    var xmldatafullfilename=this.file+'?'+now.getTime()
//    if (jslog) jslog.debug("TMap.updateData: filename="+xmldatafullfilename);
    GDownloadUrl(xmldatafullfilename, function(data, responseCode) {
        var xml = GXml.parse(data);
        var mapControls = self.lControl;
        for(var i = 0; i< mapControls[0].l.length; i++) {
            lyr=mapControls[0].l[i];
//          jslog.debug("i="+i+", .xmltag="+lyr.xmltag+" selectable="+lyr.hasMarkers)
            if (lyr.hasMarkers) {
                markersRO=lyr.clase().Xml(dE(xml.documentElement,lyr.xmltag),mapControls[0]);
                markers=new Array()
                for (ndx=0; ndx<markersRO.length; ndx++) markers.push(markersRO[ndx]);
                markers.sort(TTTsortByName);
//                jslog.debug("markers.length="+lyr.xmltag+", "+markers.length);
                lyr.setMarkers(markers);
            }
        }
        //actualiza los controles del mapa (capas y centrado)
  	for(var i=0; i<mapControls.length; i++) mapControls[i].updateData(true);
    });
    this.map.removeControl(this.loadControl);    

}

function TTTsortByName(a,b) {
    an=a.name;
    bn=b.name;
    return (an<bn?-1:(an>bn?1:0));
}


// n= node type: 0=hasChildren, 1=Single, 2=hasParent
TMap.getNewLayer = function (n,d,id) {
    var c = new Function("return "+dA(d,"tipo")+";");
    var t = dA(d,"marker");
    return new TLayer(n,dA(d,"text"),dA(d,"icon"),c,id+"_cb"+t,parseInt(dA(d,"zoom")),(parseInt(dA(d,"show"))!=0)?true:false,t);
}
