
/* *************************************************
FILENAME:     agsTOC.js
AUTHOR:       André von Wartburg
CREATED:      20. 07. 2010
COPYRIGHT:    rawi-geo. Alle Rechte vorbehalten.
DESCRIPTION:	Table-Of-Contents (TOC) functionality
 
TODO: 
- restrictions: cross service groups?
- include LOD-dependency, visibility override
- Dependecy w/ Identify: Id only when layer is on (layerStore[currSvc][x].vis = '1')
- shut service out completely when none of layers are visible
- svc has vis layrs but no toc?!?

************************************************** */

// start here	
function initTOC() {
	
	// loop thur all bizSvc to set initial visibilities
	for (x in bizSvc) {
		currSvc = bizSvc[x];
					
		// set map 
		setVisibleLayers(currSvc);
	
		// set checkboxes
		for (x in layerStore[currSvc]) {
			
			// TODO: check if config table is consistent w/ layer.getInfo (only when internalDebug is ON)
			
			if (layerStore[currSvc][x].vis == '1') {
				
				ln = layerStore[currSvc][x].name_ags; // layers name
				lyrIdCombi = currSvc + "-" + ln; 			// DIV layer-id
				lyrChkboxId = lyrIdCombi + "-chkbox"; // FORM chkbox-id
		
				// layer must have checkbox
				if(dojo.byId(lyrChkboxId)) {
			
					pn = dojo.byId(lyrIdCombi).parentNode; // DIV parent-id
		
					// turn all initially visible layers ON
					dojo.toggleClass(lyrChkboxId, "off");
					dojo.toggleClass(lyrChkboxId, "on");
					
					// update group visibilities
					walkupGroupCheck(pn);		
				}
				else {
					if (internalDebug) { console.log("INFO: visible Layer not included in TOC: " + lyrIdCombi ); }
				}
			}
		}
	}
}

// update group visibilities after layer change (2 levels)
function walkupGroupCheck(firstGrp) {
		
	// first level
	doGroupCheck(firstGrp);
		
	// second level 
	if (firstGrp.id != "tocRoot") {
		firstGrpCont = firstGrp.id + "-container";
		secondGrp = dojo.byId(firstGrpCont).parentNode;
		if(secondGrp.id != "tocRoot") { doGroupCheck(secondGrp); }
	}
}

// update group visibilities after layer change
function doGroupCheck(pn) {			
	cntAll = 0; 
	cntVisible = 0;
	
	if (dojo.hasClass(pn, "group_body")) { 
			
		// count all/visible layers in group
		dojo.query(".layer_chkbox", pn)
		.forEach ( function f(x) {
				cntAll++;
				if (dojo.hasClass(x, "on")) { cntVisible++; }
			}
		)

		pnChkbox = pn.id + "-chkbox";
			
		if (dojo.hasClass(pnChkbox, "off")) { dojo.removeClass(pnChkbox, "off"); }
		if (dojo.hasClass(pnChkbox, "tristate")) { dojo.removeClass(pnChkbox, "tristate"); } 
		if (dojo.hasClass(pnChkbox, "on")) { dojo.removeClass(pnChkbox, "on"); }  
			
		if (cntVisible === 0) { newClass = "off"; }
		if ((cntVisible > 0) && (cntVisible < cntAll ) ) { newClass = "tristate"; }
		if ((cntVisible > 0) && (cntVisible == cntAll ) ) { newClass = "on"; }
			
		dojo.addClass(pnChkbox, newClass);
	}
}

// add new group to TOC
function addGroup(grpId, grpName, grpRefNode, grpVisible, grpVirtual ) {
	// write html
	var headerHTML = '';
	
	if (grpVirtual) {
		headerHTML += '<img class="expander" id="' + grpId + '-show" src="http://www.geo.lu.ch/src/img/toc_trans.gif" style="width: 2px; margin: 0;" alt="" />';
	}
	else {
		headerHTML += '<img class="expander" id="' + grpId + '-show"';
		if (grpVisible) { headerHTML += 'src="http://www.geo.lu.ch/src/img/toc_close.gif"'; }
		else { headerHTML += 'src="http://www.geo.lu.ch/src/img/toc_expand.gif"'; }
		headerHTML += 'alt="" onclick="showGroup(\'' + grpId + '\')" />';
	}
	
	headerHTML += '<img class="chkbox" id="' + grpId + '-chkbox" src="http://www.geo.lu.ch/src/img/toc_trans.gif" onclick="toggleGroup(\'' + grpId + '\');" alt="ein- / ausblenden" />' + grpName ;
	
	// create DOM structure
	var grp_container = dojo.create("div", { id: grpId + "-container" }, grpRefNode, "last");
	var grp_header = 	dojo.create("div", { innerHTML: headerHTML, id: grpId + "-head" }, 	grpId + "-container", "first" );
	var grp_body =  	dojo.create("div", { 												id: grpId }, 						grpId + "-container", "last");
	
	dojo.addClass(grpId + "-head", "group_header");
	dojo.addClass(grpId, "group_body");
	dojo.addClass(grpId + "-chkbox", "group_chkbox");
	dojo.addClass(grpId + "-chkbox", "off");
	
	// set default group expandedness
	if (grpVisible) { dojo.byId(grpId).style.display = "block"; }
	else { dojo.byId(grpId).style.display = "none"; } 
		
}

// add new layer to TOC
function addLayer( lyrService, lyrId, lyrName, lyrNameSDE, lyrNode, lyrMeta, lyrIdentify ) {
	var layerHTML = "";
	combiId = lyrService + "-" + lyrId;
	if (lyrNameSDE != "NONE") layerHTML += '<div class="lyrfuncs"><a href="http://www.geo.lu.ch/meta/?fc=' + lyrNameSDE + '" target="_new"><img src="http://www.geo.lu.ch/src/img/toc_info_off.gif" alt="Info anzeigen" /></a></div>';
	layerHTML += '<div class="layer" ><img class="chkbox" id="' + combiId +'-chkbox" src="http://www.geo.lu.ch/src/img/toc_trans.gif" onclick="toggleLayer(this);" alt="ein- / ausblenden" />' + lyrName + '</div>';

	var lyr = dojo.create("div", { innerHTML: layerHTML, id: combiId }, lyrNode , "last" );
	dojo.addClass(combiId, "layer");
	dojo.addClass(combiId + "-chkbox", "layer_chkbox");
	dojo.addClass(combiId + "-chkbox", "off");	// layer is always off by default upon init
}

// expand/collapse group in TOC
function showGroup(grpId) { 
	if (dojo.byId(grpId).style.display == "none") { 
		dojo.byId(grpId).style.display = "block";
		dojo.byId(grpId + "-show").src = "http://www.geo.lu.ch/src/img/toc_close.gif"; 
		}
	else { 
		dojo.byId(grpId).style.display = "none";  
		dojo.byId(grpId + "-show").src = "http://www.geo.lu.ch/src/img/toc_expand.gif"; 
	}
}

// show/hide layer on map
function toggleLayer(lyrChkboxId) { 
	
	// POLISH: should be done w/ lyrDivId rather than lyrChkboxId...
	// split id to get service and id 
	tmpCId = lyrChkboxId.id;
	arrCId = tmpCId.split('-');
	serviceName = arrCId[0];
	lyrName = arrCId[1];
	lyrNo = null;
		
	// get layer's number
	for (x in layerStore[serviceName]){
		if (layerStore[serviceName][x].name_ags == lyrName) lyrNo = x;
	}
		
	// REMOVE after db/svc check has been established
	if (lyrNo == null) { 
		console.log("ERROR: toc layer '" + lyrName + "' does no exist in svc '" + serviceName + "'"); 
	}
	else {
		// update store	
		if (layerStore[serviceName][lyrNo].vis == '1') { layerStore[serviceName][lyrNo].vis = '0'; }
		else { layerStore[serviceName][lyrNo].vis = '1'; }
	}
	// toggle checkbox
	dojo.toggleClass(lyrChkboxId, "off");
	dojo.toggleClass(lyrChkboxId, "on");
	
	// update map
	setVisibleLayers(serviceName);
	
	// check groups
	pn = dojo.byId(serviceName + "-" + lyrName).parentNode;
	walkupGroupCheck(pn);
}

// show/hide group on map
function toggleGroup(grpId) { 
	//hide/show all contained layers/groups
	cntLyrTotal = 0; 
	cntLyrVis = 0;
	involvedSvc = [];
	
	// get all containing layers and check if ALL/SOME/NONE of the layers are ON
	dojo.query(".layer_chkbox", grpId)
	.forEach (
		function f(x) {
			cntLyrTotal++;
			if (dojo.hasClass(x, "on")) { cntLyrVis++; }
		}
	)
	
	if (internalDebug) {	console.log("STATUS: toggled group " + grpId + " contains " + cntLyrTotal + " layers. (" + cntLyrVis + " visible)"); }
	
	if (cntLyrTotal != 0) {
		
		// ALL layers in group are ON
		if (cntLyrVis == cntLyrTotal) { 
			
			// loop thru layers and remove them from their service-arrays
			dojo.query(".layer_chkbox", grpId)
			.forEach (
				function f(x) {
					
					// split 'em
					tmpLyrId = x.id;
					arrLyrId = tmpLyrId.split('-');
					serviceName = arrLyrId[0];
					lyrName = arrLyrId[1];
					
					for (x in layerStore[serviceName]){
						if (layerStore[serviceName][x].name_ags == lyrName) lyrNo = x;
					}
					
					// update store
					layerStore[serviceName][lyrNo].vis = '0';
										
					// remember the service
					isInvolved = dojo.indexOf(involvedSvc, serviceName );
					if (isInvolved == -1) { involvedSvc.push(serviceName);  } 
					
					// toggle OFF layers
					dojo.toggleClass(tmpLyrId , "on");
					dojo.toggleClass(tmpLyrId , "off");
				}
			)
			
			// toggle OFF this group
			dojo.toggleClass(grpId + "-chkbox", "on");
			dojo.toggleClass(grpId + "-chkbox", "off");
					
			// toggle OFF containing groups
			dojo.query(".group_chkbox", grpId)
			.forEach (
				function f(x) {
					dojo.toggleClass(x.id  , "on");
					dojo.toggleClass(x.id  , "off");
				}
			)	
		}
		
		// SOME or NONE of the layers in group are ON
		else { 

			// loop thru all layers and add them to their service-arrays (if not yet present)
			dojo.query(".layer_chkbox", grpId)
			.forEach (
				function f(x) {
					
					// split 'em
					lyrChkboxId = x.id;
					arrLyrId = lyrChkboxId.split('-');
					serviceName = arrLyrId[0];
					lyrName = arrLyrId[1];
					
					if (dojo.hasClass(lyrChkboxId, "off")) {
												
						for (x in layerStore[serviceName]){
							if (layerStore[serviceName][x].name_ags == lyrName) lyrNo = x;
						}
						
						// update store
						layerStore[serviceName][lyrNo].vis = '1';
						
						// toggle ON layers
						dojo.toggleClass(lyrChkboxId, "off");
						dojo.toggleClass(lyrChkboxId, "on");	 
					}
					
					// remember the service
					isInvolved = dojo.indexOf(involvedSvc, serviceName );
					if (isInvolved == -1) { involvedSvc.push(serviceName);  } 
										
				}
			)
			
			// toggle ON this group (it's off or tristate now)
			if (dojo.hasClass(grpId + "-chkbox", "off")) { dojo.removeClass(grpId + "-chkbox", "off"); }
			if (dojo.hasClass(grpId + "-chkbox", "tristate")) { dojo.removeClass(grpId + "-chkbox", "tristate"); } 
			dojo.toggleClass(grpId + "-chkbox", "on");
			
			// toggle ON containing groups
			dojo.query(".group_chkbox", grpId)
			.forEach (
				function f(x) {					
					if (dojo.hasClass(x.id , "off")) { dojo.removeClass(x.id , "off"); dojo.toggleClass(x.id , "on"); }
					if (dojo.hasClass(x.id , "tristate")) { dojo.removeClass(x.id , "tristate"); dojo.toggleClass(x.id , "on"); } 
				}
			)
		}
		
		// update involved services
		for (var i = 0;i<involvedSvc.length;i++) {
			setVisibleLayers(involvedSvc[i]);
		}
	}
	
	// check toggeled groups parent
	pnContainerid = grpId + "-container";
	pnCandidate = dojo.byId(pnContainerid).parentNode;
	if(pnCandidate.id != "tocRoot") { doGroupCheck(pnCandidate); }
}

// helper func: update map
function setVisibleLayers(serviceName){
		
	// look up visible layer in store
	tmpVis = [];
	for (x in layerStore[serviceName]){
		if (layerStore[serviceName][x].vis == '1') tmpVis.push(x);
	}
	
	// to display no layers set -1. 
	if(tmpVis.length === 0){
  	tmpVis.push(-1);
	}

	var layer = map.getLayer(serviceName);
	// console.log(tmpVis);
	layer.setVisibleLayers(tmpVis);
}

// markup non-visible layers in TOC
function setOutOfRangeVis(scale) {
	// get all containing layers and check if ALL/SOME/NONE of the layers are ON
	dojo.query(".layer_chkbox", "tocRoot")
	.forEach (
		function f(x) {
			tmpCId = x.id;
			arrCId = tmpCId.split('-');
			svcName = arrCId[0];
			lyrName = arrCId[1];
			lyrId = svcName + "-" + lyrName;
			lyrNo = null;
			visMin = null;
			visMax = null;
		
			// get layer's number
			for (x in layerStore[svcName]){
				if (layerStore[svcName][x].name_ags == lyrName) { 
					lyrNo = x;  
					visMin = layerStore[svcName][x].vis_min;
					visMax = layerStore[svcName][x].vis_max;
					if ((scale > visMin) || (scale < visMax)) {
						//console.log("TOC-Update: NOT VISIBLE " + lyrId + "(id:" + lyrNo + ",visMin:" + visMin  + " ,visMax:" + visMax + ")");
						if (!(dojo.hasClass(lyrId , "outofrange"))) { dojo.toggleClass(lyrId , "outofrange"); }
					}
					else {
						// remove outofrange class
						if (dojo.hasClass(lyrId , "outofrange")) { dojo.removeClass(lyrId , "outofrange"); }
							//console.log("TOC-Update: VISIBLE " + lyrId + "(id:" + lyrNo + ",visMin:" + visMin  + " ,visMax:" + visMax + ")");
						}
					}
				}
			//console.log("TOC-Update: " + tmpCId + "(id:" + lyrNo + ",visMin:" + visMin  + " ,visMax:" + visMax + ")");
		}
	)
	
	// update groups
	dojo.query(".group_chkbox", "tocRoot")
	.forEach (
		function f(x) {
			tmpGrpId = x.id;
			arrGrpId = tmpGrpId.split('-');
			grpName = arrGrpId[0];
			grpHead = grpName + "-head";
			cntLyrTot = 0;
			cntOutOfRange = 0;
			dojo.query(".layer_chkbox", grpName).forEach ( function f(x) { cntLyrTot++; } )
			dojo.query(".layer.outofrange", grpName).forEach ( function f(x) { cntOutOfRange++; } )
			//console.log(grpName + "(" + cntOutOfRange + "," + cntLyrTot + ")" );
			if(cntOutOfRange == cntLyrTot) {  if (!(dojo.hasClass(grpHead , "outofrange"))) { dojo.toggleClass(grpHead , "outofrange"); } }
			else {if (dojo.hasClass(grpHead , "outofrange")) { dojo.removeClass(grpHead , "outofrange"); }}
		}
	)
}
		

