﻿/**
* Class: OpenLayers.Control.StyledLayerSwitcher
*
* Inherits from:
*  - <OpenLayers.Control.LayerSwitcher>
*/
OpenLayers.Control.StyledLayerSwitcher =
    OpenLayers.Class(OpenLayers.Control.LayerSwitcher, {

    	/**  
    	* Property: activeColor
    	* {String}
    	*/
    	activeColor: "#99BA34",

    	/**  
    	* Property: mapConfig
    	* {String}
    	*/
    	mapConfig: null,

    	/**  
    	* Property: filters
    	* {String[]}
    	*/
    	filters: null,

    	/**  
    	* Property: filtersDiv
    	* {DOMElement}
    	*/
    	filtersDiv: null,

    	/**
    	* Constructor: OpenLayers.Control.PanZoomBar
    	*/
    	initialize: function(mapConfig) {

    		this.mapConfig = mapConfig;
    		this.filters = this.getFilters();
    		OpenLayers.Control.LayerSwitcher.prototype.initialize.apply(this, arguments);
    	},

    	/**
    	* Method: showControls
    	* Hide/Show all LayerSwitcher controls depending on whether we are
    	*     minimized or not
    	* 
    	* Parameters:
    	* minimize - {Boolean}
    	*/
    	showControls: function(minimize) {

    		this.maximizeDiv.style.display = minimize ? "" : "none";
    		this.minimizeDiv.style.display = minimize ? "none" : "";
    		this.layersDiv.style.display = minimize ? "none" : "";
    		//this.filtersDiv.style.display = minimize ? "none" : "";
    	},

    	/**
    	* Method: draw
    	*
    	* Returns:
    	* {DOMElement} A reference to the DIV DOMElement containing the 
    	*     switcher tabs.
    	*/
    	draw: function() {

    		OpenLayers.Control.prototype.draw.apply(this);

    		// create layout divs
    		this.loadContents();

    		// set mode to minimize
    		if (!this.outsideViewport) {
    			this.minimizeControl();
    		}

    		// populate div with current info
    		this.redraw();

    		// populate filters div(s)
    		if (this.filters.length > 0) this.fillFilterContainers();

    		return this.div;
    	},

    	/** 
    	* Method: loadContents
    	* Set up the labels and divs for the control
    	*/
    	loadContents: function() {

    		//configure main div
    		this.div.className = "olLayerSwitcher_mainDiv";

    		OpenLayers.Event.observe(this.div, "mouseup", OpenLayers.Function.bindAsEventListener(this.mouseUp, this));
    		OpenLayers.Event.observe(this.div, "click", this.ignoreEvent);
    		OpenLayers.Event.observe(this.div, "mousedown", OpenLayers.Function.bindAsEventListener(this.mouseDown, this));
    		OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent);

    		// layers list div
    		this.layersDiv = document.createElement("div");
    		this.layersDiv.className = "olLayerSwitcher_layersDiv";
    		this.layersDiv.id = "layersDiv";

    		this.baseLayersDiv = document.createElement("div");
    		this.baseLayersDiv.className = "olLayerSwitcher_baseLayersDiv";

    		this.dataLayersDiv = document.createElement("div");
    		this.dataLayersDiv.className = "olLayerSwitcher_dataLayersDiv";

    		if (this.ascending) {
    			this.layersDiv.appendChild(this.baseLayersDiv);
    			this.layersDiv.appendChild(this.dataLayersDiv);
    		} else {
    			this.layersDiv.appendChild(this.dataLayersDiv);
    			this.layersDiv.appendChild(this.baseLayersDiv);
    		}

    		this.div.appendChild(this.layersDiv);
    		OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75); // set opacity

//    		// filter groups div
//    		this.filtersDiv = document.createElement("div");
//    		this.filtersDiv.className = "olLayerSwitcher_filtersDiv";
//    		this.filtersDiv.id = "filtersDiv";

//    		if (this.filters.length > 0) {
//    			this.dataLayersDiv.className = "olLayerSwitcher_baseLayersDiv";
//    			for (var i = 0; i < this.filters.length; i++) {
//    				var filterDiv = document.createElement("div");
//    				filterDiv.id = "filterDiv_" + this.filters[i];
//    				filterDiv.className = "olLayerSwitcher_baseLayersDiv";
//    				this.filtersDiv.appendChild(filterDiv);
//    			}
//    			this.filtersDiv.lastChild.className = "olLayerSwitcher_dataLayersDiv";
//    			this.div.appendChild(this.filtersDiv);
//    		}

//    		OpenLayers.Rico.Corner.changeOpacity(this.filtersDiv, 0.75); // set opacity

    		// maximize button div
    		var imgLocation = OpenLayers.Util.getImagesLocation();
    		var sz = new OpenLayers.Size(207, 18);
    		var img = imgLocation + 'layer-switcher-maximize.png';
    		this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                      "OpenLayers_Control_MaximizeDiv",
                                      null,
                                      sz,
                                      img,
                                      "absolute");
    		this.maximizeDiv.style.top = "0px";
    		this.maximizeDiv.style.right = "0px";
    		this.maximizeDiv.style.left = "";
    		this.maximizeDiv.style.display = "none";
    		OpenLayers.Event.observe(this.maximizeDiv, "click",
            OpenLayers.Function.bindAsEventListener(this.maximizeControl, this)
          );

    		this.div.appendChild(this.maximizeDiv);

    		// minimize button div
    		var img = imgLocation + 'layer-switcher-minimize.png';
    		var sz = new OpenLayers.Size(207, 18);
    		this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                      "OpenLayers_Control_MinimizeDiv",
                                      null,
                                      sz,
                                      img,
                                      "absolute");
    		this.minimizeDiv.style.top = "0px";
    		this.minimizeDiv.style.right = "0px";
    		this.minimizeDiv.style.left = "";
    		this.minimizeDiv.style.display = "none";
    		OpenLayers.Event.observe(this.minimizeDiv, "click",
            OpenLayers.Function.bindAsEventListener(this.minimizeControl, this)
          );

    		this.div.appendChild(this.minimizeDiv);
    	},

    	/** 
    	* Method: maximizeControl
    	* Set up the labels and divs for the control
    	* 
    	* Parameters:
    	* e - {Event} 
    	*/
    	maximizeControl: function(e) {

    		this.div.style.width = "207px"; //20em
    		this.div.style.height = "";

    		this.showControls(false);

    		if (e != null) {
    			OpenLayers.Event.stop(e);
    		}
    	},

    	/** 
    	* Method: redraw
    	* Goes through and takes the current state of the Map and rebuilds the
    	*     control to display that state. Groups base layers into a 
    	*     radio-button group and lists each data layer with a checkbox.
    	*
    	* Returns: 
    	* {DOMElement} A reference to the DIV DOMElement containing the control
    	*/
    	redraw: function() {

    		//if the state hasn't changed since last redraw, no need 
    		// to do anything. Just return the existing div.
    		if (!this.checkRedraw()) {
    			return this.div;
    		}

    		//clear out previous layers 
    		this.clearLayersArray("base");
    		this.clearLayersArray("data");

    		var containsOverlays = false;
    		var containsBaseLayers = false;

    		// Save state -- for checking layer if the map state changed.
    		// We save this before redrawing, because in the process of redrawing
    		// we will trigger more visibility changes, and we want to not redraw
    		// and enter an infinite loop.
    		this.layerStates = new Array(this.map.layers.length);
    		for (var i = 0; i < this.map.layers.length; i++) {
    			var layer = this.map.layers[i];
    			this.layerStates[i] = {
    				'name': layer.name,
    				'visibility': layer.visibility,
    				'inRange': layer.inRange,
    				'id': layer.id
    			};
    		}

    		var layers = this.map.layers.slice();
    		if (!this.ascending) { layers.reverse(); }
    		for (var i = 0; i < layers.length; i++) {
    			var layer = layers[i];
    			var baseLayer = layer.isBaseLayer;

    			if (layer.displayInLayerSwitcher) {

    				if (baseLayer) {
    					containsBaseLayers = true;
    				} else {
    					containsOverlays = true;
    				}

    				// only check a baselayer if it is *the* baselayer, check data
    				//  layers if they are visible
    				var checked = (baseLayer) ? (layer == this.map.baseLayer)
                                            : layer.getVisibility();

    				// create input element
    				var inputElem = document.createElement("input");
    				inputElem.id = "input_" + layer.name;
    				inputElem.name = (baseLayer) ? "baseLayers" : layer.name;
    				inputElem.type = (baseLayer) ? "radio" : "checkbox";
    				inputElem.value = layer.name;
    				inputElem.checked = checked;
    				inputElem.defaultChecked = checked;

    				if (!baseLayer && !layer.inRange) {
    					inputElem.disabled = true;
    				}
    				var context = {
    					'inputElem': inputElem,
    					'layer': layer,
    					'layerSwitcher': this
    				};
    				OpenLayers.Event.observe(inputElem, "mouseup",
                      OpenLayers.Function.bindAsEventListener(this.onInputClick,
                                                              context)
                  );

    				// create span
    				var labelSpan = document.createElement("span");
    				if (!baseLayer && !layer.inRange) {
    					labelSpan.style.color = "gray";
    				}
    				labelSpan.innerHTML = "&nbsp;" + layer.name + "&nbsp;&nbsp;&nbsp;";
    				labelSpan.style.verticalAlign = (baseLayer) ? "3px"
                                                              : "3px";
    				OpenLayers.Event.observe(labelSpan, "click",
                      OpenLayers.Function.bindAsEventListener(this.onInputClick,
                                                              context)
                  );
    				// create line break
    				var br = document.createElement("br");

    				var groupArray = (baseLayer) ? this.baseLayers
                                                 : this.dataLayers;
    				groupArray.push({
    					'layer': layer,
    					'inputElem': inputElem,
    					'labelSpan': labelSpan
    				});

    				// Choose the map or theme layerDIV
    				var groupDiv = (baseLayer) ? this.baseLayersDiv
                                               : this.dataLayersDiv;
    				groupDiv.appendChild(inputElem); // Add elements radiobutton or checkbox
    				groupDiv.appendChild(labelSpan);

    				if (layer.options.extra != null && layer.options.extra.legend != null) {
    					var legend = layer.options.extra.legend;
    					var legendImg = document.createElement("img");
    					legendImg.src = legend.src;
    					if (legend.style != null)
    						legendImg.style = legend.style;
    					if (legend.width != null)
    						legendImg.width = legend.width;
    					if (legend.height != null)
    						legendImg.height = legend.height;
    					groupDiv.appendChild(legendImg);
    				}

    				groupDiv.appendChild(br);
    			}
    		}

    		return this.div;
    	},

    	/** 
    	* Method: getFilters
    	* Return list of filter group names in current layer list if there are any
    	* 
    	* Parameters:
    	*/
    	getFilters: function() {

    		var filterGroupList = [];
    		for (var i = 0; i < this.mapConfig.mapconfig.layerlist.layer.length; i++) {
    			if (this.mapConfig.mapconfig.layerlist.layer[i].options.extra != null &&
                    this.mapConfig.mapconfig.layerlist.layer[i].options.extra.filterRef != null) {
    				var filterGroup = this.mapConfig.mapconfig.layerlist.layer[i].options.extra.filterRef;
    				if (!contains(filterGroupList, filterGroup))
    					filterGroupList.push(filterGroup);
    			}
    		}

    		// internal function for locating an array element
    		function contains(a, e) {
    			for (var j = 0; j < a.length; j++) if (a[j] == e) return true;
    			return false;
    		}

    		return filterGroupList;
    	},

    	/** 
    	* Method: fillFilterContainers
    	* Generate filter lists and place them in their respective filter divs
    	* 
    	* Parameters:
    	*/
    	fillFilterContainers: function() {

    		// get filter group list from mapConfig
    		var filterGroups = this.mapConfig.mapconfig.filterlist["filter"];

    		// make filterGroups an array if it's not
    		if (filterGroups[0] == null) {
    			var temp = filterGroups;
    			filterGroups = [];
    			filterGroups.push(temp);
    		}

    		// generate filter lists for all filter containers
    		if (this.filters.length > 0) {
    			for (var i = 0; i < this.filtersDiv.childNodes.length; i++) {
    				if (this.filtersDiv.childNodes[i].id.split('_')[1] != null) {
    					for (var j = 0; j < this.filters.length; j++) {
    						if (this.filtersDiv.childNodes[i].id.split('_')[1] == this.filters[j]) {
    							createFilters(this.filters[j], this.filtersDiv.childNodes[i]);
    						}
    					}
    				}
    			}
    		}

    		// internal function for generating filters for one filter div
    		function createFilters(filterGroupName, filterGroupDiv) {
    			for (var f in filterGroups) {
    				var filterGroup = filterGroups[f];

    				// if the filter matches, fill up the div
    				if (filterGroup["@id"] == filterGroupName) {
    					// create group title
    					var labelTitleSpan = document.createElement("span");
    					labelTitleSpan.innerHTML = "&nbsp;Filter:  " + filterGroupName.substring(0, 1).toUpperCase() + filterGroupName.substring(1);
    					labelTitleSpan.style.verticalAlign = "3px";

    					// create line break
    					var br = document.createElement("br");

    					// add title to div
    					filterGroupDiv.appendChild(labelTitleSpan);
    					filterGroupDiv.appendChild(br);

    					// fill up the div with filter content
    					for (var e in filterGroup.property) {
    						var element = filterGroup.property[e];
    						if (element.displayName == null) continue;

    						// create input element
    						var inputFilterElem = document.createElement("input");
    						inputFilterElem.id = "input_" + element.name;
    						inputFilterElem.name = element.name;
    						inputFilterElem.type = "checkbox";
    						inputFilterElem.value = element.name;
    						inputFilterElem.checked = true;
    						inputFilterElem.style.marginLeft = "15px";

    						var context = {
    							'inputElem': inputFilterElem,
    							'layerSwitcher': this
    						};

    						OpenLayers.Event.observe(inputFilterElem, "mouseup",
													OpenLayers.Function.bindAsEventListener(this.onFilterClick, context)
							);

    						// create span
    						var labelFilterSpan = document.createElement("span");
    						labelFilterSpan.innerHTML = "&nbsp;" + element.displayName;
    						labelFilterSpan.style.verticalAlign = "3px";
    						labelFilterSpan.style.opacity = "1";
    						OpenLayers.Event.observe(labelFilterSpan, "click",
    												OpenLayers.Function.bindAsEventListener(this.onFilterClick, context)
    						);

    						// create line break
    						var br = document.createElement("br");

    						// add elements to div
    						filterGroupDiv.appendChild(inputFilterElem);
    						filterGroupDiv.appendChild(labelFilterSpan);
    						filterGroupDiv.appendChild(br);
    					}
    				}
    			}
    		}

    		/******************* GENERATE LINK **********************/
    		/* SHOULD BE MOVED TO 'onFilterClick()' - DO NOT DELETE */
    		var link = "";
    		var linkLayers = "LAYERS=";
    		var linkBBOX = "BBOX=";
    		var linkFilters = "FILTER=";

    		var filterStatus = [];
    		for (var i = 0; i < this.filtersDiv.firstChild.childNodes.length; i++) {
    			if (this.filtersDiv.firstChild.childNodes[i].type == "checkbox" && this.filtersDiv.firstChild.childNodes[i].checked == true) {
    				filterStatus.push(this.filtersDiv.firstChild.childNodes[i].id.split('_')[1]);
    			}
    		}

    		if (filterStatus.length != 0) {
    			for (var i = 0; i < this.map.layers.length; i++) {
    				if (this.map.layers[i].visibility == true) {
    					//linkLayers += this.map.layers[i].
    				}
    			}
    		}
    		/********************************************************/
    	},

    	onFilterClick: function(evt) {

    		alert(this.inputElem.id);

    	},

    	generateServiceLink: function() {


    	},

    	CLASS_NAME: "OpenLayers.Control.StyledLayerSwitcher"
    }); 