/*
  Extensions for Openlayers
  Written 2008/9 by Goudappel Coffeng, Deventer, Netherlands (Bsd)
  If you want is is free software, but we do not reccoment to use it since it is quite dedicated to our applications
  Extensions that are useful in a general context will be submitted to the Openlayers project
*/

// --------------------------------------------
function getActiveControl(panel)
// --------------------------------------------
// geeft van een panel-object het eerste actieve control terug
// dit is bedoeld als alle controls van type 'TYPE_TOOL' zijn en er een defaulttool bestaat,
// dan is er namelijk altijd precies een aktief
// --------------------------------------------
{
  for(var i=0, len=panel.controls.length; i<len; i++) {
     if (panel.controls[i].active) return i;
  }
}

// -------------------------------------------
// Workaround om WMS met bepaalde offset te verschuiven
// -------------------------------------------
  OpenLayers.Layer.WMS.prototype.getURL =
  function (bounds) {
      bounds = this.adjustBounds(bounds);
      if (this.sphericalcorrection) {
          var y = (bounds.top+bounds.bottom)/2;
          var p = new OpenLayers.Geometry.Point(0,y);
          var WGS84 = p.transform(
              new OpenLayers.Projection("EPSG:900913"), 
              new OpenLayers.Projection("EPSG:4326"));
          var x=WGS84.y;
          var dy = 4.440670387E-7*x*x*x*x*x + 9.641338494E-6*x*x*x*x - 
                   3.791462848E-2*x*x*x + 1.521499548E-2*x*x + 745.0588281*x + 0.434;
          bounds.top -= dy;
          bounds.bottom -= dy;
      }
      if (this.corry) {
          bounds.top += this.corry;
          bounds.bottom += this.corry;
      }
      if (this.corrx) {
          bounds.left += this.corrx;
          bounds.right += this.corrx;
      }
                            
      var imageSize = this.getImageSize(); 
      var newParams = {
          'BBOX': this.encodeBBOX ?  bounds.toBBOX() : bounds.toArray(),
          'WIDTH': imageSize.w,
          'HEIGHT': imageSize.h
      };
      var requestString = this.getFullRequestString(newParams);
      return requestString;
  };

// --------------------------------------------
function haalFeatureOnderXY(map,layer,x,y)
// --------------------------------------------
// geeft een feature terug dat onder de actuele muispositie (xy ligt), 
// of null als daar geen feature is
// --------------------------------------------
{
  var feature;
  for (var tpixel=1;tpixel<5;tpixel++)
  { 
    var tolerantie=map.resolution*tpixel;  // map units per pixel * t pixel
    var bounds = new OpenLayers.Bounds(x-tolerantie,y-tolerantie,x+tolerantie,y+tolerantie);
    for(var i=0, len = layer.features.length; i<len; ++i) 
    {
      feature = layer.features[i];
      if (bounds.toGeometry().intersects(feature.geometry)) 
      {
        if (OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1)
        {
          return feature;
        } 
      }
    }
  } 
  return null;
}


// --------------------------------------------
// click-event
  OpenLayers.Control.Click_bsd = OpenLayers.Class(OpenLayers.Control, {
// --------------------------------------------  
  	  onClick: function(e) {},
      defaultHandlerOptions: {
          'single': true,
          'double': false,
          'pixelTolerance': 0,
          'stopSingle': false,
          'stopDouble': false
      },

      initialize: function(options) { this.handlerOptions = OpenLayers.Util.extend( {}, this.defaultHandlerOptions);
          OpenLayers.Control.prototype.initialize.apply(this, arguments); 
          this.handler = new OpenLayers.Handler.Click(this, {'click': this.trigger}, this.handlerOptions);
      }, 

      trigger: function(e) {
        this.onClick(e);
      }

  });

// --------------------------------------------
OpenLayers.Control.DragFeature_bsd = OpenLayers.Class(OpenLayers.Control, 
// --------------------------------------------
// Uitbreiding DragFeature 
// --------------------------------------------
{
    geometryTypes: null,
    onStart: function(feature, pixel) {},
    onOver: function(feature) {},
    onOut: function() {},    
    onDrag: function(feature, pixel) {},
    onComplete: function(feature, pixel) {},
    layer: null,
    feature: null,
    dragCallbacks: {},
    featureCallbacks: {},
    lastPixel: null,
    initialize: function(layer, options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);
        this.layer = layer;
        this.handlers = {
            drag: new OpenLayers.Handler.Drag(
                this, OpenLayers.Util.extend({
                    down: this.downFeature,
                    move: this.moveFeature,
                    up: this.upFeature,
                    out: this.cancel,
                    done: this.doneDragging
                }, this.dragCallbacks)
            ),
            feature: new OpenLayers.Handler.Feature(
                this, this.layer, OpenLayers.Util.extend({
                    over: this.overFeature,
                    out: this.outFeature
                }, this.featureCallbacks),
                {geometryTypes: this.geometryTypes}
            )
        };
    },
    
    destroy: function() {
        this.layer = null;
        OpenLayers.Control.prototype.destroy.apply(this, []);
    },
    activate: function() {
        return (this.handlers.feature.activate() &&
                OpenLayers.Control.prototype.activate.apply(this, arguments));
    },
    deactivate: function() {
        // the return from the handlers is unimportant in this case
        this.handlers.drag.deactivate();
        this.handlers.feature.deactivate();
        this.feature = null;
        this.dragging = false;
        this.lastPixel = null;
        return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
    },
    overFeature: function(feature) {
        if(!this.handlers.drag.dragging) {
            this.feature = feature;
            this.handlers.drag.activate();
            this.over = true;
            // TBD replace with CSS classes
            this.map.div.style.cursor = "move";
            this.onOver(this.feature);
        } else {
            if(this.feature.id == feature.id) {
                this.over = true;
            } else {
                this.over = false;
            }
        }
    },
    downFeature: function(pixel) {
        this.lastPixel = pixel;
        this.onStart(this.feature, pixel);
    },
    moveFeature: function(pixel) {
        var res = this.map.getResolution();
        this.feature.geometry.move(res * (pixel.x - this.lastPixel.x),
                                   res * (this.lastPixel.y - pixel.y));
        this.layer.drawFeature(this.feature);
        this.lastPixel = pixel;
        this.onDrag(this.feature, pixel);
    },
    upFeature: function(pixel) {
        if(!this.over) {
            this.handlers.drag.deactivate();
            this.feature = null;
            // TBD replace with CSS classes
            this.map.div.style.cursor = "default";
            this.onOut();
        } else {
            // the drag handler itself resetted the cursor, so
            // set it back to "move" here
            this.map.div.style.cursor = "move";
        }
    },

    /**
     * Method: doneDragging
     * Called when the drag handler is done dragging.
     *
     * Parameters:
     * pixel - {<OpenLayers.Pixel>} The last event pixel location.  If this event
     *     came from a mouseout, this may not be in the map viewport.
     */
    doneDragging: function(pixel) {
        this.onComplete(this.feature, pixel);
    },

    /**
     * Method: outFeature
     * Called when the feature handler detects a mouse-out on a feature.
     *
     * Parameters:
     * feature - {<OpenLayers.Feature.Vector>} The feature that the mouse left.
     */
    outFeature: function(feature) {
        if(!this.handlers.drag.dragging) {
            this.over = false;
            this.handlers.drag.deactivate();
            // TBD replace with CSS classes
            this.map.div.style.cursor = "default";
            this.onOut();
            this.feature = null;
        } else {
            if(this.feature.id == feature.id) {
                this.over = false;
            }
        }
    },
        
    /**
     * Method: cancel
     * Called when the drag handler detects a mouse-out (from the map viewport).
     */
    cancel: function() {
        this.handlers.drag.deactivate();
        this.over = false;
    },

    /**
     * Method: setMap
     * Set the map property for the control and all handlers.
     *
     * Parameters: 
     * map - {<OpenLayers.Map>} The control's map.
     */
    setMap: function(map) {
        this.handlers.drag.setMap(map);
        this.handlers.feature.setMap(map);
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Control.DragFeature"
});

// ---------------------------------------------
    function DeleteMarkers(markerLayer) 
// ---------------------------------------------
// Dit is in principe clearMarker, met het verschil dat het de 
// markers ook echt vernietigt en dus geheugen vrijgeeft
// ---------------------------------------------    
    {
    	var amarker;
      if (markerLayer.markers != null) 
      { while(markerLayer.markers.length > 0) 
        { amarker=markerLayer.markers[0];
        	markerLayer.removeMarker(markerLayer.markers[0]);
        	amarker.destroy();
        }
      }
    }
    
    /**
     * Aanpassing van select-gedrag
     * Als meerdere wegvakken tegelijk worden geselecteerd dan wordt het select-event maar een keer uitgevoerd
     *
     * Method: selectBox
     * Callback from the handlers.box set up when <box> selection is true
     *     on.
     *
     * Parameters:
     * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }  
     */
    selectBox_maarEenEvent = function(position) {
        if (position instanceof OpenLayers.Bounds) {
            var minXY = this.map.getLonLatFromPixel(
                new OpenLayers.Pixel(position.left, position.bottom)
            );
            var maxXY = this.map.getLonLatFromPixel(
                new OpenLayers.Pixel(position.right, position.top)
            );
            var bounds = new OpenLayers.Bounds(
                minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
            );

            var prevonSelect = this.onSelect;
            var prevonUnselect = this.onUnselect;
            this.onSelect = function() {};
            this.onUnselect = function() {};
                        
            // if multiple is false, first deselect currently selected features
            if (!this.multipleSelect()) {
                this.unselectAll();
            }
            
            // because we're using a box, we consider we want multiple selection
            var prevMultiple = this.multiple;
            this.multiple = true;

            for(var i=0, len = this.layer.features.length; i<len; ++i) {
                var feature = this.layer.features[i];
                if (this.geometryTypes == null || OpenLayers.Util.indexOf(
                        this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
                    if (bounds.toGeometry().intersects(feature.geometry)) {
                        if (OpenLayers.Util.indexOf(this.layer.selectedFeatures, feature) == -1) {
                            this.select(feature);
                        }
                    }
                }
            }
            this.multiple = prevMultiple;
            this.onSelect = prevonSelect;
            this.onUnselect = prevonUnselect;
            this.onSelect(false);
        }
    }

    /**
     * Aanpassing van select-gedrag
     * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }  
     */
    selectBox_alleenCoordinates = function(position) 
    {
      if (position instanceof OpenLayers.Bounds) 
      {
         this.onSelect(position);
      }
    }

// --------------------------------------------
  function osm_getTileURL(bounds) 
// --------------------------------------------  
  {
      var res = this.map.getResolution();
      var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
      var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
      var z = this.map.getZoom();
      var limit = Math.pow(2, z);

      if (y < 0 || y >= limit) {
          return OpenLayers.Util.getImagesLocation() + "404.png";
      } else {
          x = ((x % limit) + limit) % limit;
          return this.url + z + "/" + x + "/" + y + "." + this.type;
      }
  }
                    
// ---------------------------------------------------------------
// Javascript trim, ltrim, rtrim  from http://www.webtoolkit.info/
function trim(str, chars) { return ltrim(rtrim(str, chars), chars); }
function ltrim(str, chars) { chars = chars || "\\s"; return str.replace(new RegExp("^[" + chars + "]+", "g"), "");}
function rtrim(str, chars) { chars = chars || "\\s"; return str.replace(new RegExp("[" + chars + "]+$", "g"), "");}
// ---------------------------------------------------------------

// ---------------------------------------------------------------
// Bepaling hoogte en breedte van window; functie afgekeken van www.walterzorn.de
// ---------------------------------------------------------------
function mygetWndW()
{
	var db = document.body;
	if (db && db.clientWidth) return db.clientWidth; else return window.innerWidth;
};
function mygetWndH()
{
	var db = document.body;
	if (db && db.clientHeight) return db.clientHeight; else return window.innerHeight;
};













OpenLayers.Control.InfoLayer =
  OpenLayers.Class(OpenLayers.Control, {

    /**
     * Property: activeColor
     * {String}
     */
    activeColor: "darkblue",

    /**
     * Property: width
     * CSS-style breedte van layer
     * {String}
     */
    width: null,

    /**
     * Property: height
     * CSS-style hoogte van layer
     * {String}
     */
    height: null,

    /**
     * Property: top
     * CSS-style positie van layer
     * {String}
     */
    top: "25px",


    /**
     * Property: content
     * HTML-string waarmee de layer gevuld wordt
     * {String}
     */
    content: "",

    /**
     * Property: ignoreClickEvent
     * default worden alle events behalve de eigen control-events geignoreerd
     * ignoreClickEvent = false betekent dat er wel naar click wordt geluisterd
     * belangrijk als je een <a href> ofzo in je content hebt.
     * {Boolean}
     */
    ignoreClickEvent: true,

  // DOM Elements

    /**
     * Property: layersDiv
     * {DOMElement}
     */
    layersDiv: null,

    /**
     * Property: minimizeDiv
     * {DOMElement}
     */
    minimizeDiv: null,

    /**
     * Property: maximizeDiv
     * {DOMElement}
     */
    maximizeDiv: null,

    /**
     * Constructor: OpenLayers.Control.LayerSwitcher
     *
     * Parameters:
     * options - {Object}
     */
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /**
     * APIMethod: destroy
     */
    destroy: function() {
        if (this.div)         OpenLayers.Event.stopObservingElement(this.div);
        if (this.minimizeDiv) OpenLayers.Event.stopObservingElement(this.minimizeDiv);
        if (this.maximizeDiv) OpenLayers.Event.stopObservingElement(this.maximizeDiv);
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },


    /**
     * Method: draw
     *
     * Returns:
     * {DOMElement} A reference to the DIV DOMElement containing the
     *     switcher tabs.
     */
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this);

        this.loadContents();

        // set mode to minimize
/*        if(!this.outsideViewport) {
            this.minimizeControl();
        }
*/
        this.maximizeControl();
        return this.div;
    },


    /**
     * Method: maximizeControl
     * Set up the labels and divs for the control
     *
     * Parameters:
     * e - {Event}
     */
    maximizeControl: function(e) {

        //HACK HACK HACK - find a way to auto-size this layerswitcher
        if (this.width) {
            this.div.style.width = this.width;
        } else {
            this.div.style.width = "20em";
        }

        if (this.height) {
            this.div.style.height= this.height;
        } else {
            this.div.style.height = "";
        }

        this.showControls(false);

        if (e != null) {
            OpenLayers.Event.stop(e);
        }
    },

    /**
     * Method: minimizeControl
     * Hide all the contents of the control, shrink the size,
     *     add the maximize icon
     *
     * Parameters:
     * e - {Event}
     */
    minimizeControl: function(e) {

        this.div.style.width = "0px";
        this.div.style.height = "0px";

        this.showControls(true);

        if (e != null) {
            OpenLayers.Event.stop(e);
        }
    },

    /**
     * Method: showControls
     * Hide/Show all LayerSwitcher controls depending on whether we are
     *     minimized or not
     *
     * Parameters:
     * minimize - {Boolean}
     */
    showControls: function(minimize) {

        this.maximizeDiv.style.display = minimize ? "" : "none";
        this.minimizeDiv.style.display = minimize ? "none" : "";

        this.layersDiv.style.display = minimize ? "none" : "";
    },

    positie: function(top) {
        
        this.div.style.top = top;
    },

    /**
     * Method: loadContents
     * Set up the labels and divs for the control
     */
    loadContents: function() {

        //configure main div
        this.div.style.position = "absolute";
        this.positie(this.top);
        
        this.div.style.right = "0px";
        this.div.style.left = "";
        this.div.style.fontFamily = "sans-serif";
        this.div.style.fontWeight = "bold";
        this.div.style.marginTop = "3px";
        this.div.style.marginLeft = "3px";
        this.div.style.marginBottom = "3px";
        this.div.style.fontSize = "smaller";
        this.div.style.color = "white";
        this.div.style.backgroundColor = "transparent";

        OpenLayers.Event.observe(this.div, "mouseup",
            OpenLayers.Function.bindAsEventListener(this.mouseUp, this));

        if (this.ignoreClickEvent) {
            OpenLayers.Event.observe(this.div, "click",
                          this.clickEvent);
        }
        OpenLayers.Event.observe(this.div, "mousedown",
            OpenLayers.Function.bindAsEventListener(this.mouseDown, this));
        OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent);


        // layers list div
        this.layersDiv = document.createElement("div");
        this.layersDiv.id = this.id + "_layersDiv";
        this.layersDiv.style.paddingTop = "5px";
        this.layersDiv.style.paddingLeft = "10px";
        this.layersDiv.style.paddingBottom = "5px";
        this.layersDiv.style.paddingRight = "75px";
        this.layersDiv.style.backgroundColor = this.activeColor;
        this.layersDiv.innerHTML = this.content;

        // had to set width/height to get transparency in IE to work.
        // thanks -- http://jszen.blogspot.com/2005/04/ie6-opacity-filter-caveat.html
        //
        this.layersDiv.style.width = "100%";
        this.layersDiv.style.height = "100%";

        this.div.appendChild(this.layersDiv);

        OpenLayers.Rico.Corner.round(this.div, {corners: "tl bl",
                                        bgColor: "transparent",
                                        color: this.activeColor,
                                        blend: false});

        //OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
        OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.85);
        
        var imgLocation = OpenLayers.Util.getImagesLocation();
        var sz = new OpenLayers.Size(18,18);

        // maximize button div
        var img = imgLocation + 'layer-switcher-maximize.png';
        this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                    "OpenLayers_Control_MaximizeDiv",
                                    null,
                                    sz,
                                    img,
                                    "absolute");
        this.maximizeDiv.style.top = "5px";
        this.maximizeDiv.style.right = "0px";
        this.maximizeDiv.style.left = "";
        this.maximizeDiv.style.display = "none";
        OpenLayers.Event.observe(this.maximizeDiv, "click",
            OpenLayers.Function.bindAsEventListener(this.maximizeControl, this)
        );

        this.div.appendChild(this.maximizeDiv);

        // minimize button div
        var img = imgLocation + 'layer-switcher-minimize.png';
        var sz = new OpenLayers.Size(18,18);
        this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                    "OpenLayers_Control_MinimizeDiv",
                                    null,
                                    sz,
                                    img,
                                    "absolute");
        this.minimizeDiv.style.top = "5px";
        this.minimizeDiv.style.right = "0px";
        this.minimizeDiv.style.left = "";
        this.minimizeDiv.style.display = "none";
        OpenLayers.Event.observe(this.minimizeDiv, "click",
            OpenLayers.Function.bindAsEventListener(this.minimizeControl, this)
        );

        this.div.appendChild(this.minimizeDiv);
    },

    /**
     * Method: ignoreEvent
     *
     * Parameters:
     * evt - {Event}
     */
    ignoreEvent: function(evt) {
        OpenLayers.Event.stop(evt);
    },

    /**
     * Method: mouseDown
     * Register a local 'mouseDown' flag so that we'll know whether or not
     *     to ignore a mouseUp event
     *
     * Parameters:
     * evt - {Event}
     */
    mouseDown: function(evt) {
        this.isMouseDown = true;
        this.ignoreEvent(evt);
    },

    /**
     * Method: mouseUp
     * If the 'isMouseDown' flag has been set, that means that the drag was
     *     started from within the LayerSwitcher control, and thus we can
     *     ignore the mouseup. Otherwise, let the Event continue.
     *
     * Parameters:
     * evt - {Event}
     */
    mouseUp: function(evt) {

        if (this.isMouseDown) {
            this.isMouseDown = false;
            this.ignoreEvent(evt);
        }

    },

    CLASS_NAME: "OpenLayers.Control.InfoLayer"
});

