
// Legend Tool
// Drawing principle : when legend is drawn, it follows this principle : checkboxes are dynamically checked /unchecked,  but don't directly interact with layer visibility : 
// events handle interactivity between checkboxes and layers visibility, using the "update" function (on event, function go through all checkboxes and set visibility of
// layers, according to current scale)
// schema : (oKaMap, legendOptions, alwaysShowInLegend, legendContainers, legendGroupNames, legendRadios, legendFunctionImages, [clickFunction] )
function kaLegend(oKaMap, options, alwaysShowInLegend, legendContainers, legendGroupNames, legendRadios, legendFunctionImages) {
    this.kaMap = oKaMap;
	this.alwaysShowInLegend = alwaysShowInLegend;
	this.legendContainers = legendContainers;
	this.legendGroupNames = legendGroupNames;
	this.legendRadios = legendRadios;
	this.legendFunctionImages = legendFunctionImages;
	
	this.kaMap.kaLegend = this;
	
	if(arguments.length == 8)
		this.clickFunction = arguments[7];

	this.legendCBs = new Array();
	this.legendRDs = new Array();

	// default values for options are "true"
    this.showVisibilityControl = options['showVisibilityControl'];
    this.showIcons = options['showIcons'];
    this.showOpacityControl = options['showOpacityControl'];
    this.showOrderControl = options['showOrderControl'];    
	
	this.kaMap.registerForEvent( KAMAP_MAP_INITIALIZED, this, this.draw );
    this.kaMap.registerForEvent( KAMAP_SCALE_CHANGED, this, this.update );
    this.kaMap.registerForEvent( KAMAP_LAYER_STATUS_CHANGED, this, this.update );
};

/*
 * Update the legend
 * 
 * update(eventID, [layer])
 * layer is the layer checked/unchecked
 */
kaLegend.prototype.update = function(eventID){
    if (eventID == KAMAP_SCALE_CHANGED) {
		for(var i in this.legendRDs){
			var oLayer = this.kaMap.getCurrentMap().getLayer(this.legendRDs[i].value);
			// set visibility of layer if visible at current scale
			if(oLayer.isVisible()){
				this.kaLegend_setLayerVisibility( oLayer.name, this.legendRDs[i].checked);
			}
			// set visibility in legend for layer
			this.checkLayerLegendVisibility(oLayer);
		}
			
		for(var i in this.legendCBs){
			var oLayer = this.kaMap.getCurrentMap().getLayer(this.legendCBs[i].value);
			// set visibility of layer if visible at current scale
			if(oLayer.isVisible())
				this.kaLegend_setLayerVisibility( oLayer.name, this.legendCBs[i].checked);
				
			// set visibility in legend for layer
			this.checkLayerLegendVisibility(oLayer);
		}
    }
    
	// update visibility of layers if visible at current scale
	else if (eventID == KAMAP_LAYER_STATUS_CHANGED) {
		// get the concerned layer
		var oLayer = this.kaMap.getCurrentMap().getLayer(arguments[1]);
		var counter = 0;
		// go through all  buttons and set layer visible if visible at current scale
		if(oLayer){
			//var wasCB = false; 
			for(var i in this.legendCBs){
				currentLayer = this.kaMap.getCurrentMap().getLayer(this.legendCBs[i].value);
				if(currentLayer.isVisible()){
					this.kaLegend_setLayerVisibility(this.legendCBs[i].value, this.legendCBs[i].checked);
				}
			}

			for(var i in this.legendRDs){
				var currentLayer = this.kaMap.getCurrentMap().getLayer(this.legendRDs[i].value);
				if(currentLayer.isVisible()){
					this.kaLegend_setLayerVisibility(this.legendRDs.value, this.legendRDs[i].checked);
				}
			}
		}
	}
};

/**
 * legend.draw( szContents )
 *
 * render the contents of a legend template into a div
 */
kaLegend.prototype.draw = function() {

    var aLayers = this.kaMap.getCurrentMap().getAllLayers();
    
    // for each layer except the one called __base__, create an HTML legend
    for (var i = 0; i < aLayers.length; i++){
        if(aLayers[i].kaLegendObj == null && aLayers[i].name != "__base__") {
            this.createLayerHTML( aLayers[i] );
        }
    }
	
	// get div containers for each layer
    for (var i = 0; i < aLayers.length; i++) {
    	for(var j in this.legendContainers){
    		if(aLayers[i].name == j){
    			aLayers[i].legendContainer = this.legendContainers[j];
    		}
    	}
    }
    
    // put each layer in its "legendContainer" div
    for(var i = aLayers.length - 1; i >= 0; i--){
       	if(aLayers[i].legendContainer){
        	try{
	       		this.kaMap.getRawObject(aLayers[i].legendContainer).appendChild( aLayers[i].kaLegendObj );
    		}
	    	catch(e){
    			alert("kaLegend : object with id '"+ aLayers[i].legendContainer +"' not found on page!");
    		}
    	}
    	else{
    		alert("No container defined for layer " + aLayers[i].name + " (define it in startup.js in array legendContainer)");
    	}
    }
    return;
};

// draw the html legend element for each layer
kaLegend.prototype.createLayerHTML = function( oLayer ) {
    var d, t, tb, tr, td, sel, img;
    var th = this;

    d = document.createElement("div");
    d.id = 'group_' + oLayer.name;
    d.className = "kaLegendLayer";
    d.oLayer = oLayer;
    oLayer.kaLegendObj = d;

    t = document.createElement("table");

	tb = document.createElement("tbody");

    tr = document.createElement("tr");
    
    // layer visibility checkboxes
    if (this.showVisibilityControl){
        td = document.createElement("td");
        td.className = "kaLegendLayer_checkbox";
		
        // check if layer should be a radio button
        for(var key in this.legendRadios){
        	if(key == oLayer.name)
        		oLayer.radioGroupName = this.legendRadios[key];
        }
		
		
		// layer checkbox will be radio
        if(oLayer.radioGroupName != undefined){
			// try block due to bug in IE (see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp)
			try{
				var sel = document.createElement("<input type='radio' name='"+oLayer.radioGroupName+"'>");
			}
			catch(e){
				var sel = document.createElement("input");
				sel.type = "radio";
				sel.name = oLayer.radioGroupName;
        	}
			
			
			if(this.legendRadios['defaultChecked'][oLayer.radioGroupName] == oLayer.name){
	        	sel.checked = true;
				sel.defaultChecked = true; // for IE
	        }
			
	        this.legendRDs.push(sel);
        }
		// button is checkbox 
        else{
			var sel = document.createElement("input");
	        sel.type = "checkbox";
        	sel.name = "layerVisCB";
        	sel.checked = oLayer.visible;
			sel.defaultChecked = oLayer.visible; // for IE
        	this.legendCBs.push(sel);
        }
		oLayer.input = sel;
        sel.value = oLayer.name;
        sel.onclick = function(e){th.toggleLayerVisibility(e)};
        
        td.appendChild( sel );

        tr.appendChild(td);
    }
    
    // Icon visibilty
    if(this.showIcons){
    	td = document.createElement("td");
    	tr.appendChild(td);
    	
    	img = document.createElement("img");
    	td.appendChild(img);
    	img.src = (oLayer.iconPath == null)?("images/a_pixel.gif"):oLayer.iconPath;
    }
	
	// Opacity control
    if (this.showOpacityControl) {
        td = document.createElement("td");
        
        img = document.createElement("img");
		img.className = "kaLegendLayer_opacity_imgDOWN";
        img.src = this.legendFunctionImages['opacityDown'];
        img.alt = "Decrease layer opacity";
        img.title = "Decrease layer opacity";
        img.kaLegend = this;
        img.oLayer = oLayer;
        img.onclick = function(e){th.opacityDown(e)};
        td.appendChild( img );
        
        img = document.createElement("img");
		img.className = "kaLegendLayer_opacity_imgUP";
        img.src = this.legendFunctionImages['opacityUp'];
        img.alt = "Increase layer opacity";
        img.title = "Increase layer opacity";
        img.kaLegend = this;
        img.oLayer = oLayer;
        img.onclick = function(e){th.opacityUp(e)};
        td.appendChild( img );
        tr.appendChild(td);
    }
    
    // shiftcontrol (up/down);
    if (this.showOrderControl) {
        td = document.createElement("td");
		td.className = "kaLegendLayer_ZindexControl";
    
        img = document.createElement("img");
		img.className = "kaLegendLayer_ZindexControl_imgUP";
        img.src = this.legendFunctionImages['orderUp'];
        img.alt = "Shift Layer Up";
        img.title = "Shift Layer Up";
        img.kaLegend = this;
        img.oLayer = oLayer;
        img.myDiv = d;
        img.onclick = function(e){th.moveLayerUp(e)};
        td.appendChild( img );
    
        img = document.createElement("img");
		img.className = "kaLegendLayer_ZindexControl_imgDOWN";
        img.src = this.legendFunctionImages['orderDown'];
        img.alt = "Shift Layer Down";
        img.title = "Shift Layer Down";
        img.kaLegend = this;
        img.oLayer = oLayer;
        img.myDiv = d;
        img.onclick = function(e){th.moveLayerDown(e)};
        td.appendChild( img );
    
        tr.appendChild(td);
    }

	// label
    td = document.createElement("td");
    td.innerHTML = tra[("layer_"+oLayer.name)];
	td.className = "kaLegendLayer_legendLabel";
    tr.appendChild(td);
    tb.appendChild(tr);
    t.appendChild(tb);
    
    d.appendChild(t);
    /*
    img = document.createElement( 'img' );
    img.id = 'legendImg_' + oLayer.name;
    img.src = this.urlBase +  'legend.php?map='+this.kaMap.currentMap+'&scale='+this.kaMap.getCurrentScale()+'&g='+oLayer.name;
	d.appendChild(img);
    expander.expandable = img;
    oLayer.kaLegendObj = d;
    kaLegend_expander.apply( expander );
    */
	
	// check : if layer is in array "alwaysShowInLegend", don't set the html layer visibilty. Else do it.
	this.checkLayerLegendVisibility(oLayer);
};


// check if layer is in alwaysShowInLegend. If true, it doesn't update legend layer visibility, else updates if layer
// is visible at current scale
kaLegend.prototype.checkLayerLegendVisibility = function(oLayer){
	var setIt = true;
	for(var i in this.alwaysShowInLegend){
		if(setIt && this.alwaysShowInLegend[i] == oLayer.name)
			setIt = false;
	}

	if(setIt && oLayer.kaLegendObj){
		if(oLayer.isVisible()){
			oLayer.kaLegendObj.style.display='block';
			//alert(oLayer.name + " was set to : display block");
		}
		else{
			oLayer.kaLegendObj.style.display='none';
			//alert(oLayer.name + " was set to : display none");
		}
	}
	return;
};

kaLegend.prototype.toggleLayerVisibility = function(e) {
	e = (e)?e:((event)?event:null);
	var srcEvent = (e.target)?e.target:(e.srcElement)?e.srcElement:null;
    //alert("event :\n type : " + srcEvent.type + "\n radiogroupName : " + srcEvent.name+ "\n value : " + srcEvent.value + "\n checked : " + srcEvent.checked);
	
	// if a click function has been defined, apply it
    if(this.clickFunction){
    	this.clickFunction.apply(null, [srcEvent]);
    }
	this.kaMap.triggerEvent(KAMAP_LAYER_STATUS_CHANGED, srcEvent.value, srcEvent.checked, e);
};


// this function is same as the one in kamap.js, but it doesn't trigger KAMAP_LAYER_STATUS_CHANGED event (usefull here to avoid recursion)
kaLegend.prototype.kaLegend_setLayerVisibility = function(name, bVisible){
	var layer = this.kaMap.getCurrentMap().getLayer(name);
	// if layer's visibility is already set to bVisible, we don't do anything
	if(layer.visible != bVisible){
		if(!this.kaMap.loadUnchecked && bVisible) {
	        layer.visible = true;
	        this.kaMap.setMapLayers();
			if(layer.domObj){
				layer.domObj.style.visibility = bVisible?'visible':'hidden';
				layer.domObj.style.display = bVisible?'block':'none';
				for( var i = 0; i < layer.domObj.childNodes.length; i++) {
					layer.setTile(layer.domObj.childNodes[i]);
				}
			}
	        this.kaMap.paintLayer(layer);
	    }
		else {
	        if(layer.domObj){
				layer.visible = false;
				layer.domObj.style.visibility = bVisible?'visible':'hidden';
				layer.domObj.style.display = bVisible?'block':'none';
				for( var i = 0; i < layer.domObj.childNodes.length; i++) {
					layer.setTile(layer.domObj.childNodes[i]);
				}
			}
	    }
	}
};

kaLegend.prototype.opacityDown = function(e) {
	var srcEvent = this.getSrcEvent(e);
	var oLayer = srcEvent.oLayer;
    var opc = oLayer.opacity - 10;
    this.kaMap.setLayerOpacity(oLayer.name, opc );  
};

kaLegend.prototype.opacityUp = function(e) {
	var srcEvent = this.getSrcEvent(e);
	var oLayer = srcEvent.oLayer;  
    var opc = oLayer.opacity + 10;
    this.kaMap.setLayerOpacity(oLayer.name, opc );
};


/**
* kaLegend_moveLayerDown 
* About a specific Group of layer, it moves the corresponding Legend div and 
*  the Viewport div to the next one
* @private 
* @author Lorenzo Becchi
*/
kaLegend.prototype.moveLayerDown = function(e) {
	var srcEvent = this.getSrcEvent(e);
    var myLayer = srcEvent.oLayer;
    var leg = srcEvent.myDiv.parentNode;
    var myDiv = srcEvent.myDiv;
    var lowerDiv = this.findLowerDiv(myDiv);
    
    if(lowerDiv && lowerDiv.className=='kaLegendLayer') {
        //search correspondant checbox to prevent IE uncheck on move bug
        var aCheckbox = document.getElementsByTagName('input');
        var checkboxStatusUp = null;
        var checkboxStatusDown = null;
        var checkboxUp = null;
        var checkboxDown = null;
        for(var i = 0; i < aCheckbox.length; i++) {
            var inputTag = aCheckbox[i];
            if(inputTag.value == myDiv.id.replace(/\bgroup_/, '')) {
                checkboxUp = inputTag;
                checkboxStatusUp = checkboxUp.checked;
            }
            if(inputTag.value == lowerDiv.id.replace(/\bgroup_/, '')) {
                checkboxDown =inputTag;
                checkboxStatusDown = inputTag.checked;
            }
        }
        
        // move legend group div  (need to do it to allow hidden layers syncing)
        var proxyMy = myDiv.cloneNode(true);
        var proxyLower = lowerDiv.cloneNode(true);
        myDiv.parentNode.insertBefore( proxyMy , myDiv );
        myDiv.parentNode.insertBefore( proxyLower , lowerDiv );
        myDiv.parentNode.replaceChild( lowerDiv , proxyMy );
        myDiv.parentNode.replaceChild( myDiv , proxyLower );
        
        //confirm checbox status to prevent IE uncheck on move bug
        if(checkboxUp)
        	checkboxUp.checked = checkboxStatusUp;
        if(checkboxDown)
        	checkboxDown.checked = checkboxStatusDown;
	
		//added by cappu,set zindex order of div layer in viewport
		for  (i=0,n=leg.childNodes.length; i < leg.childNodes.length; i++) {
			var child = leg.childNodes[i];
			if(child && child.className == 'kaLegendLayer') {
				child.oLayer.zIndex=(n);
				n--;
			}
		}
		
		//call function to redraw
		this.kaMap.setMapLayers();
    } 
    else {
        alert('this layer can\'t go farther down');
    } 
};

/**
 * kaLegend_moveLayerUp
 * About a specific Group of layer, it moves the corresponding Legend div and 
 * the  Viewport div to the previous one
 * @private 
 * @author Lorenzo Becchi
 */
kaLegend.prototype.moveLayerUp = function(e) {
	var srcEvent = this.getSrcEvent(e);
    var myLayer = srcEvent.oLayer;
    var leg = srcEvent.myDiv.parentNode;
    var myDiv = srcEvent.myDiv;
    var upperDiv = this.findUpperDiv(myDiv);
    
     if(upperDiv && upperDiv.className == 'kaLegendLayer') {
        //search correspondant checbox to prevent IE uncheck on move bug
        var aCheckbox = document.getElementsByTagName('input');
        var checkboxStatusUp = null;
        var checkboxStatusDown = null;
        var checkboxUp = null;
        var checkboxDown = null;
        for(var i = 0; i < aCheckbox.length; i++) {
            var inputTag = aCheckbox[i];
            if(inputTag.value == upperDiv.id.replace(/\bgroup_/, '')) {
                checkboxUp = inputTag;
                checkboxStatusUp = checkboxUp.checked;
            }
            if(inputTag.value == myDiv.id.replace(/\bgroup_/, '')) {
                checkboxDown =inputTag;
                checkboxStatusDown = inputTag.checked;
            }
        }
        
        // switch legend groups div (need to do it two allow hidden layers syncing)
        var proxyMy = myDiv.cloneNode(true);
        var proxyUpper = upperDiv.cloneNode(true);      
        myDiv.parentNode.insertBefore( proxyMy , myDiv );
        myDiv.parentNode.insertBefore( proxyUpper , upperDiv );
        myDiv.parentNode.replaceChild( upperDiv , proxyMy );
        myDiv.parentNode.replaceChild( myDiv , proxyUpper );
        
        //confirm checbox status to prevent IE uncheck on move bug
        if(checkboxUp)checkboxUp.checked = checkboxStatusUp;
        if(checkboxDown)checkboxDown.checked = checkboxStatusDown;
		
		//added by cappu,set zindex order of div layer in vieport
		for  (i = 0,n = leg.childNodes.length; i < leg.childNodes.length; i++) {
		    var child = leg.childNodes[i];
		    if(child && child.className == 'kaLegendLayer') {
				child.oLayer.zIndex=(n);
				n--;
			}
		}
		//call function to redraw
		this.kaMap.setMapLayers();
    }
    else {
        alert('this layer can\'t go farther up');
    }
};

/**
* findLowerDiv
* find recursively nextSibling in legend list
* @private 
* @author Lorenzo Becchi
*/
kaLegend.prototype.findLowerDiv = function(div) {
	var lDiv = div.nextSibling;
	if(lDiv && lDiv.className=='kaLegendLayer' && lDiv.style.display=='none') {
		this.findLowerDiv(lDiv);
	}
	return lDiv;
};
/**
* findUpperDiv
* find recursively previousSibling in legend list
* @private 
* @author Lorenzo Becchi
*/
kaLegend.prototype.findUpperDiv = function(div){
	var uDiv = div.previousSibling;
	if(uDiv && uDiv.className=='kaLegendLayer' && uDiv.style.display=='none'){
		this.findUpperDiv(uDiv);
	}
	return uDiv;
};

