var FORM_MANAGER_CONDITION_SEPARATOR = " AND ";
var FORM_MANAGER_POSSIBILITY_SEPARATOR = " OR ";
var FORM_MANAGER_NAME_VALUE_SEPARATOR = " BEING ";
var FORM_MANAGER_DEPENDS = "DEPENDS ON ";
var FORM_MANAGER_CONFLICTS = "CONFLICTS WITH ";

function getRadioValue(el) {
  for(var i = 0; i < el.length; ++i)
    if(el[i].checked) return el[i].value;
  return null;
}

function getSelectValue(el) {
  if(!el.tagName  || el.tagName.toLowerCase() !== "select")
    return null;
  return el.options[el.selectedIndex].value;
}

function setupDependencies() {
  var showEl = function() {
    this.style.display = "";
    if(this.parentNode.tagName.toLowerCase() == "label")
      this.parentNode.style.display = "";
  };
  var hideEl = function() {
    this.style.display = "none";
    if(typeof this.checked !== "undefined") this.checked = false;
    else this.value = "";
    if(this.parentNode.tagName.toLowerCase() == "label")
      this.parentNode.style.display = "none";
    this.hidden = true;
  };
  var calcDeps = function() {
    for(var i = 0, e = this.elements; i < e.length; ++i) {
      e[i].hidden = false;
      for(var j = 0, f = e[i].className.split(FORM_MANAGER_CONDITION_SEPARATOR); j < f.length; ++j)
        if(f[j].indexOf(FORM_MANAGER_DEPENDS) === 0) {
          for(var k = 0, g = f[j].substr(FORM_MANAGER_DEPENDS.length).split(FORM_MANAGER_POSSIBILITY_SEPARATOR); k < g.length; ++k)
            if(g[k].indexOf(FORM_MANAGER_NAME_VALUE_SEPARATOR) === -1) {
              if(!e[g[k]])
	        alert("FormManager: Warning: Non-existent dependency on " + e[i].name + ": " + g[k] + " doesn't exist.");
	      else if(e[g[k]].checked) break;
            else if(k + 1 == g.length)
                e[i].hide();
            } else {
              var n = g[k].split(FORM_MANAGER_NAME_VALUE_SEPARATOR),
                v = n[1];
              n = n[0];
              if(!e[n])
	        alert("FormManager: Warning: Non-existent dependency on " + e[i].name + ": " + n + " doesn't exist.");
	      else
	        if(getRadioValue(e[n]) == v || getSelectValue(e[n]) == v || (e[n].tagName && e[n].tagName.toLowerCase() !== "select" && e[n].value == v)) break;
	        else if(k + 1 == g.length) e[i].hide();
	    }
        } else if(f[j].indexOf(FORM_MANAGER_CONFLICTS) === 0) {
          if(f[j].indexOf(FORM_MANAGER_NAME_VALUE_SEPARATOR) === -1) {
            if(!e[f[j].substr(FORM_MANAGER_CONFLICTS.length)])
	      alert("FormManager: Warning: Non-existent confliction on " + e[i].name + ": " + f[j] + " doesn't exist.");
	    else if(e[f[j].substr(FORM_MANAGER_CONFLICTS.length)].checked) {
              e[i].hide();
              break;
            }
          } else {
            var n = f[j].substr(FORM_MANAGER_CONFLICTS.length).split(FORM_MANAGER_NAME_VALUE_SEPARATOR),
              v = n[1];
            n = n[0];
            if(!e[n])
	      alert("FormManager: Warning: Non-existent confliction on " + e[i].name + ": " + n + " doesn't exist.");
            else {
              if(getRadioValue(e[n]) == v || getSelectValue(e[n]) == v || (e[n].tagName && e[n].tagName.toLowerCase() !== "select" && e[n].value == v)) {
                e[i].hide();
                break;
              }
            }
          }
        }
      if(!e[i].hidden) e[i].show();
    }
  };

  var changeHandler = function(e) {
    this.form.calculateDependencies();

  	if (!e) var e = window.event;
    var eSrc = (e.srcElement) ? e.srcElement : e.target;
  
	if ( (""+typeof(handleEvent))  !=  "undefined" ) {
		handleEvent(eSrc, e.type);
	}
    return true;
  };

  for(var i = 0; i < arguments.length; ++i) {
    for(var j = 0, e = window.document.forms[arguments[i]].elements; j < e.length; ++j) {
      e[j].onchange = e[j].onkeyup = e[j].onfocus = e[j].onclick = e[j].onkeydown = changeHandler;
      e[j].hide = hideEl;
      e[j].show = showEl;
    }

    window.document.forms[arguments[i]].calculateDependencies = calcDeps;
    window.document.forms[arguments[i]].calculateDependencies();
  }
}

