/**
*   cZones
*   Handler for zones. Hide / show on zoom and such.
*
*   Bjorn Brala - Swis BV
**/
function cZones(oMap){    
    this.oMap = oMap;
    this.aZones = Array();
    this.sCurrentlyLoaded = "none";
    this.aLoadedOverlays = Array();
    
    this.init = function(){
        this.loadSettings();
        
        this.loadData();
        
        this.loadMapListeners();
        
        return this;
    }
    
    
    /**
    *   Settings    
    **/
    this.loadSettings = function(){
        
        this._sDataUrl      = this._sDataUrl        || "GeoStart/ajax/getZoneData.php";
        this._iZoomVisible  = this._iZoomVisible    || 12;
        this._iZoomFilled   = this._iZoomFilled     || 14;
        this._iZoomHidden   = this._iZoomHidden     || 19;
        this._sColor        = this._sColor          || "#4C1664";
        this._iOpacity      = this._iOpacity        || "0.2";
        this._iBorderWidth  = this._iBorderWidth    || 3;
        this.bFirstLoad     = this.bFirstLoad       || true;
        this.bVisible       = this.bVisible         || true;
        if ( this.bStartInvisble === true ) {
            this.bVisible = false;
        }        
    }
    
    /**
    *   Enable balloon for data field
    *   @param sField field with data for in the balloon
    **/
    this.enableBalloon = function(sField){
        var i = this.aZones.length;
        if ( i > 0 ) {
            while ( i-- ) {
                this.aZones[i].text.enableBalloon(sField);
            }
        } else {
            this.sEnableBalloon = sField;
        }
    }    
    
    /**
    *   Do an ajax call with callback
    **/
    this.loadData = function(){
        GDownloadUrl( this._sDataUrl, GEvent.callback(this, this.loadZoneData));
    }
    
    
    /**
    *   load the data gotten from the data url.
    **/
    this.loadZoneData = function(oJson){
        var aData = eval('(' + oJson + ')');
        
        var i = aData.length;
        
        while ( i-- ) {
            /*this.aZones[i] = {  "polyline": this.createPolyline(aData[i]),
                                "polygon":  this.createPolygon(aData[i]),
                                "text":     this.createZoneLabel(aData[i]) 
                                };*/
            this.aZones[i] = {  "polyline": this.createPolyline(aData[i]),
                                "polygon":  this.createPolygon(aData[i]),
                                "text":     this.createZoneLabel(aData[i]) 
                                };                                
            this.aZones[i].bounds = this.aZones[i].polyline.getBounds();
            this.aZones[i].text['_bounds'] = this.aZones[i].polyline.getBounds();
            
            
            if ( aData[i].kleur.length == 6 ) {
                this.aZones[i].kleur = "#" + aData[i].kleur;
            } else {
                this.aZones[i].kleur = this._sColor;
            }
            
        }
        
        if ( this.bFirstLoad ) {
            this.bFirstLoad = false;
            
            if ( this.sEnableBalloon ) {
                this.enableBalloon(this.sEnableBalloon);
            }            
            this.updateZones();
        }
    }
    
    
    /**
    *   Map listener to handle map chenges
    **/   
    this.loadMapListeners = function(){
        var oThis = this;
        GEvent.addListener(oThis.oMap, 'moveend', GEvent.callback(this, this.updateZones));
    }
    /**
    *   Toggle visibility
    **/
    this.toggle = function(){
        this.bVisible = !this.bVisible;
        this.visibility(this.bVisible); 
        return this.bVisible;       
    }
    
    
    /**
    *   Show / Hide all
    **/
    this.visibility = function(bState){
        var i = this.aLoadedOverlays.length;
        if ( i > 0 ) {
            while ( i-- ) {
                if ( bState ) {
                    this.aLoadedOverlays[i].show();
                } else {
                    this.aLoadedOverlays[i].hide();
                }
            }
        }
    }
    
    /**
    *   Adding/removing zones and changing opacity.
    **/
    this.updateZones = function(){
        var state = this.checkForStateChange();
        if ( state ) {
            this.removeAll();            
            this.updateDisplay(state);
            this.sCurrentlyLoaded = state;
        }
    }
    
    
    /**
    *   remove old overlays
    **/
    this.removeAll = function(){
        var i = this.aLoadedOverlays.length;
        if ( i > 0 ) {
            while(i--){
                this.oMap.removeOverlay(this.aLoadedOverlays[i]);
            }
            this.aLoadedOverlays = Array();
        }
    }
    
    /**
    *   Update the display of zones. Depending on state it will be displayed.
    **/
    this.updateDisplay = function(sState){
        switch ( sState ) {
            case "none":
                break;
            case "polygon":
                var i = this.aZones.length;
                while ( i-- ) {
                    this.oMap.addOverlay(this.aZones[i].polygon);
                    this.aLoadedOverlays.push(this.aZones[i].polygon);                    
                    this.oMap.addOverlay(this.aZones[i].text);
                    this.aLoadedOverlays.push(this.aZones[i].text);                    
                }
                break;
            case "polyline":
                var i = this.aZones.length;
                while ( i-- ) {
                    this.oMap.addOverlay(this.aZones[i].polyline);
                    this.aLoadedOverlays.push(this.aZones[i].polyline);                    
                }
                break;        
        }
        this.visibility(this.bVisible);
    }
    
    /**
    *   Check what should be loaded at this time.
    **/
    this.checkForStateChange = function(){
        var iZoom   = this.oMap.getZoom();        
        var sNewState;

        if ( iZoom < this._iZoomVisible ) {
            sNewState = "none";
        } else if ( iZoom >= this._iZoomVisible && iZoom <= this._iZoomFilled ) {
            sNewState = "polygon";
        } else if ( iZoom >= this._iZoomFilled && iZoom <= this._iZoomHidden ) {
            sNewState = "polyline";
        } else if ( iZoom < this._iZoomHidden ) {
            sNewState = "none";
        }
        if ( sNewState == this.sCurrentlyLoaded ) {
            return false;
        } else {
            return sNewState;
        }
    }
    
    /**
    *   Create a polyline
    **/   
    this.createPolyline = function(aInfo){
        var aPoints = this.createPoints(aInfo);
        if ( aInfo.kleur && aInfo.kleur.length == 6 ) {
            var sKleur  = "#"+aInfo.kleur;
        } else { 
            var sKleur = this._sColor;
        }
        var oPoly = new GPolyline(aPoints, sKleur, this._iBorderWidth, 1);

        
        oPoly._GeoInfo = aInfo;
        return oPoly;
    }
    
    /**
    *   Create a polyline
    **/   
    this.createPolygon = function(aInfo){        
        var aPoints = this.createPoints(aInfo);
        
        if ( aInfo.kleur && aInfo.kleur.length == 6 ) {
            var sKleur  = "#"+aInfo.kleur;
        }else{ 
            var sKleur = this._sColor;
        }

        var oPoly = new GPolygon(aPoints, sKleur, this._iBorderWidth, parseFloat(0.8), sKleur, parseFloat(this._iOpacity));
        oPoly._GeoInfo = aInfo;
        return oPoly;
    }    
    
    /**
    *   Create the center label for the polygone.
    **/
    this.createZoneLabel = function(aInfo){
        var sTitel  = aInfo.titel;
        var point   = new GLatLng(parseFloat(aInfo.lat), parseFloat(aInfo.lng));
        var oLabel  = new ZoneLabel(point, sTitel);
        oLabel._Data = aInfo;
        return oLabel;
    }
    
    
    /**
    *   Convert array of lat's and lng's to real GPoints()
    **/
    this.createPoints = function(aInfo){
        var aPoints = aInfo['aGeometry'];
        var i = aPoints.length;
        var aGPoints = new Array();
        aPoints.reverse;
        while ( i -- ) {
            point = new GLatLng( parseFloat(aPoints[i].lat), parseFloat(aPoints[i].lng) );
            aGPoints.push(point);
        }
        return aGPoints;
    }
}


// A Rectangle is a simple overlay that outlines a lat/lng bounds on the
// map. It has a border of the given weight and color and can optionally
// have a semi-transparent background color.
function ZoneLabel(point, sText) {
    this._sText = sText;
    this._point = point;
}
ZoneLabel.prototype = new GOverlay();



// Creates the DIV representing this rectangle.
ZoneLabel.prototype.initialize = function(map) {

    var oElement = document.createElement('div');
    
    oElement.style.position     = "absolute";
    oElement.style.textAlign    = "center";
    oElement.style.width        = "50px";
    oElement.style.height       = "20px";
    oElement.style.cursor       = "pointer";
    
    var aText = Array();
    
    aText.push("<span style='position:absolute;top:1px;left:1px;z-index:1000000000;color:black;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:0px;left:0px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:2px;left:2px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:2px;left:0px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:0px;left:2px;color:white;'>"+this._sText+"</span>");
    var sText = aText.join('');
    
    oElement.innerHTML = sText;
    
    // Our rectangle is flat against the map, so we add our selves to the
    // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
    // below the marker shadows)
    map.getPane(G_MAP_MARKER_SHADOW_PANE).appendChild(oElement);
    
    this.map_ = map;
    this.div_ = oElement;
    var self = this;
    GEvent.addDomListener(oElement, 'click', function(){
        self.clickHandler();
    });
    
}

ZoneLabel.prototype.enableBalloon = function(sField){
    this.balloonEnabled = true;
    this.balloonField = sField;
}


ZoneLabel.prototype.getBalloonHtml = function(){    
    var oElement = document.createElement("div");
    oElement.className = "infoWindow";
    var aHtml = new Array();
    
    aHtml.push("<strong>"+this._Data['titel']+"</strong>");
    aHtml.push("<p>"+this._Data[this.balloonField]+"</p>");
    oElement.innerHTML = aHtml.join('');
        
    var oLink = document.createElement("a");
    oLink.className = "zoomAnchor";
    oLink.innerHTML = "<img alt='+' src='GeoStart/images/controls/grey/small_plus.gif'/> Zoom in naar de zone";
    var href = document.createAttribute('href');
    href.nodeValue = "#";
    oLink.setAttributeNode(href);
    
    var oLinkDiv = document.createElement("div");
    oLinkDiv.className = "ballonButton";
    oLinkDiv.appendChild(oLink);
    oLinkDiv.style.paddingTop = "20px";
    
    var self = this;
    GEvent.addDomListener(oLink, 'click', function(){
        self.zoomToZone();
        self.map_.closeInfoWindow();
    });
    oElement.appendChild(oLinkDiv);
    return oElement;
}

ZoneLabel.prototype.clickHandler = function(){
    if ( this.balloonEnabled ) {
        this.map_.openInfoWindowHtml(this._point, this.getBalloonHtml());
    } else {
        this.zoomToZone();
    }
}

ZoneLabel.prototype.zoomToZone = function(){
    this.map_.setCenter(this._point, this.map_.getBoundsZoomLevel(this._bounds));
}

// Remove the main DIV from the map pane
ZoneLabel.prototype.hide = function() {
  this.div_.style.display = "none";
}
// Remove the main DIV from the map pane
ZoneLabel.prototype.show = function() {
  this.div_.style.display = "block";
}


// Remove the main DIV from the map pane
ZoneLabel.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
}

// Copy our data to a new Rectangle
ZoneLabel.prototype.copy = function() {
  return new Rectangle(this._point, this._sText);
}

// Redraw the rectangle based on the current projection and zoom level
ZoneLabel.prototype.redraw = function(force) {
  // We only need to redraw if the coordinate system has changed
  if (!force) return;
  
  // Calculate the DIV coordinates of two opposite corners of our bounds to
  // get the size and position of our rectangle
  var coords = this.map_.fromLatLngToDivPixel(this._point);
  
  this.div_.style.left = ( coords.x - 25 ) + "px";
  this.div_.style.top = ( coords.y - 10 ) + "px";
  
}

