/*
  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)
// --------------------------------------------
{
  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, 
// --------------------------------------------
{
    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"
});

    /**
     * Method: DeleteMarkers
     * Dit is in principe clearMarker, met het verschil dat het de 
     * markers ook echt vernietigt en dus geheugen vrijgeeft
     */
    function DeleteMarkers(markerLayer) 
    {
    	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;
};

