
/**
 * @requires OpenLayers/Popup/Framed.js
 * @requires OpenLayers/Layer/Grid.js
 * @requires OpenLayers/Class.js
 * @requires OpenLayers/Util.js
 * $Workfile: atExtendOpenLayers.js $
 * $Revision: 30 $
 * $Modtime: 7/07/10 13:58 $
 * $Author: Peter.goulborn $ 
 */

/**
 * A class to provide an iShareMaps map as an OpenLayers layer
 */
OpenLayers.Layer.iShareMaps = OpenLayers.Class(OpenLayers.Layer.Grid, {

    DEFAULT_PARAMS: {
        'RequestType': 'OLMap',
		'MapID': -1,
		'ServiceAction': 'ZoomToLocation'
    },
    initialize: function(name, url, params, options) {
        var newArguments = [];
        newArguments.push(name, url, params, options);
        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);

        if (arguments.length > 0) {
            OpenLayers.Util.applyDefaults(
                           this.params,
                           this.DEFAULT_PARAMS
                           );
        }

        // unless explicitly set in options, if the layer is transparent, 
        // it will be an overlay
        if (options == null || options.isBaseLayer == null) {
            this.isBaseLayer = ((this.params.transparent != "true") && 
                                (this.params.transparent != true));
        }
    }, 
    /**
     * APIProperty: transitionEffect
     * {String} The transition effect to use when the map is panned or
     *     zoomed.  
     *
     * There are currently two supported values:
     *  - *null* No transition effect (the default).
     *  - *resize*  Existing tiles are resized on zoom to provide a visual
     *    effect of the zoom having taken place immediately.  As the
     *    new tiles become available, they are drawn over top of the
     *    resized tiles.
     */
    transitionEffect: 'resize',
    
    clone: function (obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.iShareMaps(this.name,
                                           this.url,
                                           this.params,
                                           this.options);
        }
        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },
    addTile:function(bounds,position) {
        return new OpenLayers.Tile.Image(this, position, bounds, 
                                         null, this.tileSize);
    },
    redraw: function(  ) {
		if( this.params.layers && this.params.layers.length ) {
			if ( this.params.layers.length === 0) {
				this.setVisibility(false);
				for( var i = 0;  i < this.grid.length; i++ ) {
				
					for( var j = 0; j < this.grid[i].length; j++) {
						var tile = this.grid[i][j];
						if( tile.backBufferTile ) {
							//tile.backBufferTile.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
						}
					}
				
				}
			}
			else {
				this.setVisibility(true);	
			}
		}
		OpenLayers.Layer.Grid.prototype.redraw.apply(
	        this, arguments
	    ); 
    },
    getURL: function (bounds) {
        bounds = this.adjustBounds(bounds);
		var centre = bounds.getCenterLonLat();
		
        var imageSize = this.getImageSize(); 
        this.view = {
					    mapwidth: imageSize.w,
						mapheight: imageSize.h,
					 	easting: centre.lon,
						northing: centre.lat,
						zoom: imageSize.w * this.map.getResolution()
					 }
        
        var url = this.getFullRequestString(this.view);
        
        return url;
    },
    getFullRequestString:function(newParams, altUrl) {
        // use layer's url unless altUrl passed in
        var url = (altUrl == null) ? this.url : altUrl;
        
        // create a new params hashtable with all the layer params and the 
        // new params together. then convert to string
        var allParams = OpenLayers.Util.extend({}, this.params);
        allParams = OpenLayers.Util.extend(allParams, newParams);
        var paramsString = OpenLayers.Util.getParameterString(allParams);
        
        // if url is not a string, it should be an array of strings, 
        // in which case we will deterministically select one of them in 
        // order to evenly distribute requests to different urls.
        if (url instanceof Array) {
            url = this.selectUrl(paramsString, url);
        }   
        
        // ignore parameters that are already in the url search string
        var urlParams = OpenLayers.Util.upperCaseObject(
                            OpenLayers.Util.getParameters(url));
        for(var key in allParams) {
            if(key.toUpperCase() in urlParams) {
                delete allParams[key];
            }
        }
        paramsString = OpenLayers.Util.getParameterString(allParams);
        
        // requestString always starts with url
        var requestString = url;        
     
        if (paramsString != "") {
            var lastServerChar = url.charAt(url.length - 1);
            if ((lastServerChar == "&") || (lastServerChar == "?")) {
                requestString += paramsString;
            } else {
                if (url.indexOf('?') == -1) {
                    //serverPath has no ? -- add one
                    requestString += '?' + paramsString;
                } else {
                    //serverPath contains ?, so must already have paramsString at the end
                    requestString += '&' + paramsString;
                }
            }
        }
        return requestString;
    },

    CLASS_NAME: "OpenLayers.Layer.iShareMaps"
});


/**
 * A class to provide an iShareMaps with background raster as an OpenLayers layer. 
 * Using old call to provide image with basemap and datamap combined.
 */
OpenLayers.Layer.iShareMaps.Combo = OpenLayers.Class(OpenLayers.Layer.iShareMaps, {

    DEFAULT_PARAMS: {
        'RequestType': 'Map'
    },

    CLASS_NAME: "OpenLayers.Layer.iShareMaps.Combo"
});

OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {                
	defaultHandlerOptions: {
	    'single': true,
	    'double': true,
	    'pixelTolerance': 0,
	    'stopSingle': false,
	    'stopDouble': false
	},
	initialize: function(options, callbacks) {
	    this.handlerOptions = OpenLayers.Util.extend(
	    	this.defaultHandlerOptions, options
	    );
		callbacks = OpenLayers.Util.extend(
			{'click': this.defaultClick, 'dblclick': this.defaultDoubleClick}, callbacks
		);
	    OpenLayers.Control.prototype.initialize.apply(
	        this, arguments
	    ); 
	    this.handler = new OpenLayers.Handler.Click(
	        this, 
			{
	            'click': callbacks.click,
	            'dblclick': callbacks.dblclick
	        }, 
			this.handlerOptions
	    );
	}, 
	defaultClick: function(evt) {
		//evt.xy is OpenLayers.Pixel
		var clickPixel = evt.xy;
		var clickLonLat = this.map.getLonLatFromPixel(clickPixel);
	    alert("Single click at: \n" + clickLonLat + " \n" + clickPixel);
	},
	defaultDoubleClick: function(evt) {  
		var clickPixel = evt.xy;
		var clickLonLat = this.map.getLonLatFromPixel(clickPixel);
	    alert("Double click at: \n" + clickLonLat + " \n" + clickPixel);
	}  
});


OpenLayers.Control.Hover = OpenLayers.Class(OpenLayers.Control, {                
    defaultHandlerOptions: {
        'delay': 500,
        'pixelTolerance': null,
        'stopMove': false
    },

    initialize: function(options, callbacks) {
        this.handlerOptions = OpenLayers.Util.extend(
            this.defaultHandlerOptions, options
        );		
		callbacks = OpenLayers.Util.extend(
			{'pause': this.defaultPause, 'move': this.defaultMove}, callbacks
		);
        OpenLayers.Control.prototype.initialize.apply(
            this, arguments
        ); 
        this.handler = new OpenLayers.Handler.Hover(
            this,
            {
				'pause': callbacks.pause,
				'move': callbacks.move
			},
            this.handlerOptions
        );
    }, 

    defaultPause: function(evt) {
		//evt.xy is OpenLayers.Pixel
        alert('pause ' + evt.xy);
       
    },

    defaultMove: function(evt) {
		//evt.xy is OpenLayers.Pixel
        // if this control sent an Ajax request when
        // the mouse pauses the onMove callback could
        //  be used to abort that request.
    }
});



OpenLayers.Control.Drag = OpenLayers.Class(OpenLayers.Control, {               
    defaultHandlerOptions: {
		'stopDown': false
    },

    initialize: function(callbacks) {
		callbacks = OpenLayers.Util.extend(
			{
				'move': function( pixel ) {
					// pixel - { Openlayers.Pixel }
					       
				},

				'done': function(pixel) {
					// pixel - { Openlayers.Pixel }
				},

				'down': function(pixel) {
					// pixel - { Openlayers.Pixel }
				},

				'up': function(pixel) {
					// pixel - { Openlayers.Pixel }
				},

				'out': function(pixel) {
					// pixel - { Openlayers.Pixel }
				}
			}, 
			callbacks
		);
        OpenLayers.Control.prototype.initialize.apply(
            this, arguments
        ); 
        this.handler = new OpenLayers.Handler.Drag(
            this,
            callbacks,
            this.defaultHandlerOptions
        );
    } 

   
});

/**
 * Class: OpenLayers.Popup.FramedCompact
 * 
 * Inherits from: 
 *  - <OpenLayers.Popup.Framed>
 */
OpenLayers.Popup.FramedCompact = 
  OpenLayers.Class(OpenLayers.Popup.Framed, {
 	/** 
     * Constructor: OpenLayers.Popup.FramedCompact
     * 
     * Parameters:
     * id - {String}
     * lonlat - {<OpenLayers.LonLat>}
     * contentSize - {<OpenLayers.Size>}
     * contentHTML - {String}
     * anchor - {Object} Object to which we'll anchor the popup. Must expose 
     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>) 
     *     (Note that this is generally an <OpenLayers.Icon>).
     * closeBox - {Boolean}
     * closeBoxCallback - {Function} Function to be called on closeBox click.
     */
    initialize: function(id, lonlat, contentSize, contentHTML, anchor, closeBox, 
                        closeBoxCallback, image) {

        //this.imageSrc = OpenLayers.Util.getImagesLocation() + 'Cloud-popup-relative.png'; Should Astun do something like this?
        this.imageSrc  = image;
        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments);
        this.contentDiv.className = this.contentDisplayClass;
    },

    /** 
     * Property: displayClass
     * {String} The CSS class of the popup.
     */
    displayClass: "olPopup olFramedCompactPopup",
    
    /** 
     * Property: contentDisplayClass
     * {String} The CSS class of the popup content div.
     */
    contentDisplayClass: "olFramedCompactPopupContent",

    /**
     * Property: autoSize
     * {Boolean} FramedCompact is autosizing by default.
     */
    autoSize: true,

    /**
     * Property: panMapIfOutOfView
     * {Boolean} FramedCompact does pan into view by default.
     */
    panMapIfOutOfView: true,

    /**
     * Property: imageSize
     * {<OpenLayers.Size>}
     */
    imageSize: new OpenLayers.Size(676, 736),

    /**
     * Property: isAlphaImage
     * {Boolean} The FramedCompact does not use an alpha image (in honor of the 
     *     good ie6 folk out there)
     */
    isAlphaImage: false,

    /** 
     * Property: fixedRelativePosition
     * {Boolean} The FramedCompact popup works in just one fixed position.
     */
    fixedRelativePosition: false,
    

    /**
     * Property: positionBlocks
     * {Object} Hash of different position blocks, keyed by relativePosition
     *     two-character code string (ie "tl", "tr", "bl", "br")
     */
    positionBlocks: {
        "tl": {
            'offset': new OpenLayers.Pixel(0, 0),
            'padding': new OpenLayers.Bounds(5, 10, 10, 5),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 10, 10, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(5, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 10, 5, 0),
                    position: new OpenLayers.Pixel(-655, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 5),
                    anchor: new OpenLayers.Bounds(0, 5, 10, null),
                    position: new OpenLayers.Pixel(0, -645)
                },
                { //bottom-right
                    size: new OpenLayers.Size(5, 5),
                    anchor: new OpenLayers.Bounds(null, 5, 5, null),
                    position: new OpenLayers.Pixel(-655, -645)
                },
                { // stem
                    size: new OpenLayers.Size(10, 10),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(-225, -712)
                }
            ]
        },
        "tr": {
            'offset': new OpenLayers.Pixel(0, 0),
            'padding': new OpenLayers.Bounds(10, 10, 5, 5),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(5, 10, 5, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(5, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 10, 0, 0),
                    position: new OpenLayers.Pixel(-655, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 5),
                    anchor: new OpenLayers.Bounds(5, 5, 5, null),
                    position: new OpenLayers.Pixel(0, -645)
                },
                { //bottom-right
                    size: new OpenLayers.Size(5, 5),
                    anchor: new OpenLayers.Bounds(null, 5, 0, null),
                    position: new OpenLayers.Pixel(-655, -645)
                },
                { // stem
                    size: new OpenLayers.Size(10, 10),
                    anchor: new OpenLayers.Bounds(0, 0, null, null),
                    position: new OpenLayers.Pixel(-215, -712)
                }
            ]
        },
        "bl": {
            'offset': new OpenLayers.Pixel(0, 0),
            'padding': new OpenLayers.Bounds(5, 5, 10, 10),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 5, 10, 5),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(5, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 5, 5, 5),
                    position: new OpenLayers.Pixel(-655, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 5),
                    anchor: new OpenLayers.Bounds(0, 0, 10, null),
                    position: new OpenLayers.Pixel(0, -645)
                },
                { //bottom-right
                    size: new OpenLayers.Size(5, 5),
                    anchor: new OpenLayers.Bounds(null, 0, 5, null),
                    position: new OpenLayers.Pixel(-655, -645)
                },
                { // stem
                    size: new OpenLayers.Size(10, 10),
                    anchor: new OpenLayers.Bounds(null, null, 0, 0),
                    position: new OpenLayers.Pixel(-225, -702)
                }
            ]
        },
        "br": {
            'offset': new OpenLayers.Pixel(0, 0),
            'padding': new OpenLayers.Bounds(10, 5, 10, 10),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(5, 5, 10, 5),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(5, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 5, 5, 5),
                    position: new OpenLayers.Pixel(-655, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 5),
                    anchor: new OpenLayers.Bounds(5, 0, 10, null),
                    position: new OpenLayers.Pixel(0, -645)
                },
                { //bottom-right
                    size: new OpenLayers.Size(5, 5),
                    anchor: new OpenLayers.Bounds(null, 0, 5, null),
                    position: new OpenLayers.Pixel(-655, -645)
                },
                { // stem
                    size: new OpenLayers.Size(10, 10),
                    anchor: new OpenLayers.Bounds(0, null, null, 0),
                    position: new OpenLayers.Pixel(-215, -702)
                }
            ]
        }
    },

    /**
     * Property: minSize
     * {<OpenLayers.Size>}
     */
    minSize: new OpenLayers.Size(15, 15),

    /**
     * Property: maxSize
     * {<OpenLayers.Size>}
     */
    maxSize: new OpenLayers.Size(600, 660),

    /** 
     * Method: calculateRelativePosition
     * 
     * Parameters:
     * px - {<OpenLayers.Pixel>}
     * 
     * Returns:
     * {String} The relative position ("br" "tr" "tl" "bl") at which the popup
     *     should be placed. Also updates class of groupDiv accordingly.
     */
    calculateRelativePosition:function(px) {
        var quadrant = OpenLayers.Popup.Framed.prototype.calculateRelativePosition.apply(this, arguments);
        this.groupDiv.className = 'olQuadrant-' + quadrant;
        return quadrant;
    }, 
   
    /** 
     * Method: destroy
     */
    destroy: function() {
        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Popup.FramedCompact"
});

/**
 * Class: OpenLayers.Popup.FramedMarker
 * 
 * Inherits from: 
 *  - <OpenLayers.Popup.FramedCompact>
 */
OpenLayers.Popup.FramedMarker = 
  OpenLayers.Class(OpenLayers.Popup.FramedCompact, {

    /**
     * Property: minSize
     * {<OpenLayers.Size>}
     */
    minSize: new OpenLayers.Size(25, 15),

    /** 
     * Property: displayClass
     * {String} The CSS class of the popup.
     */
    displayClass: "olPopup olFramedMarkerPopup",
    /** 
     * Property: contentDisplayClass
     * {String} The CSS class of the popup content div.
     */
    contentDisplayClass: "olFramedMarkerPopupContent",
    /**
     * Method: onclick
     * Ignore clicks, but allowing default browser handling
     * 
     * Parameters:
     * evt - {Event} 
     */
    onclick: function (evt) {
        if(jQuery) jQuery(this.contentDiv).trigger('popUpClicked',[evt]);
		OpenLayers.Event.stop(evt, true);
    },
    CLASS_NAME: "OpenLayers.Popup.FramedMarker"
});


/**
 * @requires OpenLayers/Control.js
 * @requires OpenLayers/Handler/Drag.js
 * @requires OpenLayers/Control/DragPan.js
 */

/**
 * Class: OpenLayers.Control.DragPanExt
 * The DragPan control pans the map with a drag of the mouse.
 *
 * Inherits from:
 *  - <OpenLayers.Control.DragPan>
 */
OpenLayers.Control.DragPanExt = OpenLayers.Class(OpenLayers.Control.DragPan, {
    
    /**
     * Method: draw
     * Creates a Drag handler, using <panMap> and
     * <panMapDone> as callbacks.
     */    
    draw: function() {
        this.handler = new OpenLayers.Handler.Drag(this, {
                "move": this.panMap,
                "done": this.panMapDone
            }, {
                interval: this.interval,
                keyMask: this.keyMask
            }
        );
    },


    CLASS_NAME: "OpenLayers.Control.DragPanExt"
});


