/* Copyright (c) 2009 Australian Institute of Marine Science */

/**
 * @requires OpenLayers/Control.js
 * @requires atlas.css
 */

/**
 * Class: OpenLayers.Control.AtlasLegend
 * Displays a legend for all the visible layers that have a legend graphic
 * associated with them. This works in a manner similar to the Attribution
 * control, except that it allows an image to be displayed for each layer
 * corresponding to its legend. These legend items are displayed one after 
 * each other in a vertical format. The legend graphic should correspond to 
 * an icon on the left followed by text on the right. 
 *
 * Legend items can be grouped into categories using the 'legendGroup' property
 * of each layer. All legend items with a group are listed under the name of the
 * group. If no legendGroup is specified then the layer will be filed under the 
 * miscellaneous category. The name of this category can be set using the 
 * 'miscCategory' attribute of this control.
 *
 * The legend graphic is specified as a URL using the 'legendUrl' property
 * of the 'atlasData' property of a layer. If the layer has no 'legendUrl' 
 * property then it will not appear in the legend.
 *
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.AtlasLegend = 
  OpenLayers.Class(OpenLayers.Control, {
          
	/**
	 * Property: miscCategory 
	 * {string} miscellaneous category string. Legend items with no category
	 * are placed in this category.
	 */
	miscCategory: "Miscellaneous",
	
	/**
	 * Property: enableMiscCategoryTitle
	 * {boolean} If false then the title for the 'miscellaneous' category is not displayed. 
	 * This is useful for creating a clean legend when no categorisation
	 * is used. If true then the miscCategory text will be one of the category titles
	 * in the legend.
	 */
	enableMiscCategoryTitle: false, 
	 
	// DOM Elements
  
    /**
     * Property: layersDiv
     * {DOMElement} 
     */
    //legendDiv: null,
	
    /**
     * Constructor: OpenLayers.Control.AtlasLegend 
     * 
     * Parameters:
     * options - {Object} Options for control.
     */
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /** 
     * Method: destroy
     * Destroy control.
     */
    destroy: function() {
        this.map.events.un({
			"legendChange": this.updateLegend,
            "removelayer": this.updateLegend,
            "addlayer": this.updateLegend,
            "changelayer": this.updateLegend,
            "changebaselayer": this.updateLegend,
			'finishedLoading': this.updateLegend,
            scope: this
        });
        
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },    
    
    /**
     * Method: draw
     * Initialize control.
     * 
     * Returns: 
     * {DOMElement} A reference to the DIV DOMElement containing the control
     */    
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        this.map.events.addEventType("legendChange");
        this.map.events.on({
			'finishedLoading': this.updateLegend,
            'changebaselayer': this.updateLegend,
            'changelayer': this.updateLegend,
            'addlayer': this.updateLegend,
            'removelayer': this.updateLegend,
			"legendChange": this.updateLegend,
            scope: this
        });
        this.updateLegend();
        
        return this.div;    
    },

    /**
     * Method: updateLegend
     * Update legend div
     */
    updateLegend: function() {
		//this.layersDiv = document.createElement("div");
		if (this.map.loading) {
			return;
		}
        var legendItems = {};		// {map<category, array layers with legend graphics>}
		var i, len;
        if (this.map && this.map.layers) {
			// Group the legend items into their categories. 
			// Sort the legend items into hashmap of arrays, where
			// the key is the category and the value is an array of
			// all legend items in that category.
			len = this.map.layers.length;
            for(i = 0; i < len; i++) {
                var layer = this.map.layers[i];
				// Only handle the layer 
				// --------------------
				// This is not finished
				
				// Ignore layers that are not visible, or have no legend information, or
				// the legendItem is disabled
                if (layer.atlasData && layer.atlasData.legendUrl && layer.getVisibility() && 
					layer.atlasData.showItemInLegend) {

					// Group the layers by the dataset name and the owner
					var legendCatAddon = '';
					if (typeof layer.atlasData.ownerTitle !== 'undefined') {
						legendCatAddon = ' ('+layer.atlasData.ownerTitle+')';
					}
					// If the dataset/owner combo is line split them on separate lines.
					var legendCategory;					
					if (layer.atlasData.datasetTitle.length + legendCatAddon.length > 25) {
						legendCategory = layer.atlasData.datasetTitle + '<br />'+legendCatAddon;
					} else {
						legendCategory = layer.atlasData.datasetTitle + legendCatAddon;
					}
	
					// If this is the first item in the category then
					// initalise the array to save the item.
					var categoryArray = legendItems[legendCategory];					
					if (typeof categoryArray === 'undefined') {
						// New category
						categoryArray = [];
						// Save the array back to the map
						legendItems[legendCategory] = categoryArray;						
					}
					// Save a reference to the entire layer so we have access to
					// all its attributes.
					categoryArray.push(layer);
                }
            }
			
			// Create the HTML			
			var category = null;
			var legendHtml = [];
			
			for (category in legendItems) {
				if (legendItems.hasOwnProperty(category)) {
					legendHtml.push('<div class="categoryText">'+category+'</div>');
					
					var legendLayer = legendItems[category];
					
					for (i = 0; i < legendLayer.length; i++) {
						var atlasData = legendLayer[i].atlasData;
						var legendTitle;
						
						// -------------------------
						//      Legend Text
						// -------------------------
						
						// Calculate the text to display with each item. If the text is
						// long then split the variableTitle and layerTitle on separate
						// lines.
						var itemText = '';
						// Only display the auto legend text if it is not be overwritten.
						if (typeof atlasData.legendTitleOverwrite === 'undefined') {
							var variableText = legendLayer[i].atlasData.variableTitle;
							var layerText = atlasData.layerTitle || '';		// handle optional layerTitle
							if (variableText.length + layerText.length > 25) {
								itemText = variableText + '<br />'+ layerText;
							} else {
								itemText = variableText + ' - ' +layerText;
							}
						} else {	
							itemText = atlasData.legendTitleOverwrite;
						} 
						
						// If the text is not empty wrap it in a div for styling
						if (itemText !== '') {
							itemText = '<div class="itemText">'+itemText+'</div>';
						}
						// Finish me itemText => div if not empty
						
						// If there are multiple legendUrls then we display all of them with the layer.
						// If we only have one legendUrl make it an array with a single element
						// to simplify subsequent processing.
						var legendUrls = [];
						if (!ATLAS.Util.isArray(legendLayer[i].atlasData.legendUrl)) {
							legendUrls.push(legendLayer[i].atlasData.legendUrl);
						} else {
							legendUrls = legendLayer[i].atlasData.legendUrl;
						}
						
						var imageHtml = [];
						for (var j = 0; j < legendUrls.length; j++) {
							imageHtml.push('  <div class="legendImage"><img src="'+legendUrls[j]+'" /></div>');
						}
						legendHtml.push(
						'<div class="legendItem">'+
						itemText+
						imageHtml.join('\n')+
						'</div>');
					}
				}
			}
			if (legendHtml.length > 0) {
				this.div.innerHTML = '<div class="header">Legend</div>'+legendHtml.join('\n');
				this.div.style.display = '';
			} else {
				this.div.innerHTML = '';
				this.div.style.display = 'none';
			}
        }
    },

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

