/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt 
 * for the full text of the license. */

/** 
 * @requires OpenLayers/Control.js
 * 
 * Class: OpenLayers.Control.ckLayerSwitcher
 *
 * Inherits from:
 *  - <OpenLayers.Control>
 */
OpenLayers.Control.ckLayerSwitcher = 
  OpenLayers.Class(OpenLayers.Control, {

    /**  
     * Property: roundCorner
     * {Boolean}
     */
    roundCorner: true,

    /**  
     * Property: roundCorner
     * {Boolean}
     */
    activeColor: "#767A81",

    /**  
     * Property: layerStates 
     * {Array(Object)} Basically a copy of the "state" of the map's layers 
     *     the last time the control was drawn. We have this in order to avoid
     *     unnecessarily redrawing the control.
     */
    layerStates: null,
    

	/** @type String */
	// neuer Parameter KDVZ 2007-05-30
	controlWidth: "20em",

  // DOM Elements
  
    /**
     * Property: layersDiv
     * {DOMElement} 
     */
    layersDiv: null,
    
    /** 
     * Property: baseLayersDiv
     * {DOMElement}
     */
    baseLayersDiv: null,

    /** 
     * Property: baseLayers
     * {Array(<OpenLayers.Layer>)}
     */
    baseLayers: null,
    
    
    /** 
     * Property: dataLbl
     * {DOMElement} 
     */
    dataLbl: null,
    
    /** 
     * Property: dataLayersDiv
     * {DOMElement} 
     */
    dataLayersDiv: null,

    /** 
     * Property: dataLayers
     * {Array(<OpenLayers.Layer>)} 
     */
    dataLayers: null,


    /** 
     * Property: minimizeDiv
     * {DOMElement} 
     */
    minimizeDiv: null,

    /** 
     * Property: maximizeDiv
     * {DOMElement} 
     */
    maximizeDiv: null,
    
    /**
     * APIProperty: ascending
     * {Boolean} 
     */
    ascending: true,

    /**
     * Property: groupDivs
     * Object with {DOMElements}, {Booleans} and {Strings}
     */
     groups: {
              groupDivs:{},
              checked: {},
              layers:{},
              display: {}
              },

    /**
     * Constructor: OpenLayers.Control.ckLayerSwitcher
     * 
     * Parameters:
     * options - {Object}
     */
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
        this.layerStates = [];
    },

    /**
     * APIMethod: destroy 
     */    
    destroy: function() {
        
        OpenLayers.Event.stopObservingElement(this.div);

        OpenLayers.Event.stopObservingElement(this.minimizeDiv);
        OpenLayers.Event.stopObservingElement(this.maximizeDiv);

        //clear out layers info and unregister their events 
        this.clearLayersArray("base");
        this.clearLayersArray("data");
        
        this.map.events.unregister("addlayer", this, this.redraw);
        this.map.events.unregister("changelayer", this, this.redraw);
        this.map.events.unregister("removelayer", this, this.redraw);
        this.map.events.unregister("changebaselayer", this, this.redraw);
        
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },

    /** 
     * Method: setMap
     *
     * Properties:
     * map - {<OpenLayers.Map>} 
     */
    setMap: function(map) {
        OpenLayers.Control.prototype.setMap.apply(this, arguments);

        this.map.events.register("addlayer", this, this.redraw);
        this.map.events.register("changelayer", this, this.redraw);
        this.map.events.register("removelayer", this, this.redraw);
        this.map.events.register("changebaselayer", this, this.redraw);
    },

    /**
     * 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();    

        return this.div;
    },

    /** 
     * Method: clearLayersArray
     * User specifies either "base" or "data". we then clear all the
     *     corresponding listeners, the div, and reinitialize a new array.
     * 
     * Parameters:
     * layersType - {String}  
     */
    clearLayersArray: function(layersType) {
        var layers = this[layersType + "Layers"];
        if (layers) {
            for(var i=0; i < layers.length; i++) {
                var layer = layers[i];
                OpenLayers.Event.stopObservingElement(layer.inputElem);
                OpenLayers.Event.stopObservingElement(layer.labelSpan);
            }
        }
        this[layersType + "LayersDiv"].innerHTML = "";
        this[layersType + "Layers"] = [];
        this.groups.groupDivs = {};
    },


    /**
     * Method: checkRedraw
     * Checks if the layer state has changed since the last redraw() call.
     * 
     * Returns:
     * {Boolean} The layer state changed since the last redraw() call. 
     */
    checkRedraw: function() {
        var redraw = false;
        if ( !this.layerStates.length ||
             (this.map.layers.length != this.layerStates.length) ) {
            redraw = true;
        } else {
            for (var i=0; i < this.layerStates.length; i++) {
                var layerState = this.layerStates[i];
                var layer = this.map.layers[i];
                if ( (layerState.name != layer.name) || 
                     (layerState.inRange != layer.inRange) || 
                     (layerState.id != layer.id) || 
                     (layerState.visibility != layer.visibility) ) {
                    redraw = true;
                    break;
                }    
            }
        }    
        return redraw;
    },
    
    /** 
     * 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;
        var i;
        var layer;
        
        // 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 = [];
        for (i = 0; i < this.map.layers.length; i++) {
            layer = this.map.layers[i];
            this.layerStates[i] = {
                'name': layer.name, 
                'visibility': layer.visibility,
                'inRange': layer.inRange,
                'id': layer.id
            };
            
            // create group divs
            if (layer.group && !layer.isBaseLayer) {
                layer.group = layer.group.replace(/\/$/,"");
                layer.group = layer.group.replace(/^\//,"");
                this.createGroupDiv(layer.group);
            }
        }    

        var layers = this.map.layers.slice();
        if (!this.ascending) { layers.reverse(); }
        for(i = 0; i < layers.length; i++) {
            layer = layers[i];
            var baseLayer = layer.isBaseLayer;
            var layersDiv = null;

            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 div
                var layerDiv = document.createElement("div");
                var layerDivClass = "olLayerDiv" + (checked ? "Active" : "Inactive");

                // 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";
                    layerDivClass = "olLayerDiv"+"OutOfRange";
                }

                labelSpan.innerHTML = layer.name;
                // KDVZ 2007-11-05, Styles ueber CSS
                labelSpan.className = "olLayersLabel";
                labelSpan.style.verticalAlign = (baseLayer) ? "baseline" : "baseline";
                OpenLayers.Event.observe(labelSpan, "click", 
                    OpenLayers.Function.bindAsEventListener(this.onInputClick,
                                                            context)
                );
                layerDiv.className =  layerDivClass;
                
                var groupArray = (baseLayer) ? this.baseLayers : this.dataLayers;
                groupArray.push({
                    'layer': layer,
                    'inputElem': inputElem,
                    'labelSpan': labelSpan
                });
                                                     
    
                /* select parent DIV for layer, wheter it is Base/Data layer
                 * or some of the Groups
                 */
                if (!baseLayer) {
                    // no group
                    if (!layer.group)  {
                        layersDiv = this.dataLayersDiv;
                    }
                    // group exists it is most probably allready there
                    else {
                        var groupname = layer.group;
                        var div = this.groups.groupDivs[groupname];
                        // append layer to the group
                        this.appendLayerToGroups(layer);
                        layersDiv = div;
                    }
                }
                // base layers
                else {
                    layersDiv = this.baseLayersDiv;
                }
                
                
                // apend input and layer lables
                layerDiv.appendChild(inputElem);
                layerDiv.appendChild(labelSpan);

                /*
                 * buttons
                 */
                // remove button
                if (layer.buttonDropLayer === true) {
                    this.addDropLayerButton(layer,layerDiv);
                }

                // move button
                if (layer.buttonMoveLayer === true) {
                    this.addMoveLayerButton(layer,layerDiv);
                }

                // opacity button
                if (layer.buttonOpacity === true) {
                    this.addOpacityLayerButton(layer,layerDiv);
                }

                // extent button
                if (layer.buttonZoomToExtent === true) {
                    this.addZoomToLayerExtentButton(layer,layerDiv);
                }
                
                // extent button
                if (layer.buttonGetLegend === true) {
                    this.addGetLegendButton(layer,layerDiv);
                }
                
                // final line break
                layersDiv.appendChild(layerDiv);
            }
        }

        // if no overlays, dont display the overlay label
        this.dataLbl.style.display = (containsOverlays) ? "" : "none";        
        
        // if no baselayers, dont display the baselayer label
        this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";        

        return this.div;
    },

    /** 
     * Method:
     * A label has been clicked, check or uncheck its corresponding input
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {DOMElement} inputElem
     *  - {<OpenLayers.Control.ckLayerSwitcher>} layerSwitcher
     *  - {<OpenLayers.Layer>} layer
     */

    onInputClick: function(e) {

        if (!this.inputElem.disabled) {
            if (this.inputElem.type == "radio") {
                this.inputElem.checked = true;
                this.layer.map.setBaseLayer(this.layer);
            } else {
                this.inputElem.checked = !this.inputElem.checked;
                this.layerSwitcher.updateMap();
            }
        }
        OpenLayers.Event.stop(e);
    },

    /** 
     * Method:
     * A group label has been clicked, check or uncheck its corresponding input
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {DOMElement} inputElem
     *  - {<OpenLayers.Control.ckLayerSwitcher>} layerSwitcher
     *  - {DOMElement} groupDiv
     */

    onInputGroupClick: function(e) {

        // setup the check value
        var check = !this.inputElem.checked;

        // get all <input></input> tags in this div
        var inputs = this.groupDiv.getElementsByTagName("input");

        // check the group input, other inputs are in groupDiv,
        // inputElem is in parent div
        this.inputElem.checked=check;

        // store to groupCheckd structure, where it can be later found
        this.layerSwitcher.groups.checked[this.inputElem.value] = check;

        for (var i = 0; i < inputs.length; i++) {
            // same as above
            inputs[i].checked=check;
            this.layerSwitcher.groups.checked[inputs[i].value] = check;
        }

        // groups are done, now the layers
        var dataLayers = this.layerSwitcher.dataLayers;
        for (var j = 0; j < dataLayers.length; j++) {
            var layerEntry = dataLayers[j];   
            if (this.layerSwitcher.isInGroup(
                    this.inputElem.value,layerEntry.layer)) {
                layerEntry.inputElem.checked = check;
                layerEntry.layer.setVisibility(check);
            }
        }

        OpenLayers.Event.stop(e);
    },
    
    /**
     * Method: onLayerClick
     * Need to update the map accordingly whenever user clicks in either of
     *     the layers.
     * 
     * Parameters: 
     * e - {Event} 
     */
    onLayerClick: function(e) {
        this.updateMap();
    },

    /**
     * Method: onGroupClick
     * On group label was clicked
     * 
     * Context: 
     * layergroup - {String} 
     * groups - {Array} of {DOMElements}
     */
    onGroupClick: function(e) {
        var layergroup = this.layergroup;
        var div = this.groups.groupDivs[layergroup];
        if (div) {
            var colapse = (div.style.display != "block" ? true : false);
            this.layerswitcher.colapseGroup(layergroup,colapse);
        }
    },

    /**
     * Method: colapseGroup
     * Toggle group div with layers visibility
     * 
     * Context: 
     * layergroup - {String} 
     * colapse - {Boolean}
     */
    colapseGroup: function(layergroup,colapse) {
        var div = this.groups.groupDivs[layergroup];
        if (div) {
        	var groupNames = layergroup.split("/");
        	var folderId = "folder_"+groupNames.join("_");
        	var folder = OpenLayers.Util.getElement(folderId);
        	folder.src = (colapse === true ? "./theme/citkomm/img/folderopen.gif" : "./theme/citkomm/img/folder.gif");
        	//alert(folder.id);
            div.style.display = (colapse === true ? "block" : "none");
            this.groups.display[layergroup] = div.style.display;
        }
    },

    /**
     * Method: colapseAllGroups
     * Toggle group div with layers visibility
     * 
     * Context: 
     * layergroup - {String} 
     * colapse - {Boolean}
     */
    colapseAllGroups: function(colapse) {
    	for (var i in this.groups.groupDivs) {
    		//prompt(i, this.groups.groupDivs[i]);
    		this.colapseGroup(i,colapse);
    	}
    },

    /** 
     * Method: onRemoveLayerClick
     * 
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {Layer} Layer
     */

    onRemoveLayerClick: function(e) {
        
        var map = this.layer.map;
        map.removeLayer(this.layer,true);

        OpenLayers.Event.stop(e);
    },

    /** 
     * Method: onMoveLayerClick
     * 
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {Layer} Layer
     *  - {Boolean} up
     *  - layerSwitcher {OpenLayers.Control}
     */

    onMoveLayerClick: function(e) {
        
        var map = this.layer.map;
        var idx = null;
        var newidx = null;
        var layers = map.layers;
        var tmplayer = null;

        // get layer index
        for (var i = 0; i < map.layers.length; i++) {
            if (this.layer == map.layers[i]) {
                idx = i;
                break;
            }
        }

        // move up index
        if (this.up === true) {
            i = 1;
            while (1) {
                newidx = idx-i;
                if (newidx <= 0 ) {
                    newidx = 0;
                    break;
                }
                else if (map.layers[newidx].displayInLayerSwitcher === true && 
                    map.layers[newidx].group == map.layers[idx].group) {
                    break;
                }
                else {
                    i += 1;
                }
            }
        }
        // get down index
        else {
            i = 1;
            while (1) {
                newidx = idx+i;
                if (newidx >= map.getNumLayers()) {
                    newidx = map.getNumLayers()-1;
                    break;
                }
                else if (map.layers[newidx].displayInLayerSwitcher === true &&
                    map.layers[newidx].group == map.layers[idx].group) {
                    break;
                }
                else {
                    i += 1;
                }
            }
        }

        // switch
        map.raiseLayer(map.layers[idx], newidx-idx);

        this.layerSwitcher.redraw();
        OpenLayers.Event.stop(e);
    },

    /** 
     * Method: onOpacityLayerClick
     * 
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {Layer} Layer
     *  - {Boolean} up
     *  - layerSwitcher {OpenLayers.Control}
     */

    onOpacityLayerClick: function(e) {
        
        if (!this.layer.opacity) {
            this.layer.opacity = 1;
        }

        var opacity = this.layer.opacity;



        opacity = this.up === true ? opacity+0.1 : opacity-0.1;
        opacity = opacity < 0 ? 0 : opacity;
        opacity = opacity > 1 ? 1 : opacity;
        this.layer.setOpacity(opacity);

        //this.layerSwitcher.redraw();
        OpenLayers.Event.stop(e);
    },

    /** 
     * Method: onZoomToLayer
     * 
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {Layer} Layer
     *  - layerSwitcher {OpenLayers.Control}
     */

    onZoomToLayer: function(e) {
        
        var map = this.layer.map;
        map.zoomToExtent(this.layer.maxExtent);

        //this.layerSwitcher.redraw();
        OpenLayers.Event.stop(e);
    },

    /** 
     * Method: onZoomToLayer
     * 
     * 
     * Parameters:
     * e - {Event} 
     *
     * Context:  
     *  - {Layer} Layer
     *  - layerSwitcher {OpenLayers.Control}
     */

    onGetLegendClick: function(e) {
    	var url = this.layer.getFullRequestString({REQUEST: 'GetLegendGraphic', LAYER: this.layer.params.LAYERS});
    	var winParams = 'menubar=no,toolbar=no,location=no,directories=no,fullscreen=no,titlebar=yes,hotkeys=yes,status=yes,scrollbars=yes,resizable=yes'
		ckMapFunctions.targetBlank(url, 'LegendWin', winParams, 400, 600);
		
        OpenLayers.Event.stop(e);
    },

    /** 
     * Method: updateMap
     * Cycles through the loaded data and base layer input arrays and makes
     *     the necessary calls to the Map object such that that the map's 
     *     visual state corresponds to what the user has selected in 
     *     the control.
     */
    updateMap: function() {
        var i;
        var layerEntry;

    	// KDVZ 2007-11-05, loadstart Event
    	// fuer ckMsgbar Control
		this.map.events.triggerEvent("loadstart");

        // set the newly selected base layer        
        for(i=0; i < this.baseLayers.length; i++) {
            layerEntry = this.baseLayers[i];
            if (layerEntry.inputElem.checked) {
                this.map.setBaseLayer(layerEntry.layer, false);
            }
        }

        // set the correct visibilities for the overlays
        for(i=0; i < this.dataLayers.length; i++) {
            layerEntry = this.dataLayers[i];   
            layerEntry.layer.setVisibility(layerEntry.inputElem.checked);
        }
        // KDVZ 2007-11-05, loadend Event
        // fuer ckMsgbar Control
		this.map.events.triggerEvent("loadend");
    },

    /** 
     * Method: maximizeControl
     * Set up the labels and divs for the control
     * 
     * Parameters:
     * e - {Event} 
     */
    maximizeControl: function(e) {

        //HACK HACK HACK - find a way to auto-size this layerswitcher
        //this.div.style.width = "20em";
        // KDVZ 2007-11-05
        this.div.style.width = this.controlWidth;
        this.div.style.height = "";

        this.showControls(false);

        if (e) {
            OpenLayers.Event.stop(e);                                            
        }
    },
    
    /** 
     * Method: minimizeControl
     * Hide all the contents of the control, shrink the size, 
     *     add the maximize icon
     *
     * Parameters:
     * e - {Event} 
     */
    minimizeControl: function(e) {

        this.div.style.width = "0px";
        this.div.style.height = "0px";

        this.showControls(true);

        if (e) {
            OpenLayers.Event.stop(e);                                            
        }
    },

    /**
     * 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" : "block";

        this.layersDiv.style.display = minimize ? "none" : "";
    },
    
    /** 
     * Method: loadContents
     * Set up the labels and divs for the control
     */
    loadContents: function() {

        // KDVZ 2007-05-30, class name
        this.div.className = "olControlLayerSwitcher";
        //configure main div
        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.id = "olLayersDiv";
        // KDVZ 2007-11-05, class name
        this.layersDiv.className = "olLayersDiv";

        this.baseLbl = document.createElement("div");
        this.baseLbl.className = "olGroupLabel";
        this.baseLbl.id = "olBaseLayerLabel";
        // KDVZ 2007-11-05, deutsche Texte
        //this.baseLbl.innerHTML = "Base Layer";
        this.baseLbl.innerHTML = OpenLayers.i18n("baseLayer");
        
        this.baseLayersDiv = document.createElement("div");
        this.baseLayersDiv.id = "olBaseLayersDiv";
        this.baseLayersDiv.className = "olDataOrBaseLayersDiv";

        this.dataLbl = document.createElement("div");
        this.dataLbl.className = "olGroupLabel";
        this.dataLbl.id = "olDataLayerLabel";
        // KDVZ 2007-11-05, deutsche Texte
        //this.dataLbl.innerHTML = "Overlays";
        this.dataLbl.innerHTML = OpenLayers.i18n("overlays");
        
        this.dataLayersDiv = document.createElement("div");
        this.dataLayersDiv.id = "olBaseLayersDiv";
        this.dataLayersDiv.className = "olDataOrBaseLayersDiv";

        if (this.ascending) {
            this.layersDiv.appendChild(this.baseLbl);
            this.layersDiv.appendChild(this.baseLayersDiv);
            this.layersDiv.appendChild(this.dataLbl);
            this.layersDiv.appendChild(this.dataLayersDiv);
        } else {
            this.layersDiv.appendChild(this.dataLbl);
            this.layersDiv.appendChild(this.dataLayersDiv);
            this.layersDiv.appendChild(this.baseLbl);
            this.layersDiv.appendChild(this.baseLayersDiv);
        }    
 
        this.div.appendChild(this.layersDiv);

        if (this.roundCorner === true ) {
            OpenLayers.Rico.Corner.round(this.div, {corners: "tl bl",
                                            bgColor: "transparent",
                                            color: this.activeColor,
                                            blend: false});

            // OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
            // KDVZ, 2007-11-05
            OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.90);
        }

        var imgLocation = OpenLayers.Util.getImagesLocation();
        var sz = new OpenLayers.Size(18,18);        

        // maximize button div
        var img = imgLocation + 'layer-switcher-maximize.png';
        this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                    "OpenLayers_Control_MaximizeDiv", 
                                    null, 
                                    sz, 
                                    img, 
                                    "absolute");
        this.maximizeDiv.style.top = "5px";
        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
        img = imgLocation + 'layer-switcher-minimize.png';
        sz = new OpenLayers.Size(18,18);        
        this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
                                    "OpenLayers_Control_MinimizeDiv", 
                                    null, 
                                    sz, 
                                    img, 
                                    "absolute");
        this.minimizeDiv.style.top = "5px";
        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: ignoreEvent
     * 
     * Parameters:
     * evt - {Event} 
     */
    ignoreEvent: function(evt) {
        OpenLayers.Event.stop(evt);
    },

    /** 
     * Method: mouseDown
     * Register a local 'mouseDown' flag so that we'll know whether or not
     *     to ignore a mouseUp event
     * 
     * Parameters:
     * evt - {Event}
     */
    mouseDown: function(evt) {
        this.isMouseDown = true;
        this.ignoreEvent(evt);
    },

    /** 
     * Method: mouseUp
     * If the 'isMouseDown' flag has been set, that means that the drag was 
     *     started from within the LayerSwitcher control, and thus we can 
     *     ignore the mouseup. Otherwise, let the Event continue.
     *  
     * Parameters:
     * evt - {Event} 
     */
    mouseUp: function(evt) {
        if (this.isMouseDown) {
            this.isMouseDown = false;
            this.ignoreEvent(evt);
        }
    },

    /** 
     * Method: onMouseOver
     *  
     * Parameters:
     * evt - {Event} 
     */
    onMouseOver: function(evt) {
		this.groupNameDiv.style.cursor = "pointer";
    },

    /** 
     * Method: onMouseOut
     *  
     * Parameters:
     * evt - {Event} 
     */
    onMouseOut: function(evt) {
		this.groupNameDiv.style.cursor = "default";
    },

    /** 
     * Method: createGroupDiv
     * Creates <div></div> element for group of layers defined by input string.
     * 
     * Parameters:
     * layergroup - {String} with group structure as "Parent Group/It's child"
     *  
     * Returns:
     * {DOMElement} <div></div> object for this group of layers
     */
    createGroupDiv: function(layergroup) {
        var groupNames = layergroup.split("/"); // array with layer names
        var groupName = groupNames[groupNames.length-1]; // name of the last group in the line
        var groupDiv = this.groups.groupDivs[layergroup];
        var groupNameDiv =  document.createElement("div");

        groupNameDiv.className = "olGroupName";
        
        // groupDiv does not exist: create
        if (!groupDiv) {

            // search for the parent div - it can be another group div, or 
            // this dataLayersDiv directly
            var parentDiv = this.groups.groupDivs[groupNames.slice(0,groupNames.length-2).join("/")];

            if (!parentDiv) {

                // dataLayersDiv is parent div
                if (groupNames.length == 1) {
                    parentDiv = this.dataLayersDiv;
                }
                // there is no such thing, like parent div,
                else {
                    parentDiv = this.createGroupDiv( groupNames.slice(0,groupNames.length-1).join("/"));
                }
            }

            // create the div

            groupDiv = document.createElement("div");
            groupDiv.className = "olLayerGroup";
            if (!this.groups.display[layergroup]) {
                this.groups.display[layergroup] = "block";
            }
            groupDiv.style.display= this.groups.display[layergroup];
            this.groups.groupDivs[layergroup] = groupDiv;

            // create the label
            var groupLbl = document.createElement("span");
            groupLbl.className = "olSubGroupLabel";
            groupLbl.innerHTML=groupName;

			// KDVZ 2008-06-26
			// Darstellung mit Folder-Symbol
            // setup mouse click event on groupLbl
            /*OpenLayers.Event.observe(groupLbl, "mouseup", 
                OpenLayers.Function.bindAsEventListener(
                    this.onGroupClick, {layergroup: layergroup, groups:
                    this.groups,layerswitcher:this}));
            */
            // create input checkbox
            var groupInput = document.createElement("input");
            groupInput.id = "input_" + groupNames.join("_");
            groupInput.name = groupNames.join("_");
            groupInput.type = "checkbox";
            groupInput.value = layergroup;
            groupInput.checked = false;
            groupInput.defaultChecked = false;
            if (!this.groups.checked[layergroup]) {
                this.groups.checked[layergroup] = false;
            }
            groupInput.checked = this.groups.checked[layergroup];
            groupInput.defaultChecked = this.groups.checked[layergroup];

            // create empty array of layers
            if (!this.groups.layers[layergroup]) {
                this.groups.layers[layergroup] = [];
            }
            
            // setup mouse click event on groupInput
            var context = {groupDiv: groupDiv,
                            layerSwitcher: this,
                            inputElem: groupInput};
            /*
            OpenLayers.Event.observe(groupInput, "mouseup", 
                OpenLayers.Function.bindAsEventListener(
                    this.onInputGroupClick, context));
            */        
			// KDVZ 2008-06-26
			// Darstellung mit Folder-Symbol
            var folderImg = document.createElement("img");
            folderImg.name = groupNames.join("_");
            folderImg.id = "folder_" + groupNames.join("_");
            folderImg.src = (groupDiv.style.display == "block" ? "./theme/citkomm/img/folderopen.gif" : "./theme/citkomm/img/folder.gif");
            folderImg.style.border = "medium none";
            folderImg.style.padding = "2px";
            folderImg.style.width = "16px";
            folderImg.style.height = "16px";
            folderImg.style.verticalAlign = "top";
            
            context = {layergroup: layergroup, 
            			groups:this.groups,
            			groupNameDiv: groupNameDiv,
            			layerswitcher:this};
                       
            // setup mouse click event on groupLbl
            OpenLayers.Event.observe(groupNameDiv, "mouseup", 
                OpenLayers.Function.bindAsEventListener(
                    this.onGroupClick, context));
            // setup mouseover event on groupLbl
            OpenLayers.Event.observe(groupNameDiv, "mouseover", 
                OpenLayers.Function.bindAsEventListener(this.onMouseOver, context));
            // setup mouseout event on groupLbl
            OpenLayers.Event.observe(groupNameDiv, "mouseout", 
                OpenLayers.Function.bindAsEventListener(this.onMouseOut, context));
                    
            // append to parent div
            //groupNameDiv.appendChild(groupInput);
            groupNameDiv.appendChild(folderImg);
            groupNameDiv.appendChild(groupLbl);
            parentDiv.appendChild(groupNameDiv);
            parentDiv.appendChild(groupDiv);

        }

        return this.groups.groupDivs[layergroup];
    },
	
    /** 
     * Method: addLayerToGroups
     * each group has own {Array} with list of layrs. E.g. layer with group
     * "group1/group2" is member of two groups: "group1" and
     * "group1/group2"
     * 
     * Parameters:
     * layer 
     *  
     */
    appendLayerToGroups: function(layer) {
        var groupNames = layer.group.split("/");
        var groupName = null;

        for (var i = 1; i <= groupNames.length; i++) {
            groupName = groupNames.slice(0,i).join("/");
            if (!this.isInGroup(groupName,layer)) {
                this.groups.layers[groupName].push(layer);
            }
        }
    },
    
    /** 
     * Method: isInGroup
     * 
     * 
     * Parameters:
     * groupName - {String} name of the group
     * layer 
     *  
     * Returns:
     * {Boolean} -- the layer is available in this group with specified
     * name or not
     */
    isInGroup: function (groupName, layer) {
        for (var j = 0; j < this.groups.layers[groupName].length; j++) {
            if (this.groups.layers[groupName][j].id == layer.id) {
                return true;
            }
        }
        return false;
    },

    /** 
     * Method: addDroplayerButton
     * Creates button with "Drop layer" funtionality
     * 
     * Parameters:
     * layer
     * div - {DOMElement} -- div, to which the button should be appended
     *  
     */
    addDropLayerButton: function (layer, div) {
        var button = document.createElement("img");
        button.src =OpenLayers.Util.getImagesLocation()+"/remove_layer.png"; 
        button.width=10;
        button.heigth=10;
        button.alt="Thema entfernen";
        button.title="Thema entfernen";
        button.style.margin = "3px";
        button.style.padding = "1px";
        button.style.border = "1px white solid";
        button.style.verticalAlign = "middle";
        div.appendChild(button);
        
        //event
        OpenLayers.Event.observe(button, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onRemoveLayerClick,
                                                    {"layer":layer}));

    },

    /** 
     * Method: addMoveLayerButton
     * Creates button with "Move layer up and down" funtionality
     * 
     * Parameters:
     * layer
     * div - {DOMElement} -- div, to which the button should be appended
     *  
     */
    addMoveLayerButton: function (layer, div) {
        var buttonDiv = document.createElement("div");
        buttonDiv.style.padding="0px";
        buttonDiv.style.margin="0px";
        buttonDiv.style.display="inline";

        var buttonUp = document.createElement("img");
        buttonUp.src =OpenLayers.Util.getImagesLocation()+"/move_layer_up.png"; 
        buttonUp.width=10;
        buttonUp.heigth=10;
        buttonUp.alt="Thema nach oben verschieben";
        buttonUp.title="Thema nach oben verschieben";
        buttonUp.style.margin = "3px";
        buttonUp.style.marginRight = "0px";
        buttonUp.style.padding = "1px";
        buttonUp.style.paddingRight = "0px";
        buttonUp.style.border = "1px white solid";
        buttonUp.style.borderRight = "0px";
        buttonUp.style.verticalAlign = "middle";
        buttonDiv.appendChild(buttonUp);

        var buttonDown = document.createElement("img");
        buttonDown.src =OpenLayers.Util.getImagesLocation()+"/move_layer_down.png"; 
        buttonDown.width=10;
        buttonDown.heigth=10;
        buttonDown.alt="Thema nach unten verschieben";
        buttonDown.title="MThema nach unten verschieben";
        buttonDown.style.margin = "3px";
        buttonDown.style.marginLeft = "0px";
        buttonDown.style.padding = "1px";
        buttonDown.style.paddingLeft = "0px";
        buttonDown.style.border = "1px white solid";
        buttonDown.style.borderLeft = "0px";
        buttonDown.style.verticalAlign = "middle";
        buttonDiv.appendChild(buttonDown);

        div.appendChild(buttonDiv);

        //event
        OpenLayers.Event.observe(buttonUp, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onMoveLayerClick,
                                                    {"layer":layer,"up":true,layerSwitcher:this}));
        OpenLayers.Event.observe(buttonDown, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onMoveLayerClick,
                                                    {"layer":layer,"up":false,layerSwitcher:this}));
    },

    /** 
     * Method: addOpacityLayerButton
     * Creates button with "Set opacity height and down" funtionality
     * 
     * Parameters:
     * layer
     * div - {DOMElement} -- div, to which the button should be appended
     *  
     */
    addOpacityLayerButton: function (layer, div) {
        var buttonDiv = document.createElement("div");
        buttonDiv.style.padding="0px";
        buttonDiv.style.margin="0px";
        buttonDiv.style.display="inline";

        var buttonUp = document.createElement("img");
        buttonUp.src =OpenLayers.Util.getImagesLocation()+"/set_layer_opacity_up.png"; 
        buttonUp.width=10;
        buttonUp.heigth=10;
        buttonUp.alt="Transparenz reduzieren";
        buttonUp.title="Transparenz reduzieren";
        buttonUp.style.margin = "3px";
        buttonUp.style.marginRight = "0px";
        buttonUp.style.padding = "1px";
        buttonUp.style.paddingRight = "0px";
        buttonUp.style.border = "1px white solid";
        buttonUp.style.borderRight = "0px";
        buttonUp.style.verticalAlign = "middle";
        buttonDiv.appendChild(buttonUp);

        var buttonDown = document.createElement("img");
        buttonDown.src =OpenLayers.Util.getImagesLocation()+"/set_layer_opacity_down.png"; 
        buttonDown.width=10;
        buttonDown.heigth=10;
        buttonDown.alt="Transparenz erhöhen";
        buttonDown.title="Transparenz erhöhen";
        buttonDown.style.margin = "3px";
        buttonDown.style.marginLeft = "0px";
        buttonDown.style.padding = "1px";
        buttonDown.style.paddingLeft = "0px";
        buttonDown.style.border = "1px white solid";
        buttonDown.style.borderLeft = "0px";
        buttonDown.style.verticalAlign = "middle";
        buttonDiv.appendChild(buttonDown);

        div.appendChild(buttonDiv);

        //event
        OpenLayers.Event.observe(buttonUp, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onOpacityLayerClick,
                                                    {"layer":layer,"up":true,layerSwitcher:this}));
        OpenLayers.Event.observe(buttonDown, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onOpacityLayerClick,
                                                    {"layer":layer,"up":false,layerSwitcher:this}));
    },

    /** 
     * Method: addZoomToLayerExtentButton
     * Creates button with "Zoom to layer extent" funtionality
     * 
     * Parameters:
     * layer
     * div - {DOMElement} -- div, to which the button should be appended
     *  
     */
    addZoomToLayerExtentButton: function (layer, div) {

        var button = document.createElement("img");
        button.src =OpenLayers.Util.getImagesLocation()+"/set_zoom_to_layer_extent.png"; 
        button.width=10;
        button.heigth=10;
        button.alt="Zoom to layer extent";
        button.title="Zoom to layer extent";
        button.style.margin = "3px";
        button.style.marginRight = "0px";
        button.style.padding = "1px";
        button.style.paddingRight = "0px";
        button.style.border = "1px white solid";
        button.style.borderRight = "0px";
        button.style.verticalAlign = "middle";
        div.appendChild(button);

        //event
        OpenLayers.Event.observe(button, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onZoomToLayer,
                                                    {"layer":layer,layerSwitcher:this}));
    },

    /** 
     * Method: addDroplayerButton
     * Creates button with "Drop layer" funtionality
     * 
     * Parameters:
     * layer
     * div - {DOMElement} -- div, to which the button should be appended
     *  
     */
    addGetLegendButton: function (layer, div) {
        var button = document.createElement("img");
        button.src = OpenLayers.Util.getImagesLocation()+"/map.png"; 
        button.width= 12;
        button.heigth= 12;
        button.alt= "Legende zeigen";
        button.title= "Legende zeigen";
        button.style.margin = "3px";
        //button.style.padding = "1px";
        //button.style.border = "1px white solid";
        button.style.verticalAlign = "middle";
        div.appendChild(button);
        
        //event
        OpenLayers.Event.observe(button, "mouseup", 
            OpenLayers.Function.bindAsEventListener(this.onGetLegendClick,
                                                    {"layer":layer}));
    },

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

