﻿OpenLayers.Control.GetFeatures = OpenLayers.Class(OpenLayers.Control, {
    /**
    * Constant: EVENT_TYPES
    *
    * Supported event types:
    * featuresretrieved - Triggered when features are retrieved from the layers
    *  The event object has a features property with an array of features
    */
    EVENT_TYPES: ["featuresretrieved"],

    defaultHoverHandlerOptions: {
        'delay': 500,
        'pixelTolerance': null,
        'stopMove': false
    },

    /**
    * APIProperty: clickTolerance
    * {OpenLayers.Size} Tolerance for the BBOX query in pixels. Default is 5x5.
    */
    clickTolerance: new OpenLayers.Size(5, 5),

    layers: null,

    initialize: function(layers, options) {
        // concatenate events specific to vector with those from the base
        this.EVENT_TYPES =
            OpenLayers.Control.GetFeatures.prototype.EVENT_TYPES.concat(
            OpenLayers.Control.prototype.EVENT_TYPES
        );

        this.layers = layers;

        this.hoverHandlerOptions = OpenLayers.Util.extend(
                        {}, this.defaultHoverHandlerOptions
                    );
        OpenLayers.Control.prototype.initialize.apply(
                        this, [options]
                    );
        this.handler = new OpenLayers.Handler.Hover(
                        this,
                        { 'pause': this.onPause, 'move': this.onMove },
                        this.hoverHandlerOptions
                    );
    },

    onPause: function(evt) {
        var lonlat = this.map.getLonLatFromPixel(evt.xy);
        var bounds = this.pixelToBounds(evt.xy);
        var polygon = bounds.toGeometry();
        var features = [];

        for (var i = 0; i < this.layers.length; i++) {
        	if (this.layers[i].visibility && this.layers[i].features) {
                for (var j = 0; j < this.layers[i].features.length; j++) {
                    if (this.layers[i].features[j].geometry && polygon.intersects(this.layers[i].features[j].geometry)) {
                        features.push(this.layers[i].features[j]);
                    }
                }
            }
            //might implement functionality for non vector layers such as WMS
        }

        if (features.length > 0) {
            this.events.triggerEvent("featuresretrieved", { lonlat: lonlat, features: features });
        }
    },

    /**
    * Method: pixelToBounds
    * Takes a pixel as argument and creates bounds after adding the
    * <clickTolerance>.
    * 
    * Parameters:
    * pixel - {<OpenLayers.Pixel>}
    */
    pixelToBounds: function(pixel) {
        var llPx = pixel.add(-this.clickTolerance.w / 2, this.clickTolerance.w / 2);
        var urPx = pixel.add(this.clickTolerance.h / 2, -this.clickTolerance.h / 2);
        var ll = this.map.getLonLatFromPixel(llPx);
        var ur = this.map.getLonLatFromPixel(urPx);
        return new OpenLayers.Bounds(ll.lon, ll.lat, ur.lon, ur.lat);
    },

    onMove: function(evt) {
        // if this control sent an Ajax request (e.g. GetFeatureInfo) when
        // the mouse pauses the onMove callback could be used to abort that
        // request.
    }
});
