var ConditionalShow = {

	library: [],
	settings: {},

	add: function ( watch_element, events, behaviours )
	{
		ConditionalShow.library.push( [watch_element, events, behaviours] );
	},

	init: function ()
	{
		for (var lib_index=0; lib_index<ConditionalShow.library.length; lib_index++){
			var watch_element = ConditionalShow.library[lib_index][0];
			var events = ConditionalShow.library[lib_index][1];
			var behaviours = ConditionalShow.library[lib_index][2];

			if ( behaviours["affect_elements"] == undefined ){
				behaviours["affect_elements"] = [];

				var actions_indexed = {};
				for (var i in behaviours["actions"]){
					var j;
					if (behaviours["actions"][i]["show"] != undefined){
						for (j=0; j<behaviours["actions"][i]["show"].length; j++){
							if ( actions_indexed[ behaviours["actions"][i]["show"][j] ] == undefined ){
								behaviours["affect_elements"].push( behaviours["actions"][i]["show"][j] );
								actions_indexed[ behaviours["actions"][i]["show"][j] ] = "hide";
							}
						}
					}
					if (behaviours["actions"][i]["hide"] != undefined){
						for (j=0; j<behaviours["actions"][i]["hide"].length; j++){
							if ( actions_indexed[ behaviours["actions"][i]["hide"][j] ] == undefined ){
								behaviours["affect_elements"].push( behaviours["actions"][i]["hide"][j] );
								actions_indexed[ behaviours["actions"][i]["hide"][j] ] = "show";
							}
						}
					}
				}
				// save this updated behaviours array
				ConditionalShow.settings[watch_element] = {};
				ConditionalShow.settings[watch_element]["behaviours"] = behaviours;
				ConditionalShow.settings[watch_element]["actions"] = actions_indexed;
			}

			ConditionalShow.settings[watch_element].cond_element_name = watch_element;
			ConditionalShow.settings[watch_element].update_call = function() {
				var watch_element = this.cond_element_name;
				ConditionalShow.cond_show( watch_element );
			};

			for (var i=0; i<events.length; i++){
				// check that the watch_element is a valid element id, not a csv
				var watch_elements = [];

				if ( watch_element.indexOf(",") == -1 ){
					watch_elements.push( watch_element );
				} else {
					watch_elements = watch_element.split(",");
				}

				for (var j=0; j<watch_elements.length; j++){
					if($(watch_elements[j]) == undefined) continue;
					$(watch_elements[j]).cond_element_name = watch_element;
					$(watch_elements[j]).observe(events[i], ConditionalShow.settings[watch_element].update_call.bind(ConditionalShow.settings[watch_element]));
				}
			}
			ConditionalShow.settings[watch_element].update_call();
		}
	},

	multiple_select: function( element ) {
		var selected = [];
		for(var i=0; i<$(element).options.length; i++) {
			if($(element).options[i].selected){
				selected.push($(element).options[i].value);
			}
		}
		return selected;
	},

	cond_show: function ( watch_element )
	{
//console.log("cond_show on watch_element: ");
//console.log(watch_element);
		var new_value = [];
		var watch_elements = [];
		if ( watch_element.indexOf(",") == -1 ){
			watch_elements.push( watch_element );
		} else {
			watch_elements = watch_element.split(",");
		}

		for (var j=0; j<watch_elements.length; j++){
			var watch_element_id = watch_elements[j];
			if($(watch_element_id) == undefined) continue;
			var watch_element_value = $(watch_element_id).value;
//console.log("watch_element_value: " + watch_element_value + " type: " +$(watch_element_id).type + " checked: " + $(watch_element_id).checked);
			if ( ($(watch_element_id).type == "checkbox" || $(watch_element_id).type == "radio") && $(watch_element_id).checked == false ){
				watch_element_value = 0;
				if ( $(watch_element_id+"_") != undefined && $(watch_element_id+"_").value != undefined ){
					watch_element_value = $(watch_element_id+"_").value;
				}
			} else if( $(watch_element_id).type == "select-multiple" ) {
				watch_element_value = ConditionalShow.multiple_select( watch_element_id );
			}

			if ( !Object.isArray(watch_element_value) ){
				new_value.push( watch_element_value );
			} else {
				new_value = new_value.concat( watch_element_value );
			}
		}

		var behaviours = ConditionalShow.settings[watch_element]["behaviours"];
		var allshow = [];
		var allhide = [];

		for(var i=0; i<new_value.length; i++) {
			var value = new_value[i];
			// find what the selected options actions should be
			var selected_action = behaviours["actions"][value];
			if ( selected_action == undefined ){
				// check if the value is an array - from a multiselect, orderable list etc
				var value_obj;
				if(typeof value == 'string') {
					value_obj = value.toQueryParams();
				}
				if ( value_obj != undefined && value_obj[ "rank[]" ] != undefined ){
					// from an orderable list
					// go through all of the conditions, looking for a match to perform actions

					for ( var action in behaviours["actions"] ){
						if ( ConditionalShow.adv_condition_match(action, value_obj[ "rank[]" ]) ){
							selected_action = behaviours["actions"][action];
							break;
						}
					}
				}
			}

			if ( selected_action == undefined ){
				selected_action = behaviours["actions"]["_default"];
			}

			if ( selected_action != undefined ){
				if ( selected_action["show"] != undefined )
					allshow = allshow.concat(selected_action["show"]);
				if ( selected_action["hide"] != undefined )
					allhide = allhide.concat(selected_action["hide"]);
			}
		}

		var actions = ConditionalShow.settings[watch_element]["actions"];
		var new_actions = Object.clone(actions);

		for (var i=0; i<allhide.length; i++){
			new_actions[allhide[i]] = "hide";
		}
		for (var i=0; i<allshow.length; i++){
			new_actions[allshow[i]] = "show";
		}

		for (var i in new_actions){
			if($(i) == undefined) continue;

			if (new_actions[i] == "show" ){
				Element.show( i );
			} else {
				Element.hide( i );
			}
		}
	},

	adv_condition_match: function( key, current_value ){

		var operators = ["<>", "!=", "<=", ">=", "<", ">", "==", "="];
		var op_matches = [];
		var i;
//console.log('adv_condition_match key: ' + key + " current_value: " + current_value);
		for (i=0; i<operators.length; i++){
			var op = operators[i];
			var op_point = key.indexOf(op);

			if ( op_point != -1 ){
				var op_value = key.substring(0, op_point);
				var op_compare_index = key.substring(op_point+op.length);

				var op_index = false;

				var op_value_lower = op_value.toLowerCase();
				for (var j=0; j<current_value.length; j++){
					var compare_value_lower = current_value[j].toLowerCase();

					if ( op_value_lower == compare_value_lower ){
//console.log('adv_condition_match on op_value_lower: ' + op_value_lower + " compare_value_lower: " + compare_value_lower + " at pos: " + j);
						op_matches.push( {value: op_value, index: j+1, operator: op, compare_index: op_compare_index} );
						break;
					}
				}
			}
		}

		for (i=0; i<op_matches.length; i++){
			var match = false;
			switch ( op_matches[i].operator ){
				case "<>":
				case "!=":
					if ( op_matches[i].index != op_matches[i].compare_index ){
						match = true;
					}
					break;
				case "<=":
					if ( op_matches[i].index <= op_matches[i].compare_index){
						match = true;
					}
					break;
				case ">=":
					if ( op_matches[i].index >= op_matches[i].compare_index){
						match = true;
					}
					break;
				case "<":
					if ( op_matches[i].index < op_matches[i].compare_index){
						match = true;
					}
					break;
				case ">":
					if ( op_matches[i].index > op_matches[i].compare_index){
						match = true;
					}
					break;
				case "=":
				case "==":
					if ( op_matches[i].index == op_matches[i].compare_index){
						match = true;
					}
					break;

			}
			if ( match ){
				return true;
			}
		}
		return false;
	},

	// return the elements from array1 that are not present in array2
	array_diff: function ( array1, array2 )
	{
		diff = [];

		array2_indexed = [];
		for (var i=0; i<array2.length; i++){
			array2_indexed[ array2[i] ] = i;
		}

		for (var i=0; i<array1.length; i++){
			if (array2_indexed[ array1[i] ] == undefined) {
				diff.push( array1[i] );
			}
		}

		return diff;
	}
}

document.observe('dom:loaded', function() {
	ConditionalShow.init();
});