
/*
 * @version Id: wizardEngine.js 08/mar/07
 * @package Parcelle
 * @copyright Copyright (C) 2007 Andrea Bizzotto - Tecnobit S.R.L. All rights reserved.
 * @license 
 * Created on 08/mar/07
 */

// some functions here are directly or transitive depending on insertSection() and updateSection()
// in treeEvents.js and listEvents.js

// refer to wizardEvents.js for global vars used in these scripts

/*
 * this function is called by endWizard(endOption) and updates all the attributes in the xml structure:
 *    <controls>
 * 	     <attribute id="attribute 1 id" type="attribute 1 type" value="attribute 1 value" />
 *       ....
 *    </controls>
 * setting the "value" attribute
 */ 
function updateSectionXML() {
	var controlValue = '';
	var doc = createDomParser(lastSectionControlsXML);	
	if (doc == null)
		return;
	var root = doc.getDocumentElement();
	
	var i, xmlChilds = root.getChildNodes();
	for (i = 0; i < xmlChilds.getLength(); i++) {
		var item = xmlChilds.item(i);
		var attributes = item.getAttributes();
		var controlId = '' + attributes.getNamedItem(TAG_CONTROL_ID).getNodeValue();		
		var controlType = '' + attributes.getNamedItem(TAG_CONTROL_TYPE).getNodeValue();				
		
		var control = $(controlId);
		switch (controlType) {
			case TAG_CONTROL_TYPE_SELECT:
				if (control.selectedIndex >= 0 && control.options.length > 0)
					attributes.getNamedItem(TAG_CONTROL_VALUE).setNodeValue(control.options[control.selectedIndex].value);
				else
					attributes.getNamedItem(TAG_CONTROL_VALUE).setNodeValue('');
				break;
			case TAG_CONTROL_TYPE_EDIT:
				controlValue = control.value;
				if (controlValue != null){
					controlValue = controlValue.replace(/'/g, "&#39;");
					// '
					controlValue = controlValue.replace(/"/g, "&#34;");
					// '
				}
				attributes.getNamedItem(TAG_CONTROL_VALUE).setNodeValue(controlValue);
				break;
			case TAG_CONTROL_TYPE_CHECKBOX:
				attributes.getNamedItem(TAG_CONTROL_VALUE).setNodeValue(control.checked ? "Y" : "N");
				break;
			case TAG_CONTROL_TYPE_RADIO:
				attributes.getNamedItem(TAG_CONTROL_VALUE).setNodeValue(control.checked ? "Y" : "N");
				break;
		}
	}
	lastSectionControlsXML = doc.getXML();
}

// function called when the user clicks on the finish button of the wizard
function endWizard(endOption, isDemo) {
	setCursor("wait");
	demoMode = isDemo;
	
	updateSectionXML();
	if (endOption == "newSection")
		evaluateNewSection();
	else if (endOption == "modSection")
		evaluateModifiedSection();
	else if (endOption == "adaptSection")
		evaluateAdaptSection();
}

function display(id) {
    
	//if (id == 'div256')
	//	alert('display 256');
	
	$(id).style.visibility = 'visible';
	$(id).style.display = 'block';
}

function hide(id) {

	//if (id == 'div256')
	//	alert('hide 256');

	$(id).style.visibility = 'hidden';
	$(id).style.display = 'none';
}

function toggleEnable(id) {

	$(id).disabled = !$(id).disabled;
}
function enable(id) {

	$(id).disabled = false;
}
function disable(id) {

	$(id).disabled = true;
}

function check(id) {

	$(id).checked = true;
}
function uncheck(id) {

	$(id).checked = false;
}

function lockEnable(ids) { 
    /*var status = "lockEnable - back: ";
    status += document.getElementById("back").disabled ? "N" : "Y";
    status += " forward: ";
    status += document.getElementById("forward").disabled ? "N" : "Y";
    alert(status); */

    //if(ids == null) 
    //alert(ids);

    ids = "back-forward";
	var id = ids.split("-");
    
    /*if(id != "back,forward") 
    {
        ids = "back-forward";
        id = ids.split("-");          
    }    */

	//wizardButtonsState = "";
	var i;
	for (i = 0; i < id.length; i++) {
		var button = $(id[i]);//document.getElementById(id[i]);//
		if (button != null) {
			//wizardButtonsState += button.disabled ? "N" : "Y";
            //alert('buttons ' + wizardButtonsState);
			button.disabled = true;
		}
		else
        {
            //alert("ddd");
			wizardButtonsState = "X";
        }
		//if (i < id.length - 1)
		//	wizardButtonsState += "-";
	}
    
    /*status = "lockEnable FINE - back: ";
    status += document.getElementById("back").disabled ? "N" : "Y";
    status += " forward: ";
    status += document.getElementById("forward").disabled ? "N" : "Y";
    alert(status); */   
}

function lockDisable(ids) {
    //var status = "lockDisable - back: ";
    //status += document.getElementById("back").disabled ? "N" : "Y";
    //status += " forward: ";
    //status += document.getElementById("forward").disabled ? "N" : "Y";
    //alert(status); 

	
    //if(ids == null)   
    //alert(ids);
    ids = 'back-forward';
	var id = ids.split("-");
   
    //alert(wizardButtonsState);
    var i;

    if(wizardButtonsState == "")
    {
        for (i = 0; i < id.length; i++)  
        {
            var button = document.getElementById(id[i]);//$(id[i]);
            if (button != null)    
            {
                 wizardButtonsState += button.disabled ? "N" : "Y";                           
            }
             if (i < id.length - 1)
                  wizardButtonsState += "-";             
        }        
    }
    
    var buttonsState = wizardButtonsState.split("-");
    
    //alert(wizardButtonsState);    
    
	for (i = 0; i < id.length; i++) {
		var button = document.getElementById(id[i]);//$(id[i]);
		if (button != null)
        {         
			button.disabled = buttonsState[i] == "N" ? true : false;
        }
	}
    
    //status = "lockDisable FINE - back: ";
    //status += document.getElementById("back").disabled ? "N" : "Y";
    //status += " forward: ";
    //status += document.getElementById("forward").disabled ? "N" : "Y";
    //alert(status);    
}

// handling of numeric editbox onchange to prevent non-valid chars to be inserted and out-of-bounds error
function editboxChange(controlId, isInteger, range, sign, action) {
	
	var control = $(controlId);
	var bound = range.split("-");

	var str = control.value;
	var i, len = str.length;
	var testBound;
	var showEditError;
	//
	if (control != null && control.title == "dontShowRangeError"){
		showEditError = false;
		control.title = "";
	}
	else
		showEditError = true;
		
	//For negative number change the value
	for (i = 0; i < bound.length; i++)  {
		bound[i] = bound[i].replace("N","-");
	}
	
	if (isInteger) {
		for (i = 0; i < len; i++) {
			if (str.charAt(i) < '0' || str.charAt(i) > '9') {
				if (sign != "Y" || str.charAt(i) != "-" || i > 0) {
					if (showEditError)
						alert("formato non valido: sono ammessi solo valori interi");
					control.value = bound[0];
					return;
				}
			}
  		}
	}
	else {
		var comma = 0, point = 0;
		for (i = 0; i < len; i++) {
			
			if ((i == 0 || i == len - 1) && (str.charAt(i) == ',' || str.charAt(i) == '.')) {
				if (sign != "Y" || str.charAt(i) != "-" || i > 0) {
					if (showEditError)
						alert("formato non valido");
					control.value = bound[0];
					return;
				}
			}
			if (str.charAt(i) == ',')
				comma++;
			if (str.charAt(i) == '.')
				point++;
			if (comma > 1 || point > 1 || comma == 1 && point == 1) {
				if (sign != "Y" || str.charAt(i) != "-" || i > 0) {
					if (showEditError)
						alert("formato non valido");
					control.value = bound[0];
					return;
				}
			}
			if (str.charAt(i) != ',' && str.charAt(i) != '.' && (str.charAt(i) < '0' || str.charAt(i) > '9')) {
				if (sign != "Y" || str.charAt(i) != "-" || i > 0) {
					if (showEditError)
						alert("formato non valido");
					control.value = bound[0];
					return;
				}
			}
		}
	}
	var strValue = control.value.replace(",", ".");
	var value = parseFloat(strValue);
	var fLowBound, fUpBound;
	
	fLowBound = bound[0].replace(",", ".");
	fLowBound = fLowBound.replace(",", ".");
	fLowBound = parseFloat(fLowBound);

	fUpBound = bound[1].replace(",", ".");
	fUpBound = fUpBound.replace(",", ".");
	fUpBound = parseFloat(fUpBound);	
	
	// allow negative values
	//if (sign == "Y")
	//	value = Math.abs(value);
	if (value < (fLowBound) || value > (fUpBound)) {	
		if (showEditError)
			alert("Inserire un valore compreso tra " + bound[0] + " e " + bound[1]);
		control.value = value < fLowBound ? bound[0] : bound[1];
		return;
	}
	//if is correct value
	if (action != '')
		doEditBoxAction(action);	
}
 
//
// this function get the action for an editbox and do a specific action 
//
function doEditBoxAction(action){
	var mutex, to;
	var i, j;
	
	// first split into commands
	var actions = action.split(";");
	for (i = 0; i < actions.length; i++) {
		mutex = to = '';
		
		var parts = actions[i].split(" ");
		for (j = 0; j < parts.length; j++) {
		
			var tokens = parts[j].split("=");
			if (tokens.length != 2) {
				alert('wizardEvents.js::doEditBoxAction('+ action +') ERROR: wrong handler format');
				return;
			}

			if (tokens[0] == TAG_CONTROL_MUTEX)
				mutex = tokens[1];
			if (tokens[0] == TAG_CONTROL_TO)
				to = tokens[1];
				
		}
		if (mutex != "" && to != "")
			mutexControl("", "", mutex,to, "");
	}		
}

/* 
 * this function fills the option array of a select control with the xml returned by the ajax call
 * param.responseText structure:
 * <select id="id_dest">
 *    <option id="id_option">text</option>
 *    ....
 * </select>
 */
function setComboboxOptions(param) {
	//alert(param.responseText);
	
	var doc = createDomParser(param.responseText);
	if (doc == null)
		return;
	var root = doc.getDocumentElement();

	dumpString(param.responseText, 1);
	
	var item = root;

	// retireving destination combobox
	var attributes = item.getAttributes();
	var destId = '' + attributes.getNamedItem("id").getNodeValue();

	//alert(item.getXML());
	// ---------------------- access to pending operations XML to update values -------------------------
	//alert(pendingOperations);
	var pendingValue = '';
	var operationsDoc = createDomParser(pendingOperations);
	if (operationsDoc == null) {
		return;
	}
	var operationsRoot = operationsDoc.getDocumentElement();

	var operations = operationsRoot.getChildNodes();
	for (i = 0; i < operations.getLength(); i++) {
	
		attributes = operations.item(i).getAttributes();
		if (attributes.getNamedItem("id").getNodeValue() == destId) {
		
			pendingValue = attributes.getNamedItem("value").getNodeValue();
			operationsRoot.removeChild(operations.item(i));
			//alert(operationsRoot.getXML());
		}
	}
	pendingOperations = operationsRoot.getXML();
	// ----------------------------------------------------------------------------------------------------
		
	// empty combobox
	var control = $(destId);
	control.options.length = 0;
	
	// fill with new values
	var xmlChilds = item.getChildNodes();
	for (i = 0; i < xmlChilds.getLength(); i++) {
		
		var optionId = '' + xmlChilds.item(i).getAttributes().getNamedItem("id").getNodeValue();
		var optionValue = '' + xmlChilds.item(i).getFirstChild().getNodeValue();

		control.options[i] = new Option(optionValue, optionId);
		if (optionId == pendingValue)
			control.selectedIndex = i;
	}
	fireChangeEvent(control);
}



// this function requests the new xml content to refresh the combobox indexed by destId
// destId can be a list of controls on the form: x-y-...-z	
function refreshCombobox(uses, srcId, destId) {

	//alert("uses="+uses+";src="+srcId+";dest="+destId);
	
	var selection = '';
	if (uses != "") {
		var i, use = uses.split("-");
		for (i = 0; i < use.length; i++) {		
			var control = $(use[i]);
			selection = selection + control.options[control.selectedIndex].value + "-";
		}		
	}

	var src = $(srcId);
	var id;
	//CPERON
	if (src.selectedIndex > -1 && src.selectedIndex < src.length) {
		id = src.options[src.selectedIndex].value;
		selection = selection + id;
		
		var pars = 'action=comboboxChange&itemId=' + lastSectionItem + '&selection=' + selection + '&destId=' + destId;
		//CPERON
		new Ajax.Request("wizardCallback.php", {
			method: 'get',
			parameters: pars,
			onFailure: reportError,
			onComplete: setComboboxOptions
		});
	}
}

// this code handles 'forward' button text, that has to be changed if the last active page is set by a select
// control
function updateForwardButtonPrompt() {

	var doc = createDomParser(lastSectionFormsXML);	
	if (doc == null)
		return;
	var root = doc.getDocumentElement();

	if (wizardPage == '') {
		// if it is the first time that user presses a button button, load first page id
		// wizard has at least one page so this is correct
		wizardPage = '' + root.getChildNodes().item(0).getAttributes().getNamedItem("id").getNodeValue();
	}

	$('forward').value = isLast(root, wizardPage) ? "Fine" : "avanti";
}

function updateSelector(srcId, selector) {

	// selector: "optId&dstId&rule-optId&dstId&rule-optId&dstId&rule..."
	//alert(srcId + ": " + selector);
	updateForwardButtonPrompt();
	
	var src = $(srcId);
	var id = src.options[src.selectedIndex].value;
	// relations: "optId&dstId&rule"
	var i, relations = selector.split("-");
	for (i = 0; i < relations.length; i++) {
	
		var values = relations[i].split("&");
		//alert(relations[i] + " " + values.length);
		if (id == values[0] && values[1] == TAG_FORM_DYN_RULE_ALLOW || 
			id != values[0] && values[1] == TAG_FORM_DYN_RULE_BLOCK)
			display("div" + values[2]);
		else
			hide("div" + values[2]);
	}
}

/*
	this function handle a generic mutex event.
	destId, is the control to mutex.
	to rapresent a trivial formula used to update value of destination control
*/
function mutexControl(srcId, srcType, destId, to, when) {
	try{					
		var srcControl;	
		var control = $(destId);	
		
		if (srcId != "")
			srcControl = $(srcId);
			
		if (control != null){
			if (control.tagName == "SELECT"){				
				try{					
					var controlToCopy = $(to);
					if (controlToCopy != null){
						//during initWizard prevent mutex action
						if (controlToCopy.title != "notMutex"){
							if (controlToCopy.selectedIndex > -1 && control.selectedIndex != controlToCopy.selectedIndex){
								if (controlToCopy.selectedIndex < control.options.length){
									//copy master value
									control.selectedIndex = controlToCopy.selectedIndex;
									//performe a change event to change slave control
									fireChangeEvent(control);
								}
							}
						}
						else
						{
							//set title to "" otherwise mutex action doesn't perform.
							controlToCopy.title = "";
						}
					}
				}
				catch (e){
					alert("Mutex Control SELECT Error:\tdest:\t" + destId + "\tformula:\t" + to);
				}
			}
			else {
					if (srcType == TAG_CONTROL_TYPE_CHECKBOX){
						try{
							if (srcControl.checked && when == TAG_FORM_DYN_RULE_CHECK || !srcControl.checked && when == TAG_FORM_DYN_RULE_UNCHECK){
								if (srcControl.title != "notMutex"){
									var value = getValueFromFormula(to);
									control.value = value;
									control.title = "dontShowRangeError";
									fireChangeEvent(control);
								}
							}
						}
						catch(e){
							alert("Mutex Control Error:" + TAG_CONTROL_TYPE_CHECKBOX + "\n" + e);
						}										
					}					
					else
						if (srcType == TAG_CONTROL_TYPE_RADIO){
							try{
								if (srcControl.title != "notMutex"){
									if ($(to).checked)
										control.checked = true;
									else
										control.checked = false;
									fireChangeEvent(control);
								}
							}
							catch(e){
								alert("Mutex Control Error:" + TAG_CONTROL_TYPE_CHECKBOX + "\n" + e);
							}										
						}					
						else				
						{					
							try{
								//var value = getValueFromFormula(to);
								var value = selectCallFunction(to);
								control.value = value;
								control.title = "dontShowRangeError";
								fireChangeEvent(control);
							}
							catch(e){
								alert("Mutex Control Error:\tformula:\t" + to + "\n" + e);
							}
						}
			}
		}
	}
	catch(e){
		alert("Error in mutex control\n" + e);
	}
}

function getValueFromFormula(formula){	
	var value = -1;
	if (formula != null){
		if (formula != ""){
			try{
				value = calculateValueFromFormula(formula, '-');
				if (value == -1)
					value = calculateValueFromFormula(formula, '+');
				if (value == -1)
					value = calculateValueFromFormula(formula, '/');
				if (value == -1)
					value = calculateValueFromFormula(formula, '*');
				if (value == -1)
					value = $(formula).value;
			}
			catch(e){
				value = -1;
				alert("getValueFromFormula:\tformula:\t" + formula + "\n" + e);
			}
		}			
	}
	return value;
}

function calculateValueFromFormula(formula, operation){
	var value = -1;
	var array;
	//
	index = formula.indexOf(operation);
	//
	if (index > 0){
		array = formula.split(operation);
		if (array != null)
			if (array.length > 1){
				
				switch(operation) {
					case '-':
						value = $(array[0]).value - $(array[1]).value;
						break;
					case '+':
						value = $(array[0]).value + $(array[1]).value;
						break;
					case '*':
						value = $(array[0]).value * $(array[1]).value;
						break;
					case '/':
						value = $(array[0]).value / $(array[1]).value;
						break;					
					default:
						break;					
				}				
			}
	}
	return value;
}

// this function handles two checkboxes firing events each one to the other, preventing loops
// this code uses some tricks to do the job. Don't change it before asking me
function updateMutexCheckbox(srcId, destId, set, when) {

	//alert("src=" + srcId + ";dest=" + destId + ";set=" + set + ";when=" + when + ";state=" + mutexCheckboxState);
	if (mutexCheckboxState == 0) {
	
		src = $(srcId);
		dest = $(destId);
		
		if (when == TAG_FORM_DYN_RULE_CLICK) {
		
			// positive logic
			if (set == TAG_FORM_DYN_RULE_CHECK) {
				if (dest.checked != src.checked) {
					// make equal
					mutexCheckboxState = 1;
					fireCheckboxEvent(dest, src.checked);
				}
	
			}
			// negative logic
			else {
				if (dest.checked == src.checked) {
				
					// make not equal
					mutexCheckboxState = 1;
					fireCheckboxEvent(dest, !src.checked);
				}
			}
		}
		else if (src.checked && when == TAG_FORM_DYN_RULE_CHECK ||
			    !src.checked && when == TAG_FORM_DYN_RULE_UNCHECK) {
			
			if (set == TAG_FORM_DYN_RULE_CHECK && !dest.checked)
			
				fireCheckboxEvent(dest, true);
			
			else if (set == TAG_FORM_DYN_RULE_UNCHECK && dest.checked)
			
				fireCheckboxEvent(dest, false);
		}
	}
	else
		mutexCheckboxState = 0;
}

// this function handles interaction between controls
function updateControlsState(srcType, srcId, matchValue, commands, rule) {

	// alert("type="+srcType+";id="+srcId+";matchValue="+matchValue+";commands="+commands+";rule="+rule);	
	var src = $(srcId);
	if (srcType == TAG_CONTROL_TYPE_SELECT) {

		updateForwardButtonPrompt();
				
		//11001: <attribute id="103" name="Esecuzione dell'opera" type="select" commands="300" rule="block" match="1">
		if (rule == TAG_FORM_DYN_RULE_ALLOW || rule == TAG_FORM_DYN_RULE_BLOCK) {
			var index = src.selectedIndex;
			if (src.options.length > index  && index > -1)
			{			
				var id = src.options[index].value;
				var i, control = commands.split("-");
				var matches = matchValue.split("-");
				if (control != null)
					for (i = 0; i < control.length; i++) {
						for (j = 0; j < matches.length; j++) {
							if (id == matches[j] && rule == TAG_FORM_DYN_RULE_ALLOW || id != matches[j] && rule == TAG_FORM_DYN_RULE_BLOCK)
								display("div" + control[i]);
							else
								hide("div" + control[i]);
						}
					}
			}
		}
		else if (rule == TAG_FORM_DYN_RULE_CHECK || rule == TAG_FORM_DYN_RULE_UNCHECK) {
		
			var id = src.options[src.selectedIndex].value;
			var i, control = commands.split("-");
			for (i = 0; i < control.length; i++) {
			
				if (!$(control[i]).checked && (id == matchValue))
					fireCheckboxEvent($(control[i]), true);

				if (initWizardDone)
					if ($(control[i]).checked && (id != matchValue))
						fireCheckboxEvent($(control[i]), false);

				//if ($(control[i]).checked != (id == matchValue))
				//	fireCheckboxEvent($(control[i]), id == matchValue);
			}
		}
		else if (rule == TAG_FORM_DYN_RULE_SHOW || rule == TAG_FORM_DYN_RULE_HIDE) {
				var index = src.selectedIndex;
				if (src.options.length > index  && index > -1)
				{			
					var id = src.options[index].value;
					var i, control = commands.split("-");
					var matches = matchValue.split("-");
					if (control != null)
						for (i = 0; i < control.length; i++) {
							for (j = 0; j < matches.length; j++) {
								if (id == matches[j])
								 if (rule == TAG_FORM_DYN_RULE_SHOW)
									display("div" + control[i]);
								else if (rule == TAG_FORM_DYN_RULE_HIDE)
									hide("div" + control[i]);
							}
						}
				}				
			}
		else if (rule == TAG_FORM_DYN_RULE_ENABLE || rule == TAG_FORM_DYN_RULE_DISABLE){
			var index = src.selectedIndex;
			if (src.options.length > index  && index > -1){
				var id = src.options[index].value;
				var i, control = commands.split("-");				
				if (id == matchValue && rule == TAG_FORM_DYN_RULE_ENABLE || id != matchValue && rule == TAG_FORM_DYN_RULE_DISABLE)
					for (i = 0; i < control.length; i++)
						enable(control[i]);
				else
					for (i = 0; i < control.length; i++)
						disable(control[i]);
			}			
		}
	}	
	else if (srcType == TAG_CONTROL_TYPE_CHECKBOX) {
	
		updateForwardButtonPrompt();

		var state = src.checked ? "Y" : "N";
		var control = commands.split("-");
		var i;
		
		// 11001: <attribute id="400" name="Aggiornamento prezzi" type="checkbox" default="N" commands="401-402-403" rule="hide" match="N" />
		if (rule == TAG_FORM_DYN_RULE_SHOW || rule == TAG_FORM_DYN_RULE_HIDE) {
			/*
			if (state == matchValue && rule == TAG_FORM_DYN_RULE_SHOW || 
				state != matchValue && rule == TAG_FORM_DYN_RULE_HIDE)
			*/
			if (state == matchValue && rule == TAG_FORM_DYN_RULE_SHOW || 
				state != matchValue && rule == TAG_FORM_DYN_RULE_HIDE)
				for (i = 0; i < control.length; i++)
					display("div" + control[i]);
			else
				for (i = 0; i < control.length; i++)
					hide("div" + control[i]);
		}
		// 11001: <attribute id="206" name="Direzione lavori" type="checkbox" commands="210" set="uncheck" when="check"/>
		else if (rule == TAG_FORM_DYN_RULE_CHECK || rule == TAG_FORM_DYN_RULE_UNCHECK) {
			// this code uses some tricks to do the job. Don't change it before asking me
			if (matchValue == TAG_FORM_DYN_RULE_CLICK) {
				//
				if (rule == TAG_FORM_DYN_RULE_CHECK) {
					for (i = 0; i < control.length; i++) {
						if ($(control[i]).checked != src.checked)
							fireCheckboxEvent($(control[i]), src.checked);
					}
				}
				if (rule == TAG_FORM_DYN_RULE_UNCHECK) {
					for (i = 0; i < control.length; i++) {
						if ($(control[i]).checked == src.checked)
							fireCheckboxEvent($(control[i]), !src.checked);
					}
				}
			}
			else if (src.checked && matchValue == TAG_FORM_DYN_RULE_CHECK ||
			        !src.checked && matchValue == TAG_FORM_DYN_RULE_UNCHECK) {
				
				if (rule == TAG_FORM_DYN_RULE_CHECK) {				
					for (i = 0; i < control.length; i++) {
				 		//if (!$(control[i]).checked || ($(control[i]).checked && $(control[i]).type == "radio"))
				 		if (!$(control[i]).checked)
							fireCheckboxEvent($(control[i]), true);
					}
				}
				else if (rule == TAG_FORM_DYN_RULE_UNCHECK) {				
					for (i = 0; i < control.length; i++) {
				 		if ($(control[i]).checked)
							fireCheckboxEvent($(control[i]), false);
					}
				}
			}		
		}
		// 11001: <attribute id="202" name="Progetto esecutivo" type="checkbox" commands="200-201" rule="enable" match="Y"/>
		else if (rule == TAG_FORM_DYN_RULE_ENABLE || rule == TAG_FORM_DYN_RULE_DISABLE) {
			
			if (state == matchValue && rule == TAG_FORM_DYN_RULE_ENABLE || 
				state != matchValue && rule == TAG_FORM_DYN_RULE_DISABLE)
				for (i = 0; i < control.length; i++)
					enable(control[i]);
			else
				for (i = 0; i < control.length; i++)
					disable(control[i]);
		}
	}
	else if (srcType == TAG_CONTROL_TYPE_RADIO) {
		// 11002: <attribute id="201" type="radio" group="radiogroup2" default="Y" commands="202-204" name="Collaudo nominato all'inizio dell'appalto con obbligo di visite periodiche (art. 19-d)" />	
		var state = src.checked ? "Y" : "N";
		var control = commands.split("-");
		var i;
		for (i = 0; i < control.length; i++) {
			if (rule == TAG_FORM_DYN_RULE_ENABLE || rule == TAG_FORM_DYN_RULE_DISABLE) {
				// the first control is set to a state and the others to the opposite state
				if (i == 0 && rule == TAG_FORM_DYN_RULE_ENABLE || i > 0 && rule == TAG_FORM_DYN_RULE_DISABLE)
					enable(control[i]);
				else
					disable(control[i]);
			}
			else 
			{
				if (rule == TAG_FORM_DYN_RULE_SHOW || rule == TAG_FORM_DYN_RULE_HIDE) {
					/*
					if (state == matchValue && rule == TAG_FORM_DYN_RULE_SHOW || 
						state != matchValue && rule == TAG_FORM_DYN_RULE_HIDE)
					*/
					
					if (state == matchValue && rule == TAG_FORM_DYN_RULE_SHOW ){
						for (i = 0; i < control.length; i++)
							display("div" + control[i]);
					}
					
					if (state == matchValue && rule == TAG_FORM_DYN_RULE_HIDE ){
						for (i = 0; i < control.length; i++)
							hide("div" + control[i]);
					}

					if (state != matchValue && rule == TAG_FORM_DYN_RULE_SHOW){
						for (i = 0; i < control.length; i++)
							hide("div" + control[i]);						
					}

					if (state != matchValue && rule == TAG_FORM_DYN_RULE_HIDE ){
						for (i = 0; i < control.length; i++)
							display("div" + control[i]);
					}
				}
			}								
		}
	}
	//alert(srcId + "[" + id + "=" + matchValue + "] commands " + commands + " with rule " + rule);
}

// action is a string like this : "commands=200-201 rule=enable match=Y;commands=252 rule=hide match=N;commands..."
function updateControls(srcType, srcId, action) {

	var change, mutex, commands, rule, match, set, when, uses, to;
	var i, j, k;
	
	// first split into commands
	var actions = action.split(";");
	for (i = 0; i < actions.length; i++) {
	
		// retrieve commands parts
		// commands='200-201'
		// rule='enable'
		// match='Y'
		change = mutex = commands = rule = match = set = when = uses = to = '';
		
		var parts = actions[i].split(" ");
		for (j = 0; j < parts.length; j++) {
		
			var tokens = parts[j].split("=");
			if (tokens.length != 2) {
				alert('wizardEvents.js::updateControls(' + srcType + ', ' + srcId + ', ' + action + ') ERROR: wrong handler format');
				return;
			}

			if (tokens[0] == TAG_CONTROL_CHANGE)
				change = tokens[1];
			if (tokens[0] == TAG_CONTROL_COMMANDS)
				commands = tokens[1];
			if (tokens[0] == TAG_CONTROL_RULE)
				rule = tokens[1];
			if (tokens[0] == TAG_CONTROL_MATCH)
				match = tokens[1];
			if (tokens[0] == TAG_CONTROL_MUTEX)
				mutex = tokens[1];
			if (tokens[0] == TAG_CONTROL_SET)
				set = tokens[1];
			if (tokens[0] == TAG_CONTROL_WHEN)
				when = tokens[1];
			if (tokens[0] == TAG_CONTROL_USES)
				uses = tokens[1];
			if (tokens[0] == TAG_CONTROL_TO)
				to = tokens[1];
				
		}
		if (change != "") {		
			refreshCombobox(uses, srcId, change);
		}
		if (rule != "" && match != "") {
			updateControlsState(srcType, srcId, match, commands, rule);
		}
		else if (set != "" && when != "") {
			if (mutex != "")
				updateMutexCheckbox(srcId, mutex, set, when);
			else
				updateControlsState(srcType, srcId, when, commands, set);
		}
		//		
		if (mutex != "" && to != ""){
			mutexControl(srcId, srcType, mutex,to, when);			
		}			
	}
}

// FUNCTIONS FOR WIZARD NAVIGATION
 
// checks if the condition exists
function hasGuardCondition(attrs) {
	
	//alert(attrs.getNamedItem(TAG_FORM_DYN_SRCID) + " " + attrs.getNamedItem(TAG_FORM_DYN_RULE));
	
	if (attrs.getNamedItem(TAG_FORM_DYN_SRCID) != null &&
		attrs.getNamedItem(TAG_FORM_DYN_RULE) != null)
		return true;
	return false;
}

// returns true if condition matches
function checkCondition(attributes) {

	var srcControlId = '' + attributes.getNamedItem(TAG_FORM_DYN_SRCID).getNodeValue();	
	var srcControlRule = '' + attributes.getNamedItem(TAG_FORM_DYN_RULE).getNodeValue();
	var control = $(srcControlId);
	
	if (control == null)
		return true;
	// if the page is allowed, return false, else continue iteration

	// page commanded by a select input
	if (attributes.getNamedItem(TAG_FORM_DYN_SRCVALUE) != null) {
	
		var srcControlValue = '' + attributes.getNamedItem(TAG_FORM_DYN_SRCVALUE).getNodeValue();
		if (srcControlValue == control.options[control.selectedIndex].value && srcControlRule == TAG_FORM_DYN_RULE_ALLOW ||
			srcControlValue != control.options[control.selectedIndex].value && srcControlRule == TAG_FORM_DYN_RULE_BLOCK)
			return true;	
	}
	else {	
		// page commanded by a checkbox input
		if (control.checked && srcControlRule == TAG_FORM_DYN_RULE_CHECK ||
		   !control.checked && srcControlRule == TAG_FORM_DYN_RULE_UNCHECK)
		   return true;
	}
	return false;	
}

// a page is the first page if it is the first in the XML or if it is the first page allowed by the conditions
function isFirst(root, page) {

	var i, pages = root.getChildNodes();
	for (i = 0; i < pages.getLength(); i++) {
		// if the current page is the last of the list, return always true
		var pageId = '' + pages.item(i).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
		if (pageId == page)
			return true;
					
		// the page is not the last: check if the last is allowed or not
		var attrs = pages.item(i).getAttributes();
		// if the ith page hasn't a guard condition return false
		if (!hasGuardCondition(attrs))
			return false;

		// the ith page has a guard condition			
		if (checkCondition(attrs))
			return false;
	}
	// this statement should never be reached
	alert('wizardEvents.js::isFirst(' + page + ') ERROR: page not recognized');
	return false;
}

// a page is the last page if it is the last in the XML or if it is the last page allowed by the conditions
function isLast(root, page) {

	var i, pages = root.getChildNodes();
	for (i = pages.getLength() - 1; i >= 0; i--) {
		// if the current page is the last of the list, return always true
		var pageId = '' + pages.item(i).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
		if (pageId == page)
			return true;
					
		// the page is not the last: check if the last is allowed or not
		var attrs = pages.item(i).getAttributes();
		// if the ith page hasn't a guard condition return false
		if (!hasGuardCondition(attrs))
			return false;

		// the ith page has a guard condition
		if (checkCondition(attrs))
			return false;
	}
	// this statement should never be reached
	alert('wizardEvents.js::isLast(' + page + ') ERROR: page not recognized');
	return false;
}

// this function returns the previous valid page or false if there no exists one
function prevPage(root, page) {

	var i, pages = root.getChildNodes();
	// set i to current page
	for (i = 0; i < pages.getLength(); i++) {
		
		var pageId = '' + pages.item(i).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
		if (pageId == page)
			break;
	}
		
	if (i == 0) {
		//alert('wizardEvents.js::prevPage(' + page + ') ERROR: page not recognized');
		return false;
	}
	// find first acceptable page
	while (true) {
		// i points to the current page so it is possible to query the successor pages if i = n - 1
		if (i > 0) {
		
			var attrs = pages.item(i - 1).getAttributes();
			// if form is free, take that to be the next page
			if (!hasGuardCondition(attrs))
				return '' + pages.item(i - 1).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
			
			// form is not free
			if (checkCondition(attrs)) {
			
				return '' + pages.item(i - 1).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
			}
			else {
				i--;
				continue;
			}
		}
		// there are no pages left
		else {
			alert('wizardEvents.js::prevPage(' + page + ') ERROR: no free pages left');
			return false;
		}
	}
}

// this function returns the next valid page or false if there no exists one
function nextPage(root, page) {

	var i, pages = root.getChildNodes();
	// set i to current page
	for (i = 0; i < pages.getLength(); i++) {
		
		var pageId = '' + pages.item(i).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
		if (pageId == page)
			break;
	}
		
	if (i == pages.getLength()) {
		//alert('wizardEvents.js::nextPage(' + page + ') ERROR: page not recognized');
		return false;
	}
	// find first acceptable page
	while (true) {
		// i points to the current page so it is possible to query the successor pages if i = n - 1
		if (i < pages.getLength() - 1) {
		
			var attrs = pages.item(i + 1).getAttributes();
			// if form is free, take that to be the next page
			if (!hasGuardCondition(attrs))
				return '' + pages.item(i + 1).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
			
			// form is not free
			if (checkCondition(attrs)) {
			
				return '' + pages.item(i + 1).getAttributes().getNamedItem(TAG_FORM_ID).getNodeValue();
			}
			else {
				i++;
				continue;
			}
		}
		// there are no pages left
		else {
			alert('wizardEvents.js::nextPage(' + page + ') ERROR: no free pages left');
			return false;
		}
	}
}

/*
 * This function allows 'back' and 'forward' navigation of the wizard
 * Note: wizardPage is declared in wizardEvents.js
 * The XML structure for the forms is:
 * <forms>
 *    <form id="form 1 id" srcid="source 1 id" srcvalue="source 1 value" [rule="rule"] />
 *    ....
 * </forms>
 */
function navigate(direction, endOption, demo) {

	var doc = createDomParser(lastSectionFormsXML);	
	if (doc == null)
		return;
	var root = doc.getDocumentElement();

	// if it is the first time that user presses a button button, load first page id
	if (wizardPage == '') {
		// wizard has at least one page so this is correct
		wizardPage = '' + root.getChildNodes().item(0).getAttributes().getNamedItem("id").getNodeValue();
        wizardButtonsState = (($('back') == null || $('back').disabled) ? "N" : "Y") + '-' + ($('forward').disabled ? "N" : "Y");    
	}
	if (direction == 'back') {

		var prev = prevPage(root, wizardPage);
		if (prev == false)
			return;
			
		display(prev);
		hide(wizardPage);
		
		// update buttons state
		if (isFirst(root, prev)) {
			$('back').disabled = true;	            
		}
		if (isLast(root, wizardPage)) {
			$('forward').value = "avanti";            
		}        
        
        wizardButtonsState = (($('back') == null || $('back').disabled) ? "N" : "Y") + '-' + ($('forward').disabled ? "N" : "Y");         
        
        //alert(wizardButtonsState);   
		
        wizardPage = prev;                
	}
	else {  // forward
		if (isLast(root, wizardPage)) {	
        	setCursor("wait");
			// empty wizard content
			hide(wizardPage);
			display('WAIT_DIV');			
			wizardPage = '';
			// end the wizard
			endWizard(endOption, demo);
			return;
		}
		// get next page
                
		var next = nextPage(root, wizardPage);
		if (next == false)
			return;

		display(next);
		hide(wizardPage);
        
		// update buttons state
		if (isLast(root, next)) {
			$('forward').value = "Fine";	
            //wizardButtonsState = 'Y-N';		
		}
/*		else {
			$('forward').value = "avanti";	
		}*/
		if (isFirst(root, wizardPage)) {
			$('back').disabled = false;
            //wizardButtonsState = 'Y-Y';
		}

        wizardButtonsState = (($('back') == null || $('back').disabled) ? "N" : "Y") + '-' + ($('forward').disabled ? "N" : "Y");    

		wizardPage = next;               
	}
}

// 
function manageVersionForm(action) {
	switch(action)
	{
		case "cancel":		
				setCursor("wait");				
				hide('page1');
				display('WAIT_DIV');			
				if(useOldStyleWizard)
			        wizard.hide();
			    else
			        wizard.close();
				setCursor("auto");
			break;
		case "proceed":
				setCursor("wait");
				var pars = 'action=listDblClick&sectionId=' + selectedSection + '&proceed=Y';			
				new Ajax.Request(PHP_RESPONSE_FILE, {method: 'get', parameters: pars, onFailure: reportError, onComplete: listCallback});
			break;
	}
	return;
}


//check if the atributes contains mutex clauses.
function checkMutexToAttribute(control){	
	if (control != null){
		for (i = 0; i < control.attributes.length; i++) {
			try{
				if (control.attributes[i].value.search("mutex") != -1){
					if (control.attributes[i].value.search("to=") != -1){
						return true;
					}
				}
			}
			catch(ex){
				alert('checkMutexToAttribute' + ex);
			}
		}
	}
	return false;
}