//clear our form values when deselecting
$.fn.clearForm = function() {
  return this.each(function() {
    var type = this.type, tag = this.tagName.toLowerCase();
    if (tag == 'form')
      return $(':input',this).clearForm();
    if (type == 'text' || type == 'password' || tag == 'textarea')
      this.value = '';
    else if (type == 'checkbox' || type == 'radio')
      this.checked = false;
    else if (tag == 'select')
      this.selectedIndex = -1;
  });
};

function setBindings() {
	// Create the binding event handlers
	var many_bindings_js = $("input[type='hidden'][name*='js_dataform_bindings']");
	var bindings_js = '';
	var bindings;
	var bindingParent;
	var parents;
	var children;
	var key;
	
//	console.log("many_bindings_js");
//	console.log(many_bindings_js);
	
	for (var B=0; B < many_bindings_js.length; B++) {
		bindings_js = many_bindings_js[B].value;
		
//		console.log(bindings_js);
		if (!bindings_js)
			continue;
		
		// Scrub Yes/No/True/False values to remove the trailing space and newlines because CF is awesome
		bindings_js = bindings_js.replace(/"(Yes|No|True|False)[\s]*"/ig, '"$1"');
		bindings = JSON.parse(bindings_js);
		
		var old_children = {};
		var bindings_to_remove = [];
		
		for (var k=0; k < bindings.length; k++) {
			for (var p in old_children) {
				if (bindings[old_children[p]]['CHILDREN'] == bindings[k]['CHILDREN'].toString()) {
					// Found a same child, append to the common parent
					key = old_children[bindings[k]['CHILDREN'].toString()];
					bindings[key]['PARENTS'] = bindings[key]['PARENTS'].concat(bindings[k]['PARENTS']);

					// And then remove this binding because we added everything to the common parent
					bindings_to_remove.push(k);
					break;
				}
			}
			old_children[ bindings[k]['CHILDREN'].toString() ] = k;
		}
		
		for (var i in bindings_to_remove) {
			delete bindings[bindings_to_remove[i]];
		}
		
		for (var k=0; k < bindings.length; k++) {
			if (!bindings[k])
				continue;
			
			// Parents
			parents = bindings[k]['PARENTS'];
//			console.log(parents);
			for (var i=0; i < parents.length; i++) {
				for (var j=0; j < parents[i].length; j++) {
					bindingParent = smartGetElement(parents[i][j]);
					if(!bindingParent.length){
						throw("couldn't find your mommy!");
					}
					
					// Replace the original string with the actual DOM element 
					if (typeof parents[i][j] == "object") {
						parents[i][j][0] = bindingParent;
					} else {
						parents[i][j] = bindingParent;
					}
					
					// Create the set of bindings on this element
					if (!bindingParent.data("bindings")) {
						bindingParent.data("bindings", []);
					}
					
					// Set each group of compound or single bindings (elements which
					// are AND'd together). Each group will be OR'd together to evaluate truth.
					bindingParent.data("bindings").push(bindings[k]);
					
					$(bindingParent).closest(".item").addClass('p1'); //Setting class for CSS styling
					// Set event handler
					bindingParent.change(doBinding).click(doBinding);
					if (bindingParent.attr("type") == 'text') {
						bindingParent.keyup(doBinding);
					}
				}
			}
			
			// Children
			children = bindings[k]['CHILDREN'];
			
			try {
				for (var i=0; i < children.length; i++) {
					var child = smartGetElement(children[i]);
					if(!child.length){
						throw({ type: "binding", message: "Missing child question: " + children[i], detail: "Parent question: " + bindings[k].PARENTS[0][0][0][0].name, binding: bindings[k] });
					}
					children[i] = child.closest(".item");
					
					
					// Added classes so the CSS can be set to indent children from the parents. 
					// This only works with single parent situations, and only goes 4 levels deep
					if($(children[i]).attr("class") != "item required p1"){
						$(children[i]).addClass('c1'); //Setting class for CSS styling
					}
	
					if($(children[i]).prev().prev().attr("class") == "item required p1"){
						$(children[i]).addClass('c1'); //Setting class for CSS styling
					}
					if($(children[i]).prev().prev().attr("class") == 'item c1 p1'){
						$(children[i]).removeClass('c1'); //Setting class for CSS styling
						$(children[i]).addClass('c2'); //Setting class for CSS styling
					}
					if($(children[i]).prev().prev().attr("class") == 'item c2 p1'){
						$(children[i]).removeClass('c2'); //Setting class for CSS styling
						$(children[i]).addClass('c3'); //Setting class for CSS styling
					}
					
					if($(children[i]).attr("class") == 'item' && $(children[i]).prev().prev().attr("class") == "item c1"){
						$(children[i]).addClass('c1'); //Setting class for CSS styling
					}
					if($(children[i]).attr("class") == 'item c1' && $(children[i]).prev().prev().attr("class") == "item c2"){
						$(children[i]).removeClass('c1'); //Setting class for CSS styling
						$(children[i]).addClass('c2'); //Setting class for CSS styling
					}
					if($(children[i]).attr("class") == 'item c2' && $(children[i]).prev().prev().attr("class") == "item c3"){
						$(children[i]).removeClass('c2'); //Setting class for CSS styling
						$(children[i]).addClass('c3'); //Setting class for CSS styling
					}
					//END adding classes
	
					// Evaluate initial parent states and hide children if needed
					if (!hasAllTruth(parents)) {
						$(children[i]).hide();
					}
				}
			} catch(e) {
				if(typeof(console)) {
					console.log("Error while trying to establish children questions for bindings", e);
				}
			}
		}
	}
}

function smartGetElement(name) {
	var bindingElement
	var regex
	var trimmed;
	
	if (typeof name == "object") {
		// We're on a list (parent with choice)
		bindingElement = $("select[name^='"+name[0]+"']");
		
		/*
		 * This 'Other' checking is custom to ezPlug. Please keep it in mind when updating bindings.js
		 */
		if (name[1] == 'Other') {
			bindingElement = $("input[name^='"+name[0]+"_YYY-Others-YYY']");
		}
		if (!bindingElement.length) {
			bindingElement = $("input[name^='"+name[0]+"']");
		}
	} else {
		// We're on a string (direct parent)
		bindingElement = $("select[name^='"+name+"']");

		if (!bindingElement.length) {
			bindingElement = $("input[name^='"+name+"']");
		}
		if (!bindingElement.length) {
			bindingElement = $("textarea[name^='"+name+"']");
		}
		if (!bindingElement.length) {
			// If we didn't find an element #q directly, look for a label with for=id_name
			bindingElement = $("label[for*='"+name+"']");
		}
	}
//	console.log(bindingElement);
	
	return bindingElement;
}

function doBinding() {
	var parents;
	var children;
	var bindings = $(this).data("bindings");
	
	for (var b=0; b < bindings.length; b++) {
		parents = bindings[b]['PARENTS'];
		children = bindings[b]['CHILDREN'];
		
		
		if (typeof(console) != 'undefined') {
			//console.log(parents);
			//console.log(children);
		}
		
		
		if (hasAllTruth(parents)){
			// show
			for (var i=0; i < children.length; i++){
				$(children[i]).not(':animated').slideDown();
			}
		} else {
			// hide
			for (var i=0; i < children.length; i++){
				$(children[i]).not(':animated').slideUp();
				$(children[i]).find('input,select,textarea').clearForm();
			}
		}
	}
}

function hasSingleTruth(element) {
	var choice = null;
	if (element.length > 1) {
		// We're on a list (parent with choice)
		choice = element[1];
		element = element[0];
	}
	
	var tagName = element.attr("type");
	var value = element.val();
	
	if (
		(tagName == "checkbox" && (element.length == 1 && element.attr("checked") || element.filter("input[value='"+choice+"']").attr("checked")))
		|| ((tagName == "select-one" || tagName == "select-multiple") && (value && value.indexOf(choice) != -1))
		|| ((tagName == "text") && element.val() != "")
		|| (tagName == "radio" && element.filter(":checked").val() == choice)) {
		return true;
	} else {
		return false;
	}
}

function hasAllTruth(listOfParents) {
	for(var i=0; i < listOfParents.length; i++) {
		var parentSet = listOfParents[i];
		
		// Assume we have all truth
		var tempTruth = true;
		
		for(var x=0; x < parentSet.length; x++){
			var parent = parentSet[x];
			
			// Make sure I always had truth before
			tempTruth = hasSingleTruth(parent) && tempTruth;
		}
		
		if(tempTruth)
			return true;
	}
	return false;
}

// this seems to be called already
$(function() {
	setBindings();
});

