/***************************************************************
*  Copyright notice
*
*  (c) 2008 Alexander Kellner <alexander.kellner@wunschtacho.de>
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

// global array with all rules
var pmcond_rules = new Array();
var pmcond_rules_ptr = 0;
// inner array ptrs
var pmcond_rules_base_id = 0;
var pmcond_rules_target_id = 1;
var pmcond_rules_value_from_field = 2;
var pmcond_rules_target_function = 3;
var pmcond_rules_target_condition = 4;

// global array with all fieldsets that contain rules with another fieldset as target
var pmcond_fieldsets = new Array();
var pmcond_fieldsets_ptr = 0;
// inner array ptrs
var pmcond_fieldsets_fieldset_id = 0;
var pmcond_fieldsets_base_id = 1;
var pmcond_fieldsets_target_id = 2;

// global array with all fields that contain rules with another field as target
var pmcond_fields = new Array();
var pmcond_fields_ptr = 0;
// inner array ptrs
var pmcond_fields_field_id = 0;
var pmcond_fields_base_id = 1;
var pmcond_fields_target_id = 2;

// add a rule to the array of rules
function pmcond_add(uid, baseID, baseFieldset, targetID, valueFromField, targetFunction, targetCondition){
	var array_uid = uid.split(","); // explode ids of target at ,
	var array_baseID = baseID.split(","); // explode ids of target at ,
	var array_baseFieldset = baseFieldset.split(","); // explode basefieldset at ,
	var array_valueFromField = valueFromField.split(","); // explode value at ,
	var array_targetID = targetID.split(","); // explode ids of target at ,
	var array_targetFunction = targetFunction.split(","); // explode function name at ,
	var array_targetCondition = targetCondition.split(","); // explode conditions at ,

	// check if length of all given variables are the same
	if (array_valueFromField.length != array_targetID.length || array_valueFromField.length != array_baseID.length || array_valueFromField.length != array_targetFunction.length || array_valueFromField.length != array_targetCondition.length || array_valueFromField.length != array_baseFieldset.length) { // If array length is not equal
		alert ('Error in Function ' + functionName + ': Length of array is not equal (' + array_valueFromField.length + '/' + array_targetID.length + '/' + array_baseID.length + '/' + array_targetFunction.length + '/' + array_targetCondition.length + '/' + array_baseFieldset.length + ')!'); // errormessage
		return "err"; // stop function
	}
	// start loop
	for (i=0; i < array_valueFromField.length; i++) { // one loop for every value
		// rules
		pmcond_rules[pmcond_rules_ptr] = new Array(array_baseID[i], array_targetID[i], array_valueFromField[i], array_targetFunction[i], array_targetCondition[i]);
		pmcond_rules_ptr++;

		//if(array_baseID[i] == "uid31"){array_baseFieldset[i] = "powermaildiv_" + array_baseID[i]}

		var targettype = array_targetID[i].substr(0,25);

		if(targettype == "tx-powermail-pi1_fieldset"){
			// fieldsets (fieldset id, rule in the fieldset id, target of the rule)
			pmcond_fieldsets[pmcond_fieldsets_ptr] = new Array(array_baseFieldset[i], array_baseID[i] ,array_targetID[i]);
			pmcond_fieldsets_ptr++;
		} else { // targets a normal field
			// fields (fields id, target of the field)
			pmcond_fields[pmcond_fields_ptr] = new Array("powermaildiv_uid" + array_uid[i],array_baseID[i] ,array_targetID[i]);
			pmcond_fields_ptr++;
		}
	}

	Event.observe(window, 'load', pmcond_init, false);
}

// execute all rules (one by one, no subrules)
function pmcond_init(){
	var rule_index;
	for(var i=0; i < pmcond_rules.length; i++) {
		pmcond_exec_rule(i);
	}
}

// called by the html onchange event
function pmcond_main(baseID) {
	var rule_index_list = pmcond_get_rule_index_list(baseID);

	//alert("first call list: " + rule_index_list + " source: " + baseID);

	for(var i=0; i < rule_index_list.length; i++){
		//alert(" source: " + baseID + " target: " + pmcond_rules[rule_index_list[i]][pmcond_rules_target_id]);
		ret = pmcond_sub(rule_index_list[i], -1, "show", 0);
		if(ret == 0) {return;}
	}
}

// recursive function that will execute rules on or hide all subsequent (to the first rule) fieldsets
function pmcond_sub(rule_index, targetID, act, recCtr){
	// dont lock browser if recursion error would occur (won't happen! :))
	if(recCtr > 100){alert("ERROR: to much recursion, most likely due to a condition loop."); return 0;}

	if(act == "show"){
		// get rule target (fieldset id)
		var targetID = pmcond_rules[rule_index][pmcond_rules_target_id];
		// execute rule
		act = pmcond_exec_rule(rule_index);

	} else {
		// get the fieldset object
		var fs = document.getElementById(targetID);
		// hide the fieldset
		if(fs.visible()){new Effect.Fade(fs, {duration : 0.3 });}
		// set act to hide for all subsequent fieldsets
		act = "hide";
	}
	// also execute rules on subtargets
	var sub_targets = pmcond_get_sub_targets(targetID);
	//alert(targetID);

	for(var i=0; i < sub_targets.length; i++) {
		//alert("act: " + act + " sub target base: " + sub_targets[i][0] + " sub target target: " + sub_targets[i][1]);

		// new rule
		var baseID = sub_targets[i][0];
		// get rule target (fieldset id) (for act hide)
		var targetID = sub_targets[i][1];

		// recursive call
		//alert("exec rule " + rule_index);
		var rule_index = pmcond_get_rule_index(baseID, targetID);
		ret = pmcond_sub(rule_index, targetID, act, recCtr);
		if(ret == 0) {return;}
	}

	return 1;
}

// get the rule index from the baseID and fsID
function pmcond_get_rule_index(baseID, targetID){
	// find index of given baseID
	for(var i=0; i < pmcond_rules.length; i++) {
		if (pmcond_rules[i][pmcond_rules_base_id] == baseID && pmcond_rules[i][pmcond_rules_target_id] == targetID) {
			// found
			return i;
		}
	}
	// not found
	return -1;
}

// get a rule list for given base ID
function pmcond_get_rule_index_list(baseID){
	var ret = Array();
	var ret_ptr = 0;
	// find rules
	for(var i=0; i < pmcond_rules.length; i++) {
		if (pmcond_rules[i][pmcond_rules_base_id] == baseID) {
			// add rule to return array
			ret[ret_ptr] = i;
			ret_ptr++;
		}
	}
	return ret;
}

// get all sub targets from a targetID
function pmcond_get_sub_targets(targetID){
	var ret = Array();
	var ret_ptr = 0;
	// find fieldsets
	for(var i=0; i < pmcond_fieldsets.length; i++) {
		if (pmcond_fieldsets[i][pmcond_fieldsets_fieldset_id] == targetID) {
			// add target to return array
			ret[ret_ptr] = new Array(pmcond_fieldsets[i][pmcond_fieldsets_base_id], pmcond_fieldsets[i][pmcond_fieldsets_target_id]);
			ret_ptr++;
		}
	}
	// find fields
	for(var i=0; i < pmcond_fields.length; i++) {
		if (pmcond_fields[i][pmcond_fields_field_id] == targetID) {
			// add target to return array
			ret[ret_ptr] = new Array(pmcond_fields[i][pmcond_fields_base_id], pmcond_fields[i][pmcond_fields_target_id]);
			ret_ptr++;
		}
	}


	return ret;
}

/**
 * Function pmcond_exec_rule() shows or hides elements if a value is equal to or is set etc...
 *
 *	// EXPLANATION
 *	// valueFromField: Do something if this value is set (e.g.: 'value')
 * 	// targetIDs: ID of target element (field or fieldset) (e.g.: 'uid42')
 *	// baseID: ID of own field element (e.g.: 'uid41')
 *	// targetFunction: What should happened (e.g.: 'hide' or 'show')
 *	// possibilities: hide, show
 *	// targetCondition: When should be done anything (e.g.: 'ifValue')
 *	// possibilities: ifValue, ifNotValue, ifSet, ifNotSet
 *
 */

// Function pmcond_main() shows or hides elements if a value is equal to or is set etc...
function pmcond_exec_rule(rule_index) {
	// get args
	var baseID = pmcond_rules[rule_index][pmcond_rules_base_id];
	var targetID = pmcond_rules[rule_index][pmcond_rules_target_id];
	var valueFromField = pmcond_rules[rule_index][pmcond_rules_value_from_field];
	var targetFunction = pmcond_rules[rule_index][pmcond_rules_target_function];
	var targetCondition = pmcond_rules[rule_index][pmcond_rules_target_condition];

	// EXPLANATION
	// valueFromField: Do something if this value is set (e.g.: 'value')
	// targetIDs: ID of target element (field or fieldset) (e.g.: 'uid42')
	// baseID: ID of own field element (e.g.: 'uid41')
	// targetFunction: What should happened (e.g.: 'hide' or 'show')
	// possibilities: hide, show
	// targetCondition: When should be done anything (e.g.: 'ifValue')
	// possibilities: ifValue, ifNotValue, ifSet, ifNotSet

	// CONFIG
	var target = new Array(); // init array
	var base = new Array(); // init array
	var doit = new Array(); // init array
	var functionName = 'pmcond_main'; // name of current js function

	// LET'S GO
	var target = document.getElementById(targetID); // current target element
	var base = document.getElementById(baseID); // current base element

	// check if target and base elements are existing
	if (!target || !base) {
		alert ('Error in Function ' + functionName + ': Target or base ID don\'t exists (' + getElementById(targetID) + '/' + getElementById(baseID) + ')');
		return "err";
	}

	// 1. get value of basefield
	ty = base.type.toLowerCase();
	switch(ty) {
		case 'text': // if current field is a text field
			var base_value = base.value;
			break;
		case 'checkbox': // if current field is a checkbox field
			if (base.checked == true) { // if checkbox is checked
				var base_value = base.value; // value of checkbox
			} else {
				var base_value = ''; // clear value of checkbox if not checked
			}
			break;
		case 'select-one': // if current field is a select field
			var base_value = base.options[base.selectedIndex].value;
			break;
		default: // default
			alert ('Error in Function ' + functionName + ': base field (' + ty + ') is not allowed');
			return "err";
	}

	// 2. condition part: set doit to 1 or 0
	switch(targetCondition) {
		case 'ifValue': // if current value is an especially value
			if (base_value == valueFromField) {
				doit = 1; // do something
			} else {
				doit = 0; // do nothing
			}
			break;
		case 'ifNotValue': // if current value is not an especially value
			if (base_value != valueFromField) {
				doit = 1; // do something
			} else {
				doit = 0; // do nothing
			}
			break;
		case 'ifSet': // if current value is set
			if (base_value != '') {
				doit = 1; // do something
			} else {
				doit = 0; // do nothing
			}
			break;
		case 'ifNotSet': // if current value is not set
			if (base_value == '') {
				doit = 1; // do something
			} else {
				doit = 0; // do nothing
			}
			break;
		default: // default
			alert ('Error in Function ' + functionName + ': condition (' + targetCondition + ') is not allowed');
			doit = 0; // do nothing
			return "err";
	}

	// 3. do something if doit == 1
	switch(targetFunction) {
		case 'show': // show target
			if (doit) { // of conditions is 1
				target.style.display = "block";
				//if(!target.visible()){new Effect.Appear(target, {duration : 0.3 });}
				//if(!target.visible()){target.show();}
				var ret = "show";
			} else {
				target.style.display = "none";
				//if(target.visible()){new Effect.Fade(target, {duration : 0.3 });}
				//if(target.visible()){target.hide();}
				var ret = "hide";
			}
			break;
		case 'hide': // hide target
			if (doit) { // of conditions is 1
				target.style.display = "none";
				//if(target.visible()){new Effect.Fade(target, {duration : 0.3 });}
				//if(target.visible()){target.hide();}
				var ret = "hide";
			} else {
				target.style.display = "block";
				//if(!target.visible()){new Effect.Appear(target, {duration : 0.3 });}
				//if(target.visible()){target.show();}
				var ret = "show";
			}
			break;
		default: // default
			alert ('Error in Function ' + functionName + ': function (' + targetFunction + ') is not allowed');
			return "err";
	}

	return ret; // after loop
}
