/**
* $Workfile: atolLayerControl.js $
* $Revision: 95 $
*  $Modtime: 5/11/09 12:16 $
*   $Author: Peter.goulborn $ 
* 
* Class: Astun.iSharemaps.OLUIControl
* Controls iShareMaps layers in extended OpenLayers maps.  Instances of this
* class are created with the <Astun.iSharemaps.OLUIControl> consructor.  
*/
if (!OpenLayers || !Prototype) throw new Error('Dependent library not found');  // Needs to be nicer, possibly iSharemaps-wide library error?

if (!Astun) var Astun = {};
if (!Astun.iSharemaps) Astun.iSharemaps = {};
Astun.iSharemaps.OLLayerControl = Class.create(
{
    /**
    * Constructor: Astun.iSharemaps.OLUIControl
    * Create a new iShareMaps layer control object. This class interacts 
    *     with Astun.iSharemaps.OLMap objects to set the displayed layers.
    *
    * Parameters:
    * layergroups - {Array} Array of layergroups
    * atolMap - {<Astun.iSharemaps.OLMap>} Astun iShareMaps wrapper for
    *     OpenLayers map object.
    */
    initialize: function(atolMap, mapSource, forceThematic) {
        this.queryHandler = new Astun.JS.Common.QueryHandler({
            'layers': 'l',
            'loadThematic': ''
        });

        var urlLayers = this.queryHandler.getParameter('layers');
        if (urlLayers) {
            if (!Object.isArray(urlLayers)) {
                urlLayers = [urlLayers];
            }
            var original = urlLayers.length;
            for (var l = 0; l < original; l++) {
                var layers = urlLayers.shift();
                layers = layers.split(',');
                while (layers.length) {
                    urlLayers.push(layers.pop() + ''.trim());  //make sure we try to trim string, if this array member is not a string then it should end up just being ignored
                }
            }
            this.urlLayers = urlLayers;
        }

        var urlLoadThematic = this.queryHandler.getParameter('loadThematic');
        var urlForceThematic;

        if (urlLoadThematic === 'off' || urlLoadThematic === 'no' || urlLoadThematic === 'false' || urlLoadThematic === '0') {
            urlForceThematic = 'off';
        }
        else if (urlLoadThematic === 'on' || urlLoadThematic === 'yes' || urlLoadThematic === 'true' || urlLoadThematic === '1' || urlLoadThematic === '') {
            urlForceThematic = 'on';
        }

        this.thematicInfo = {};
        this.thematicInfo.force = forceThematic || urlForceThematic;

        this.mapWrapper = atolMap;
        this.layerGroups = $A([]);
        this.geometrySources = $H();
        //keep currently displayed theme info
        //keep cached data Json string
        this.themeDataSources = $H();
        //if current theme being processed
        this.thematicInfo.themeBeingProcessed = false;
        this.cutOffDate = new Date();
        if (mapSource && mapSource.layerGroups) {
            this.importLayerGroups(mapSource.layerGroups);
        }
        this.defaultStyleMap = new OpenLayers.StyleMap({
            'default': {
                fillColor: '#eeeeee',
                fillOpacity: 0.3,
                strokeColor: '#333333',
                strokeOpacity: 0.5,
                strokeWidth: 1
            }
        });

        var toggleHomeFeatureEvent = function(evt) {
            this.toggleHomeFeature(evt.memo);
        }
        
        var showResultsLayerEvent = function( evt ) {
			this.showLayer( evt.memo.displayName );
        }
        
        var layerControl = this;
        
        Event.observe(this.mapWrapper.mapElement, 'astun:resultsReceived', showResultsLayerEvent.bindAsEventListener(this));
			       
        Event.observe(this.mapWrapper.mapElement, 'astun:setHomeFeature', toggleHomeFeatureEvent.bindAsEventListener(this));
		if( jQuery ) {
			var $eventElement = jQuery( '#' + this.mapWrapper.mapElement.id );
			$eventElement.bind( 'toggleLayer', function( evt, layerName ) {
				if( layerName ) {
					layerControl.toggleLayer( layerName );
				}
			} );
			$eventElement.bind( 'hideLayer', function( evt, layerName ) {
				if( layerName ) {
					layerControl.hideLayer( layerName );
				}
			} );
			$eventElement.bind( 'showLayer', function( evt, layerName ) {
				if( layerName ) {
					layerControl.showLayer( layerName );
				}
			} );
			$eventElement.bind( 'showLayerGroup', function( evt, groupName ) {
				if( groupName ) {
					layerControl.showLayerGroup( groupName );
				}
			} );
			$eventElement.bind( 'hideLayerGroup', function( evt, groupName ) {
				if( groupName ) {
					layerControl.hideLayerGroup( groupName );
				}
			} );
		}
    },
	reset: function() {
		this.layerGroups = $A([]);
        this.geometrySources = $H();
        this.themeDataSources = $H();
        this.thematicInfo.themeBeingProcessed = false;
        this.cutOffDate = new Date();
	},
    getAllGroupDisplayName: function() {
        /**
        * Function: getAllGroupDisplayName
        * To return all the layergroups display name in a concatenated string, used for debugging.
        *
        * Parameters:
        * 
        * Returns:
        * {string} 
        */
        var strText = "";
        for (var gj = 0; gj < this.layerGroups.length; gj++)
            strText += " " + this.getGroupDisplayName(gj) + ";" + " \n ";
        return strText;
    },

    getGroupDisplayName: function(grpNO) {
        /**
        * Function: getGroupDisplayName
        * To return all the displayName of a layerGroup,  used for debugging.
        *
        * Parameters:
        * grpNO - {number} The index of the groupd in the layerGroups array
        *
        * Returns:
        * {string} The displayName of the layerGroup
        */

        return this.layerGroups[grpNO].displayName;
    },

    getLayersProperties: function(lyrGrp) {
        /**
        * Function: getLayersProperties
        * To return all the set properties for all layers in a layerGroup, used for debugging.
        *
        * Parameters:
        * lyrGrp - {number} The index of the groupd in the layerGroups array
        *
        * Returns:
        * {string} Concatenated string of all the properties
        */
        var strTxt = '';
        strTxt = " Layer Group displayName: " + this.layerGroups[lyrGrp].displayName + " \n ";
        var aj = 0;
        for (aj = 0; aj < this.layerGroups[lyrGrp].layers.length; aj++) {
            strTxt += "\n" + this.layerGroups[lyrGrp].layers[aj].layerName;
            strTxt += "\n" + this.layerGroups[lyrGrp].layers[aj].displayName;
            strTxt += "\n" + this.layerGroups[lyrGrp].layers[aj].initiallyVisible;
            strTxt += "\n" + this.layerGroups[lyrGrp].layers[aj].currentlyVisible;
        }
        return strTxt;
    },

    addLayerGroup: function(group) {
        /**
        * Function: addLayerGroup
        * Add a layerGroup to the layerControl object.
        *
        * Parameters:
        * group - {object} A layerGroup
        *
        * Returns:
        *
        */
        var newGroup = new LayerGroup(group.displayName, group.guid);
        if (group.themeFields) {
            newGroup.themeFields = group.themeFields;
        }
        var addLayer = this.addLayer.bind(this);
        newGroup.addLayer = addLayer.methodize();
        newGroup.mapWrapper = this.mapWrapper;
        if (group.layers.length) {
            var layers = $A(group.layers);
            for (var i = 0; i < layers.length; i++) {
                newGroup.addLayer(layers[i]);
                //newGroup.layers.push(layers[i]) ; // prak 26/9
                layers[i].currentlyVisible = false;
                if (layers[i].initiallyVisible) {
                    layers[i].show( true );
                }
            }
        }
        this.layerGroups.push(newGroup);
    },


    addLayer: function(group, layer) {
        /**
        * Function: addLayer
        * Add a layer to a layerGroup object.
        *
        * Parameters:
        * group - {object} A layerGroup
        * layer - {object} A layer
        *
        * Returns:
        *
        */
        layer.group = group;
        layer.show = function( force ) {
            if ( force || ( this.active && !this.currentlyVisible ) ) {
                switch (this.type) {
                    case 'base':
                        this.group.mapWrapper.addISMLayer(this.layerName);
                        if (!this.group.mapWrapper.ismDataLayer.visibility) {
                            this.group.mapWrapper.ismDataLayer.setVisibility(true);
                        }
                        else {
                            this.group.mapWrapper.draw();
                        }
                        this.group.activeShown++;
                        this.currentlyVisible = true;
                        this.group.mapWrapper.mapElement.fire('astun:saveSetting', { setting: 'visibleLayers', value: '' + this.group.mapWrapper.ismDataLayer.params.layers });
                        this.group.mapWrapper.mapElement.fire('astun:layerShow', { layer: this });
                        if( jQuery ) {
							jQuery( '#' + this.group.mapWrapper.mapElement.id ).trigger( 'layerShown',  this.layerName);
							if( this.group.activeShown == this.group.activeLayers.length ) {
								jQuery( '#' + this.group.mapWrapper.mapElement.id ).trigger( 'layerGroupShown',  this.displayName );
							}
						
						}
						
                        break;
                    case 'thematic':
                        // do nothing - at the moment only toggle is available
                        break;
                    default:
                        break;
                }
            }
        };

        layer.hide = function() {
            /**
            * Function: hide, function of the layer object
            * Turn off the visibility of a layer.
            *
            * Parameters:
            *
            * Returns:
            *
            */
            if (this.active && this.currentlyVisible) {
                switch (this.type) {
                    case 'base':
                        this.group.mapWrapper.removeISMLayer(this.layerName);
                        if (this.group.mapWrapper.ismDataLayer.params.layers.length) {
                            this.group.mapWrapper.draw();
                        }
                        else {
                            this.group.mapWrapper.ismDataLayer.setVisibility(false);
                        }
                        this.group.activeShown--;
                        this.currentlyVisible = false;
                        this.group.mapWrapper.mapElement.fire('astun:saveSetting', {
                            setting: 'visibleLayers',
                            value: '' + this.group.mapWrapper.ismDataLayer.params.layers
                        });
                        this.group.mapWrapper.mapElement.fire("astun:layerHide", {
                            layer: this
                        });
                        if( jQuery ) {
							jQuery( '#' + this.group.mapWrapper.mapElement.id ).trigger( 'layerHidden',  this.layerName);
							if( this.group.activeShown == 0 ) {
								jQuery( '#' + this.group.mapWrapper.mapElement.id ).trigger( 'layerGroupHidden',  this.displayName );
							}
						}
                    case 'thematic':
                        // do nothing - at the moment only toggle is available
                        break;
                    default:
                        break;
                }
            }
        };

        layer.toggle = function() {
            /**
            * Function: toggle, function of the layer object
            * Turn off the visibility of a layer if layer currently visible or ON if not currently visible.
            *
            * Parameters:
            *
            * Returns:
            *
            */
            if (this.toggleThematic) {
                this.toggleThematic();
            }
            else if (this.currentlyVisible) {
                this.hide();
            }
            else {
                this.show();
            }
        }
        group.layers.push(layer);
        if (layer.active) {
            switch (layer.type) {
                case 'base':
                    group.activeLayers.push(layer);
                    break;
                case 'thematic':
                    group.thematicLayers.push(layer);
                    var toggler = this.toggleThematic.bind(this);
                    layer.toggleThematic = toggler.curry(layer.layerName, layer.layerName); //NOTE: remove second argument when events not handled directly by toggleThematic
                    var reloader = this.reloadThematic.bind(this)
                    layer.reload = reloader.methodize();
                    break;
            }

        }
    },

    importLayerGroups: function(mapSource) {
        /**
        * Function: importLayerGroups, 
        * Creates layerGroups on the layerControl object from a Json string
        *
        * Parameters:
        * mapSource - {object} Json object
        *
        * Returns:
        *
        */ 
        this.reset();
        for (var i = 0; i < mapSource.layerGroups.length; i++) {
            this.addLayerGroup(mapSource.layerGroups[i]);
        }
        var loadVisibleLayers = function(layersString) {
            if (!!layersString) {
                var layerArray = layersString.split(',');
                this.showLayers(layerArray);
            }
        };
        if (this.urlLayers) {
            this.showLayers(this.urlLayers);
        }
        else {
            this.mapWrapper.mapElement.fire('astun:loadSetting', { setting: 'visibleLayers', loadFunction: loadVisibleLayers.bind(this) });
        }

        var loadVisibleThematic = function(thematicName) {
            if (!!thematicName && !!this.findLayer(thematicName)) {
                this.toggleThematic(thematicName, thematicName); //toggleThematic needs to be fixed to rely only on string passed as first argument
            }
            else if (this.thematicInfo.force) {
                for (var groupId = 0, groupLimit = this.layerGroups.length; groupId < groupLimit; ++groupId) {
                    var groupObject = this.layerGroups[groupId];
                    if (groupObject.thematicLayers.length) {
                        var thematicName = groupObject.thematicLayers[0].layerName;
                        this.toggleThematic(thematicName, thematicName); //toggleThematic needs to be fixed to rely only on string passed as first argument
                    }
                }
            }
        };
        if (!(this.thematicInfo.force && this.thematicInfo.force == 'off')) {
            this.mapWrapper.mapElement.fire('astun:loadSetting', { setting: 'visibleThematic', loadFunction: loadVisibleThematic.bind(this) });
        }
        this.mapWrapper.mapElement.fire("astun:sourceLoad", { layerControl: this, mapSource: mapSource });
    },


    findLayer: function(lyrName) {
        /**
        * Function: findLayer, 
        * Returns a layer Object whose properties 'layerName' or 'displayName' 
        * equal passed string or null if none found. Layer name 
        * takes precedence - all layers are searched for that first.
        *
        * Parameters:
        * lyrName - {string} String to match 'layerName'/'displayName'
        *
        * Returns:
        * {object} - Layer object or null.
        *
        */
        for (var i = 0; i < this.layerGroups.length; i++) {
            for (var j = 0; j < this.layerGroups[i].layers.length; j++) {
                if (this.layerGroups[i].layers[j].layerName == lyrName) {
                    return this.layerGroups[i].layers[j];
                }
            }
        }
        for (var i = 0; i < this.layerGroups.length; i++) {
            for (var j = 0; j < this.layerGroups[i].layers.length; j++) {
                if (this.layerGroups[i].layers[j].displayName == lyrName) {
                    return this.layerGroups[i].layers[j];
                }
            }
        }
        return null;
    },
	
    hideLayer: function(lyrName) {
        /**
        * Function: hideLayer, 
        * Turn off the visiblity of a layer on the map display. Method of the layerControl object.
        *
        * Parameters:
        * lyrName - {string} String to match 'layerName' of layer
        *
        * Returns:
        *
        */
        var lyr = this.findLayer(lyrName)
        if (lyr) {
            lyr.hide();
        }
    },

    showLayer: function(lyrName) {
        /**
        * Function: hideLayer, 
        * Turn On the visiblity of a layer on the map display. Method of the layerControl object.
        *
        * Parameters:
        * lyrName - {string} String to match 'layerName' of layer
        *
        * Returns:
        *
        */
        var lyr = this.findLayer(lyrName)
        if (lyr) {
            lyr.show();
        }
    },
	
    toggleLayer: function(lyrName) {
        /**
        * Function: toggleLayer, 
        * Turn On the visiblity of a layer on the map display. Method of the layerControl object.
        *
        * Parameters:
        * lyrName - {string} String to match 'layerName' of layer
        *
        * Returns:
        *
        */
        var lyr = this.findLayer(lyrName)
        if (lyr) {
            lyr.toggle();
        }
    },
    showLayers: function(lyrNameArray) {
        /**
        * Function: showLayers, 
        * Turn On the visiblity of all layer on the map display for a given array of layerNames.
        *
        * Parameters:
        * lyrNameArray - {Array} of layer names
        *
        * Returns:
        *
        */
        var tmpArray = lyrNameArray.slice(0);
        while (tmpArray.length) {
            this.showLayer(tmpArray.shift())
        }
    },

    findLayerGroup: function(layerGroupName) {
        /**
        * Function: findLayerGroup, 
        * Return a layerGroup object with a matching displayName, null if not found
        *
        * Parameters:
        * layerGroupName - {string} Matching displayName of grooup to be returned
        *
        * Returns:
        * {object} - layerGroup object
        */
        for (var i = 0; i < this.layerGroups.length; i++) {
            if (this.layerGroups[i].displayName == layerGroupName) {
                bLyrFound = true;
                return this.layerGroups[i];
            }
        }
        return;
    },


    showLayerGroup: function(layerGroupName) {
        /**
        * Function: showLayerGroup, 
        * Turns ON map visibility of all layers within a layerGroup with matching display name.
        *
        * Parameters:
        * layerGroupName - {string} Matching displayName of grooup to be returned
        *
        * Returns:
        */
        var layerGroup = this.findLayerGroup(layerGroupName);
        layerGroup.showLayers();
        //$(this.group.mapWrapper.mapElement).fire("astun:showLayerGroup", {layerGroup: this});
    },

    hideLayerGroup: function(layerGroupName) {
        /**
        * Function: hideLayerGroup, 
        * Turns OFF map visibility of all layers within a layerGroup with matching display name.
        *
        * Parameters:
        * layerGroupName - {string} Matching displayName of grooup to be returned
        *
        * Returns:
        */
        var layerGroup = this.findLayerGroup(layerGroupName);
        layerGroup.hideLayers();
        //$(this.group.mapWrapper.mapElement).fire("astun:showLayerGroup", {layerGroup: this});
    },


    reloadThematic: function(oLayer) {
        /**
        * Function: reloadThematic, 
        * Reloads the thematic layer corresponding to the layer with theme defined.
        *
        * Parameters:
        * oLayer - {object} layer object with theme
        *
        * Returns:
        */
        //return if already theme being processed.		
        if (this.thematicInfo.themeBeingProcessed) {
            return;
        }
        //indicate a theme being processed
        this.thematicInfo.themeBeingProcessed = true;
        this.mapWrapper.mapElement.fire('astun:themeLoadBegin', {});
        var oThematicMapLayer = this.findThematicMapLayer();
        //this.mapWrapper.map.removeLayer(oThematicMapLayer);
        //this.createThematicLayer(oLayer);	
        this.mapWrapper.clearPopups();
        this.getThematicRules(oThematicMapLayer, oLayer);
        this.thematicLayerFinished(oThematicMapLayer, oLayer, true)
    },

    toggleThematic: function(lyrName) {
        /**
        * Function: toggleThematic 
        * Turns ON map visibility of the theme for a layer with matching name if not already visible
        * Or Turns OFF map visibility of the theme for a layer with matching name if already visible
        *
        * Parameters:
        * lyrName - {string} layerName for layer object
        *
        * Returns:
        */
        //return if already theme being processed.		
        if (this.thematicInfo.themeBeingProcessed) {
            return;
        }

        var sCutOffDate = this.mapWrapper.date;
        var iMonth = sCutOffDate.substring(5, 7) - 1;
        this.cutOffDate.setFullYear(sCutOffDate.substring(0, 4), iMonth, sCutOffDate.substring(8, 10));

        var data = $A(arguments);
        lyrName = data[1];

        var oLayer = this.findLayer(lyrName);
        var oThematicMapLayer = this.findThematicMapLayer();

        //indicate a theme being processed
        this.thematicInfo.themeBeingProcessed = true;
        this.mapWrapper.mapElement.fire('astun:themeLoadBegin', {});

        if (!this.mapWrapper.map.thematic) {
            this.mapWrapper.map.thematic = {};
        }

        this.mapWrapper.map.thematic.homeEn = new OpenLayers.LonLat(this.mapWrapper.currentLocation.x, this.mapWrapper.currentLocation.y);

        if (!oThematicMapLayer) {
            this.createThematicLayer(oLayer);
            return;
        }

        //Themaric layer present, clear any popup and clear any graph displayed
        this.mapWrapper.clearPopups();
        $('homeWard').innerHTML = '';
        $('hoverWard').innerHTML = '';
        if (this.thematicInfo.layerName === oLayer.layerName && this.thematicInfo.columnName === oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex]) {
            var bLayerVisible = false;
            bLayerVisible = oThematicMapLayer.visibility;
            if (bLayerVisible) {
                this.thematicLayerFinished(oThematicMapLayer, oLayer, false);
            }
            else {
                this.thematicLayerFinished(oThematicMapLayer, oLayer, true);
                if (this.thematicInfo.homeFeature) {
                    this.mapWrapper.interactions.showHomeWardGraph(this.thematicInfo);
                }
            }
        }
        else {
            if (this.thematicInfo.geometrySource == oLayer.thematic.geometrySource) {
                this.getThematicRules(oThematicMapLayer, oLayer);
                this.thematicLayerFinished(oThematicMapLayer, oLayer, true);
            }
            else {
                this.mapWrapper.map.removeLayer(oThematicMapLayer);
                this.createThematicLayer(oLayer);
                this.thematicLayerFinished(oThematicMapLayer, oLayer, false);
            }
        }

    },

    findThematicMapLayer: function() {
        /**
        * Function: findThematicMapLayer 
        * search and retrun the thematic layer, if any
        *
        * Parameters:
        * 
        *
        * Returns:
        * {object) - the thematic layer or null
        */
        for (i = 0; i < this.mapWrapper.map.layers.length; i++) {
            if (this.mapWrapper.map.layers[i].name == 'thematicLayer')
                return this.mapWrapper.map.layers[i];
        }
        return null;
    },

    createThematicLayer: function(oLayer) {
        /**
        * Function: createThematicLayer 
        * Creates and show on map the thematic layer for a given layer object
        *
        * Parameters:
        * oLayer - {object} layer object
        *
        * Returns:
        */
        strGeometrySource = oLayer.thematic.geometrySource;
        var oJSon = this.geometrySources.get(strGeometrySource);
        if (!oJSon) {
            oJSon = this.getGeoJSONFromAjax(oLayer);
            return;
        }
        //update current datasource being looked at 
        this.thematicInfo.geometrySource = oLayer.thematic.geometrySource;
        var geojson = new OpenLayers.Format.GeoJSON();
        var oGeoJSON = geojson.read(oJSon, "FeatureCollection");
        this.generateThematicLayer(oLayer, oGeoJSON);
    },

    getThematicRules: function(oThematicMapLayer, oLayer) {
        /**
        * Function: getThematicRules 
        * Gets the thematic rules data
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * oLayer - {object} layer object	
        *
        * Returns:
        */
        //Initialise the rules object and destroy any previous ones
        oThematicMapLayer.styleMap = this.defaultStyleMap;
        // If auto = true get the ranges values thru AJAX call 
        if ((!oLayer.thematic.ranges.initialised) && oLayer.thematic.ranges.auto) {
            this.getThematicRangesFromAjax(oThematicMapLayer, oLayer);
            return;
        }
        this.applyThematicRules(oThematicMapLayer, oLayer);
    },

    applyThematicRules: function(oThematicMapLayer, oLayer) {
        /**
        * Function: applyThematicRules 
        * Creates the rules on the map thematic layer from the object theme rules data
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * oLayer - {object} layer object	
        *
        * Returns:
        */
        var sRuleName = '';
        var oRuleColour = {};
        var iLower = 0;
        var iUpper = 0;
        var oRules = [];
        var sPropertyToCompare = 'currentValue';
        for (i = 0; i < oLayer.thematic.ranges.range.length; i++) {
            //rules name, values and colour
            sRuleName = 'ruleNo' + i;
            oRuleColour = oLayer.thematic.ranges.range[i].colour;
            iLower = oLayer.thematic.ranges.range[i].low;
            iUpper = oLayer.thematic.ranges.range[i].high;
            var sRuleName = new OpenLayers.Rule(
			{
			    name: oLayer.thematic.ranges.range[i].label,
			    filter: new OpenLayers.Filter.Comparison(
					{
					    type: OpenLayers.Filter.Comparison.BETWEEN,
					    property: sPropertyToCompare,
					    lowerBoundary: iLower,
					    upperBoundary: iUpper
					}),
			    symbolizer: { Polygon: { fillColor: oRuleColour,
			        fillOpacity: 0.6, strokeColor: "black"}
			    }

			});
            oRules[i] = sRuleName;
        }
        var oThematicStyle = new OpenLayers.Style();
        oThematicStyle.addRules(oRules);
        oThematicMapLayer.styleMap = new OpenLayers.StyleMap({ "default": oThematicStyle });
        //Set the currentValue value to -1 to disable any theme 
        for (i = 0; i < oThematicMapLayer.features.length; i++) {
            oThematicMapLayer.features[i].attributes.currentValue = -1;
        }
        //stores thematic info in current object		
        this.thematicInfo.layerName = oLayer.layerName;
        this.thematicInfo.columnName = oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex];
        this.thematicInfo.oLayer = oLayer;
        this.thematicInfo.title = oLayer.thematic.legendTitle;
        this.mapWrapper.map.thematic.title = oLayer.thematic.legendTitle;
        this.getThematicLayerCurrentValueData(oThematicMapLayer, oLayer);
    },


    getThematicLayerCurrentValueData: function(oThematicMapLayer, oLayer) {
        /**
        * Function: getThematicLayerCurrentValueData 
        * Fetch the data for to be used for the application of the theme
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * oLayer - {object} layer object	
        *
        * Returns:
        */
        sThemeDataSource = oLayer.thematic.dataSource.name;
        //keep in map object to be subsequently used by popup to show map
        this.mapWrapper.map.thematic.dataSourceName = sThemeDataSource;
        this.getThemeDataFromAjax(oThematicMapLayer, oLayer, true);
    },


    getThemeDataFromAjax: function(oThematicMapLayer, oLayer, currentMonth) {
        /**
        * Function: getThemeDataFromAjax 
        * Fetches the data for to be used for the application of the theme by making an Ajax call
        * First it gets for current month and then calls itself to get for previous month	
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * oLayer - {object} layer object	
        * currentMonth - {bool} true/false flag
        *
        * Returns:
        */
        var pointInPolygon = function(oPolygon, en) {
            /**
            * Function: pointInPolygon 
            * Checks if a point is in a given geometry boundaries.
            *
            * Parameters:
            * oPolygon - {object} String format of a Polygon geometry 
            * en - {object) OpenLayers.LonLat object
            *
            * Returns:
            * {bool} - true if point is in specified polygon geometry
            */
            var x = en.lon;
            var y = en.lat;
            var _tmp = oPolygon.substring(9, oPolygon.length - 2).split(","); //point list
            var polySides = _tmp.length - 1;
            var polyX = Array();
            var polyY = Array();
            for (var k = 0; k < polySides; k++) {
                var xy = _tmp[k].split(" ");
                polyX.push(parseFloat(xy[0]));
                polyY.push(parseFloat(xy[1]));
            }
            var i, j;
            var oddNodes = false;
            for (var i = 0, j = polySides - 1; i < polySides; j = i++) {
                val = polyX[i] + (y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]);
                if (polyY[i] < y && polyY[j] >= y || polyY[j] < y && polyY[i] >= y) {
                    if (polyX[i] + (y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]) < x) {
                        oddNodes = !oddNodes;
                    }
                }
            }
            return oddNodes;
        };
        var successFunc = function(transport) {
            //try {
            var oJsonThemeVal = transport.responseText.evalJSON(true);
            var oLayer = this.thematicInfo.oLayer;
            var oThematicMapLayer = this.thematicInfo.oThematicLayer;
            this.themeDataSources.set(oLayer.thematic.dataSource.name, oJsonThemeVal);
            var arData = oJsonThemeVal.data;
            var iDataColumnIndex = oJsonThemeVal.columns.indexOf(oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex]);
            this.mapWrapper.map.thematic.columnName = oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex];
            this.mapWrapper.map.thematic.themeField = oLayer.group.themeFields[oLayer.group.themeFieldsIndex];
            var iWardIndex = oJsonThemeVal.columns.indexOf('neighbourhood');
            var iDistrictIndex = oJsonThemeVal.columns.indexOf('district');
            this.fillThematicLayerWithValues(oThematicMapLayer, arData, iDataColumnIndex, iWardIndex, iDistrictIndex, currentMonth);
            var featureName = $('txtAreaId').value;
            if (
					!featureName &&
					this.mapWrapper.currentLocation &&
					!!(this.mapWrapper.currentLocation.uid) &&
					!!(this.mapWrapper.currentLocation.uid !== -1)
				) {
                //TODO: this is quite slow! Can it be improved?
                var location = new OpenLayers.LonLat(this.mapWrapper.currentLocation.x, this.mapWrapper.currentLocation.y);
                //determine the polygon feature containing point								
                var fout = Array();
                //var current = started;
                for (var i = 0; i < oThematicMapLayer.features.length; i++) {
                    //var previous = current;
                    var the_geom = oThematicMapLayer.features[i].geometry.toString();
                    if (the_geom.indexOf('POLYGON') != -1) {
                        if (pointInPolygon(the_geom, location)) {
                            fout.push(oThematicMapLayer.features[i]);
                        }
                    }
                } //for


                //$( 'atMapSpurForm' ).insert( times );
                for (var k = 0; k < fout.length; k++) {
                    var feature = fout[k];
                    var layer = feature.layer;
                    featureName = feature.attributes.name;
                    //this.toggleHomeFeature(featureName);
                }
            }
            if (featureName) {
                this.mapWrapper.mapElement.fire('astun:setHomeFeature', featureName);
            }
            $('hoverWard').innerHTML = '';
            //after last call to function
            this.mapWrapper.mapElement.fire('astun:thematicLoaded', oLayer);

            //}
            /*catch (parsingError) 
            {
            if (transport.status != 0) { // i.e. if not fail because interrupted
            alert ('Error: Failed to parse Theme data for comparison');
            }					
            }*/
        }; //onSuccess
        var options = {
            method: 'get',
            parameters: null,
            onFailure: function(transport) {
                if (transport.status != 0) { // i.e. if not fail because interrupted
                    alert('Error: Failed  to get Theme data for comparison');
                }
            },
            onSuccess: successFunc.bindAsEventListener(this)
        };
        var myURL = location.href.substring(0, location.href.lastIndexOf("/") + 1);
        myURL += 'getdata.aspx?requesttype=json&Type=data&ds=';
        myURL += oLayer.thematic.dataSource.name;
        sColumn = oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex];
        var sBaseColumn = '';
        if (sColumn.indexOf("_rate_avg") != -1) {
            sBaseColumn = sColumn.substring(0, sColumn.indexOf("_rate_avg"));
        }
        else if (sColumn.indexOf("_avg") != -1) {
            sBaseColumn = sColumn.substring(0, sColumn.indexOf("_avg"));
        }
        else if (sColumn.indexOf("_rate") != -1) {
            sBaseColumn = sColumn.substring(0, sColumn.indexOf("_rate"));
        }
        else {
            sBaseColumn = sColumn;
        }

        myURL += '&select=neighbourhood,district,month,' + sColumn + ',' + sBaseColumn + "_avg_diff";
        var dateCriteria = '';
        //builds the Ajax call 

        dateCriteria = this.getDateSelection(1, this.cutOffDate.getFullYear(), this.cutOffDate.getMonth());
        this.thematicInfo.currentDateCriteria = dateCriteria;
        //stores the selection  criteria for 3 month and 1 year for use by popup
        this.mapWrapper.map.thematic.dateCriteria1 = this.getDateSelection(3, this.cutOffDate.getFullYear(), this.cutOffDate.getMonth());
        this.mapWrapper.map.thematic.dateCriteria2 = this.getDateSelection(12, this.cutOffDate.getFullYear(), this.cutOffDate.getMonth());

        //myURL += '&filter=^datetime^' + dateCriteria;
        myURL += '&filter=^datetime^= (SELECT max(datetime) FROM "' + oLayer.thematic.dataSource.name + '")';
        new Ajax.Request
		(myURL,
			options
		);
    },

    fillThematicLayerWithValues: function(oThematicMapLayer, arData, iDataColumnIndex, iWardIndex, iDistrictIndex, currentMonth) {
        /**
        * Function: fillThematicLayerWithValues 
        * Fill the 'currentMonth' or 'previousMonth' property for each feature of the thematic layer
        * from data obtained from the Ajax call.
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * arData - {Array} Array of data
        * iDataColumnIndex - {number} the index in data array to be used
        * iWardIndex - {number} the index in data array that contains ward name
        * iDistrictIndex - {number} the index in data array that contains district name
        * currentMonth - {bool} true - current month/false - previous month
        *
        * Returns:
        */
        var sFeatureName = '';
        var tempVal = 0;
        var arTemp = {};
        for (var i = 0; i < oThematicMapLayer.features.length; i++) {
            sFeatureName = oThematicMapLayer.features[i].attributes.name;
            for (var j = 0; j < arData.length; j++) {
                //if ( ( arData[j][iWardIndex]+ '@' + arData[j][iDistrictIndex] ) == sFeatureName )
                if ((arData[j][iWardIndex]) == sFeatureName) {
                    arTemp = arData[j];
                    tempVal = arTemp[iDataColumnIndex];

                    oThematicMapLayer.features[i].attributes.currentValue = tempVal;
                    oThematicMapLayer.features[i].attributes.previousValue = arTemp[iDataColumnIndex + 1];

                    break;

                }
            }
        }

        oThematicMapLayer.redraw();
    },



    getThematicRangesFromAjax: function(oThematicMapLayer, oLayer) {
        /**
        * Function: getThematicRangesFromAjax 
        * Fetch the thematic ranges for rules to be used for theme appication
        *
        * Parameters:
        * oThematicMapLayer - {object} map thematic layer object
        * oLayer - {object} map layer object
        *
        * Returns:
        */
        var successFunc = function(transport) {
            try {
                var oJsonTheme = transport.responseText.evalJSON();
                var iLow = oJsonTheme.columns.indexOf('low');
                var iHigh = oJsonTheme.columns.indexOf('high');
                for (i = 0; i < oLayer.thematic.ranges.range.length; i++) {
                    oLayer.thematic.ranges.range[i].low = oJsonTheme.data[i][iLow];
                    oLayer.thematic.ranges.range[i].high = oJsonTheme.data[i][iHigh];
                }
                //set flat that thematic values initialised for this layer
                //oLayer.thematic.ranges.initialised = true ;
                this.applyThematicRules(oThematicMapLayer, oLayer);
            }
            catch (parsingError) {
                if (transport.status != 0) { // i.e. if not fail because interrupted
                    alert('Error: Failed to get Theme comparison ranges');
                }
            }
        }; //onSuccess
        var options = {
            method: 'get',
            parameters: null,
            onFailure: function(transport) {
                if (transport.status != 0) { // i.e. if not fail because interrupted
                    alert('Error: Failed to get Theme comparison ranges');
                }
            },
            onSuccess: successFunc.bindAsEventListener(this)
        };
        var myURL = location.href.substring(0, location.href.lastIndexOf("/") + 1);
        myURL += 'getdata.aspx?RequestType=JSON&Type=THEMECLASS&Layer=' + oLayer.layerName;
        myURL += '&col=' + oLayer.thematic.themeFields[oLayer.group.themeFieldsIndex] + '&table="' + oLayer.thematic.dataSource.name + '"';
        myURL += '&range=' + oLayer.thematic.ranges.count + '&themetype=' + oLayer.thematic.thematicType;
        //myURL += '&filter=datetime ' + this.getDateSelection(1, this.cutOffDate.getFullYear(), this.cutOffDate.getMonth()).replace(/\'/g, '\'\'');
        myURL += '&filter=datetime= (SELECT max(datetime) FROM "' + oLayer.thematic.dataSource.name + '")';

        new Ajax.Request(myURL, options);
    },


    getGeoJSONFromAjax: function(oLayer) {
        /**
        * Function: getGeoJSONFromAjax 
        * Fetch the geometries data for the creation of features on thematic vector layer
        *
        * Parameters:
        * oLayer - {object} map layer object
        *
        * Returns:
        */
        var onSuccessFunc = function(transport) {
            try {
                var oJson = transport.responseText.evalJSON();
                var geojson = new OpenLayers.Format.GeoJSON();
                var oGeoJSON = geojson.read(oJson, "FeatureCollection");
                this.thematicInfo.geometrySource = oLayer.thematic.geometrySource;
                this.geometrySources.set(oLayer.thematic.geometrySource, oJson);
                this.generateThematicLayer(oLayer, oGeoJSON);
            }
            catch (parsingError) {
                if (transport.status != 0) { // i.e. if not fail because interrupted
                    alert('Error: Failed to get data for Ward boundaries');
                }
            }
        };
        var options =
		{
		    method: 'get',
		    parameters: null,
		    onFailure: function(transport) {
		        if (transport.status != 0) { // i.e. if not fail because interrupted
		            alert('Error: Failed to get data for Ward boundaries');
		        }
		    },
		    onSuccess: onSuccessFunc.bindAsEventListener(this)
		};
        var myURL = location.href.substring(0, location.href.lastIndexOf("/") + 1);
        new Ajax.Request
				(myURL + 'GetData.aspx?RequestType=GeoJson&ds=' + oLayer.thematic.geometrySource,
					options
				);
    },

    generateThematicLayer: function(oLayer, oGeoJSON) {
        /**
        * Function: generateThematicLayer 
        * Create the map vector layer for the theme from for the layer object using data from GeoJSON
        *
        * Parameters:
        * oLayer - {object} map layer object
        * oGeoJSON - {object} GeoJSON object containing geometry data for the polygons
        *
        * Returns:
        */
        var oThematicLayer = new OpenLayers.Layer.Vector('thematicLayer', { styleMap: this.defaultStyleMap });
        //create the features on the vector layer from GeoJSON 
        oThematicLayer.addFeatures(oGeoJSON);
        //create the field in each feature that will contain data to be used to apply theme rules
        //and a previous value for previous month
        for (i = 0; i < oThematicLayer.features.length; i++) {
            oThematicLayer.features[i].attributes.currentValue = -1;
            oThematicLayer.features[i].attributes.previousValue = -1;
        }
        //keep a variable for current feature hovered over
        this.thematicInfo.hoverFeature = '';
        this.thematicInfo.oThematicLayer = oThematicLayer;
        this.mapWrapper.thematicLayer = oThematicLayer;
        var featureHoverSelectOption = {
            hover: true,
            onSelect: function(feature) {
                this.map.thematic.featureName = feature.attributes.name;
                this.map.thematic.feature = feature;
            },
            onUnselect: function(feature) {
                this.map.thematic.featureName = '';
                this.map.thematic.feature = null;
            }
        };
        var ctrlHoverSelectFeature = new OpenLayers.Control.SelectFeature(oThematicLayer, featureHoverSelectOption);
        ctrlHoverSelectFeature.handlers["feature"].stopDown = false;
        ctrlHoverSelectFeature.handlers["feature"].stopUp = false;
        //this.mapWrapper.addControl('featureClickSelect', ctrlClickSelectFeature);		
        this.mapWrapper.addControl('featureHoverSelect', ctrlHoverSelectFeature);
        //if the 'initialised' flag in 'thematic' for layer does not exit, create and set to false
        if (!oLayer.thematic.ranges.initialised)
            oLayer.thematic.ranges.initialised = false;
        //Create the rules and draw the thematic layer			
        this.getThematicRules(oThematicLayer, oLayer);
        this.mapWrapper.map.addLayer(oThematicLayer);
        this.thematicLayerFinished(oThematicLayer, oLayer, true);
    },

    thematicLayerFinished: function(oThematicMapLayer, oLayer, bVisible) {
        /**
        * Function: thematicLayerFinished 
        * Set the layer currentlyVisible propery according to visibility on Map.
        * Sets/unsets hover observation event.
        *
        * Parameters:
        * oThematicMapLayer - {object} theme map vector layer object
        * oLayer - {object} map layer object
        * bVisible - {bool} GeoJSON true - visible / false - not visible
        *
        * Returns:
        */

        if (bVisible) {
            oLayer.currentlyVisible = true;
            if (oLayer.group.currentLayer) {
                var previousLayer = oLayer.group.currentLayer;
                previousLayer.currentlyVisible = false;
                previousLayer.group.currentLayer = null;
                this.mapWrapper.mapElement.fire('astun:thematicHide', {
                    layer: previousLayer
                });
            }

            oLayer.currentlyVisible = true;
            oLayer.group.currentLayer = oLayer;
            oThematicMapLayer.setVisibility(true);
            this.mapWrapper.mapElement.fire('astun:thematicShow', {
                layer: oLayer
            });
            this.mapWrapper.setControl('drag', new OpenLayers.Control.Drag(
				{
				    'down': function(evt) {
				        this.map.wrapper.installedControls['hover'].deactivate();
				        this.map.wrapper.installedControls['featureHoverSelect'].deactivate();
				    },
				    'up': function(evt) {
				        this.map.wrapper.installedControls['hover'].activate();
				        this.map.wrapper.installedControls['featureHoverSelect'].activate();
				    }
				}
			));
            this.mapWrapper.setControl('hover', new OpenLayers.Control.Hover(
				{ 'delay': 1500 },
				{
				    'pause': this.mapWrapper.interactions.showThematicPopUp.bindAsEventListener(this.mapWrapper),
				    'move': function(e) {
				        clearTimeout(this.map.wrapper.timers.hover);
				    }
				}
			));



            this.mapWrapper.mapElement.fire('astun:saveSetting', { setting: 'visibleThematic', value: '' + oLayer.layerName });
        }
        else {
            //TODO: reset hover and drag controls to those set before thematic layer loaded.
            this.mapWrapper.removeControl('drag');

            oLayer.currentlyVisible = false;
            oLayer.group.currentLayer = null;
            oThematicMapLayer.setVisibility(false);
            this.mapWrapper.mapElement.fire('astun:thematicHide', {
                layer: oLayer
            });
            $('homeWard').innerHTML = '';
            $('hoverWard').innerHTML = '';
            this.mapWrapper.mapElement.fire('astun:deleteSetting', { setting: 'visibleThematic' });
        }
        this.thematicInfo.themeBeingProcessed = false;
        this.mapWrapper.mapElement.fire('astun:themeLoadComplete', {});
    },


    getDateSelection: function(noMonth, prevYear, prevMonth) {
        /**
        * Function: getDateSelection 
        * builds the date selection criteria
        *
        * Parameters:
        * noMonth - {number} no of months back from 'cutOffDate'
        * prevYear - {number} year value of 'cutOffDate'
        * prevMonth - {number} month value of 'cutOffDate', javascript month is zero based
        *
        * Returns:
        * {string} Format for e.g "between '2008-11-01' and '2008-11-30'"
        */
        var oDate = new Date();
        var curYear = oDate.getFullYear();
        var curMonth = oDate.getMonth();
        var tempMonth = curMonth;
        var tempYear = curYear;
        var lastMonth = 0;
        var monthDays = 0;
        //getting dates for specific month and year
        if (prevYear) {
            tempYear = prevYear;
            tempMonth = prevMonth;
        }
        else {
            if (curMonth == 0) {
                tempMonth = 11;
                tempYear = curYear - 1
            }
            else {
                tempMonth = curMonth - 1;
                //tempMonth = tempMonth + 1 ; //calendar
            }
        }
        tempMonth = tempMonth + 1; //inclusive range
        var dd = new Date(tempYear, (tempMonth), 0);
        var monthDays = dd.getDate();
        //Calender Month, javascript is zero based
        var endDate = "'" + [tempYear, (tempMonth), monthDays].join('-') + "'";
        //find start date
        if (tempMonth < noMonth) {
            tempYear = tempYear - 1;
            tempMonth = 12 - (noMonth - tempMonth);
        }
        else {
            tempMonth = tempMonth - noMonth;
        }
        tempMonth = tempMonth + 1; //inclusive range
        var startDate = "'" + [tempYear, tempMonth, '01'].join('-') + "'";
        return 'between ' + startDate + ' and ' + endDate;
    },

    toggleHomeFeature: function(featureName) {
        /**
        * Function: toggleHomeFeature 
        * Identify the polygon feature on the thematic layer with matching name and draw a yellow
        * border to make it identifiable on map display. If feature already has yellow border, 
        * will then remove it. If no name passed, will then de-select any home feature present.
        *
        * Parameters:
        * featureName - {string } corresponding feature.attributes.name
        *
        * Returns:
        * 
        */
        var oFeature = {};
        if (!this.thematicInfo.homeFeature) {
            this.mapWrapper.map.thematic.homeFeature = {};
            this.thematicInfo.homeFeature = {};
        }
        else {
            //already a home feature set, then reset it			
            $('hoverWard').innerHTML = '';
            $('homeWard').innerHTML = '';
            oFeature = this.thematicInfo.homeFeature.current;
            oFeature.style = null;
            this.thematicInfo.oThematicLayer.drawFeature(oFeature);
            //resets the pointer to current home feature
            this.mapWrapper.map.thematic.homeFeature = null;
            this.thematicInfo.homeFeature = null;
            oFeature = {};
            if (featureName === '') {
                return
            }

        }
        //determine the selected feature and keep reference for future use.
        var stylTemp = new OpenLayers.Style();
        for (i = 0; i < this.thematicInfo.oThematicLayer.features.length; i++) {
            if (this.thematicInfo.oThematicLayer.features[i].attributes.name == featureName) {
                oFeature = this.thematicInfo.oThematicLayer.features[i];
                break;
            }
        }
        this.mapWrapper.map.thematic.homeFeature = {};
        this.thematicInfo.homeFeature = {};
        this.mapWrapper.map.thematic.homeFeature.current = oFeature;
        this.thematicInfo.homeFeature.current = oFeature;

        var aRules = oFeature.layer.styleMap.styles['default'].rules;
        for (var i = 0; i < aRules.length; i++) {
            var oRule = aRules[i];
            var applies = oRule.evaluate(oFeature);
            if (applies) {
                var rangeColour = oRule.symbolizer.Polygon.fillColor;
            }
        }
        var stylTemp = new OpenLayers.Style();
        stylTemp.fillColor = rangeColour;
        stylTemp.fillOpacity = 0.6;
        // prak 17/12/08
        stylTemp.hoverFillColor = "#0000FF";
        stylTemp.hoverFillOpacity = 0.6,

		stylTemp.strokeColor = "#FFFF66";
        stylTemp.strokeOpacity = 1;
        stylTemp.strokeWidth = 6;
        oFeature.style = stylTemp;
        this.thematicInfo.oThematicLayer.drawFeature(oFeature);
        //peter plz comment
        this.mapWrapper.interactions.showHomeWardGraph(this.thematicInfo);

        //this.centreToFeature(featureName);
    },

    centreToFeature: function(sfeatureName) {
        /**
        * Function: centreToFeature 
        * Centres the map display on the polygon feature with matching feature.attributes.name
        * border to make it identifiable on map display
        *
        * Parameters:
        * featureName - {string } matching feature.attributes.name
        *
        * Returns:
        * 
        */
        var oFeature = {};
        for (i = 0; i < this.thematicInfo.oThematicLayer.features.length; i++) {
            if (this.thematicInfo.oThematicLayer.features[i].attributes.name == sfeatureName) {
                oFeature = this.thematicInfo.oThematicLayer.features[i];
                break;
            }
        }

        if (oFeature)
            this.mapWrapper.map.setCenter(oFeature.geometry.getBounds().getCenterLonLat(), 10, false, false);

    }


}); //OLLayerControl		

var LayerGroup = Class.create
({
    getDisplayName: function() {
        /**
        * Function: getDisplayName 
        * returns the display name of current layerGroup object
        *
        * Parameters:
        *
        * Returns:
        *  {string} - the display name.
        */
        return this.displayName;
    },

    getLayerDetails: function(lyrNo) {
        /**
        * Function: getLayerDetails 
        * returns the layer properties at corresponding index, concatenated in a string, for debug
        *
        * Parameters:
        * lyrNo - {number} index of layer in layers array of layer group
        * 
        * Returns:
        *  {string} - property values concatenated in a single string
        */
        var strRet = "";
        var oLyr = new layer();
        oLyr = this.layers[lyrNo];
        strRet += " Layer No : " + lyrNo;
        strRet += " " + " ,displayName: " + oLyr.displayName;
        strRet += " " + " ,layerName: " + oLyr.layerName;
        strRet += " " + " ,Visible: " + oLyr.initiallyVisible;
        strRet += " " + " ,currentlyVisible: " + oLyr.currentlyVisible;
        return strRet;
    },

    initialize: function(name, guid) {
        /**
        * Function: initialize 
        * creates a layer group with supplied name and guuid
        *
        * Parameters:
        * name - {string} to be assigned to the layerGroup 'displayName'
        * guid - {string} to be assigned to the layerGroup 'guuid'
        * 
        * Returns:
        *  {string} - property values concatenated in a single string
        */

        this.guid = guid || null;
        this.layers = $A([]);
        this.activeLayers = $A([]);
        this.thematicLayers = $A([]);
        this.activeShown = 0;
        this.displayName = name;
        this.themeFieldsIndex = 0;
    },

    showLayers: function() {
        /**
        * Function: showLayers 
        * displays all the layers in the group on the map display
        *
        * Parameters:
        * 
        * Returns:
        * 
        */
        this.activeShown = 0;
        for (i = 0; i < this.activeLayers.length; i++) {
            this.activeShown++;
            if (!this.activeLayers[i].currentlyVisible) {
                this.mapWrapper.addISMLayer(this.activeLayers[i].layerName);
                this.activeLayers[i].currentlyVisible = true;
                $(this.mapWrapper.mapElement).fire("astun:layerShow", { layer: this.activeLayers[i] });
                if( jQuery ) {
					jQuery( '#' + this.mapWrapper.mapElement.id ).trigger( 'layerShown',  this.activeLayers[i].layerName);
				}
            }
        }
        this.mapWrapper.ismDataLayer.setVisibility(true);
        this.mapWrapper.draw();

        this.mapWrapper.mapElement.fire('astun:saveSetting', { setting: 'visibleLayers', value: '' + this.mapWrapper.ismDataLayer.params.layers });

        this.mapWrapper.mapElement.fire("astun:showLayerGroup", { layerGroup: this });
       
    },

    hideLayers: function() {
        /**
        * Function: hideLayers 
        * Turn off the visibility on Map display for all layers in current group
        *
        * Parameters:
        * 
        * Returns:
        * 
        */


        this.activeShown = 0;
        for (i = 0; i < this.activeLayers.length; i++) {
            if (this.activeLayers[i].currentlyVisible) {
                this.mapWrapper.removeISMLayer(this.layers[i].layerName);
                this.activeLayers[i].currentlyVisible = false;
                $(this.mapWrapper.mapElement).fire("astun:layerHide", { layer: this.activeLayers[i] });
                if( jQuery ) {
					jQuery( '#' + this.mapWrapper.mapElement.id ).trigger( 'layerHidden',  this.activeLayers[i].layerName);
				}
            }
        }
        
        this.mapWrapper.draw();

        this.mapWrapper.mapElement.fire('astun:saveSetting', { setting: 'visibleLayers', value: '' + this.mapWrapper.ismDataLayer.params.layers });

        this.mapWrapper.mapElement.fire("astun:hideLayerGroup", { layerGroup: this });
        
    }



});


var layer = Class.create
({


    initialize: function(lyrName) {
        /**
        * Function: initialize 
        * Creates the layer object and initialises some property values. 
        * Called automatically upon obejct creattion ( var x = new layer(myLyr); )
        *
        * Parameters:
        * lyrName - {string} the assigned display name for the layer
        *
        * Returns:
        * 
        */

        this.layerName = '';
        this.displayName = lyrName;
        this.initiallyVisible = false;
        this.currentlyVisible = false;
        this.icon = '';
        this.infoClick = false;
        this.help = '';
        this.query = {};
        this.active = true;
        this.searchField = '';
        this.thematic = {};
        this.thematic.name = '';
        this.thematic.thematicType = 0;
        this.thematic.legendSubTitle = 0;
        this.thematic.themeFields = [];
        this.thematic.ranges = {};
        this.thematic.ranges.auto = true;
        this.thematic.ranges.count = 0;
        this.thematic.ranges.initialised = false;
        this.thematic.ranges.rangeNo = [];


    }
});
 
 


