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;
	
//	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);
		
		old_children = {};
		
		if (window.console && window.console.log) {
			for (var k=0; k < bindings.length; k++) {
				for (var p in old_children) {
					if (p == bindings[k]['CHILDREN'].toString()) {
						// Found a same child, append to the common parent
						console.log(bindings[ old_children[bindings[k]['CHILDREN'].toString()] ])
						// .concat(bindings[k]['PARENTS']);
					}
				}
				old_children[ bindings[k]['CHILDREN'].toString() ] = k;
			}
		}
		
		for (var k=0; k < bindings.length; k++) {
			
			// Parents
			parents = bindings[k]['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){
//						console.log(bindingParent);
						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]);
					
					// Set event handler
					bindingParent.change(doBinding);
				}
			}
			
			// Children
			children = bindings[k]['CHILDREN'];
			
			for (var i=0; i < children.length; i++) {
				var child = smartGetElement(children[i]);
				if(!child.length){
					console.log(children[i]);
					throw("couldn't find your sonny!");
				}
				children[i] = child.closest(".item");
				
				// Evaluate initial parent states and hide children if needed
				if (!hasAllTruth(parents)) {
					$(children[i]).hide();
				}
			}
		}
	}
}

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]+"']");
		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+"']");
		}
	}
	
	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 (hasAllTruth(parents)){
			// show
			for (var i=0; i < children.length; i++){
				$(children[i]).slideDown();
			}
		} else {
			// hide
			for (var i=0; i < children.length; i++){
				$(children[i]).slideUp();
			}
		}
	}
}

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");
	
	if (
	(tagName == "checkbox" && (element.length == 1 && element.attr("checked") || element.filter("input[value='"+choice+"']").attr("checked")))
	|| ((tagName == "select-one" || tagName == "select-multiple") && element.val() == choice)
	|| (tagName == "radio" && element.filter(":checked").val() == choice)) {
		// FIXME add && choice in element.val()
		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;
}

$(function() {
	setBindings();
});
