var NetForms = new Object();

NetForms.eventListeners = [];
NetForms.loadStates = [];
NetForms.startupScripts = [];
NetForms.constraints = [];

// public - add eventListeners before page loads, to bind when page is loaded
NetForms.addEventListeners = function (eventTypes, ids, fnHandler) {
	NetForms.eventListeners.push({"eventTypes":eventTypes, "ids":ids, "fnHandler":(fnHandler == null ? NetForms.updateUI : fnHandler)});
}

NetForms.addEventListener = function (eventType, id, fnHandler) {
	NetForms.addEventListeners([eventType], [id], fnHandler);
}

// public - add startup states before page loads, to execute when page is loaded
NetForms.addLoadState = function (sourceId, sourcePropExpr, sourceValueExpr) {
	NetForms.loadStates.push({"sourceId":sourceId, "sourcePropExpr":sourcePropExpr, "sourceValueExpr":sourceValueExpr});
}

// public - add startup function to execute once page is loaded (usually to ensure DOM references exist)
NetForms.addStartupScript = function (startupScript) {
	NetForms.startupScripts.push(startupScript);
}

// public - link a required value of a sources property to the value of a target property, else other value
NetForms.link = function (sourceId, sourcePropExpr, sourceValueExpr, targetId, targetPropExpr, targetValueTrueExpr, targetValueFalseExpr) {
	var constraint = new Object();
	constraint.sourceId = sourceId;
	constraint.targetId = targetId;
	constraint.sourcePropExpr = sourcePropExpr;
	constraint.sourceValueExpr = sourceValueExpr;
	constraint.targetPropExpr = targetPropExpr;
	constraint.targetValueTrueExpr = targetValueTrueExpr;
	constraint.targetValueFalseExpr = targetValueFalseExpr;
	NetForms.constraints.push(constraint);
}

// private - initialise framework
NetForms.initialise = function () {
	// bind eventListeners
	for (var i in NetForms.eventListeners) {
		var listener = NetForms.eventListeners[i];
		var fnHandler = listener.fnHandler;
		for (var j in listener.eventTypes) {
			var eventType = listener.eventTypes[j];
			for (var k in listener.ids) {
				var id = listener.ids[k];
				var element;
				if (typeof(id) == 'string') 
					element = document.getElementById(id);
				else
					element = id;
				YAHOO.util.Event.addListener(element, eventType, fnHandler);
			}
		}
	}

	// execute startup states
	for (var i in NetForms.loadStates) {
		var state = NetForms.loadStates[i];
		NetForms.set(state.sourceId, state.sourcePropExpr, state.sourceValueExpr);
	}

	// execute startup scripts
	for (var i in NetForms.startupScripts) {
		var script = NetForms.startupScripts[i];
		script();
	}

	NetForms.updateUI();

	// test for javascript
	if (document.getElementById('jscriptEnabled') != null)
		document.getElementById('jscriptEnabled').value = "true";
}

NetForms.updateUI = function () {
	NetForms.updateConstraints();
}

// public - set an elements property to a value
NetForms.set = function (sourceId, sourcePropExpr, sourceValueExpr) {
	var expr = "document.getElementById('" + sourceId+ "')." + sourcePropExpr+ " = " + NetForms.toEval(sourceValueExpr) + ";";
	eval(expr);
}

// private - convert the value expression to a form suitable for eval()
NetForms.toEval = function (expr) {
	var exp = typeof(expr) == 'string' ? '"' : '';
	return exp + expr + exp;
}

// private - update all contraints sources state based on their targets current state
NetForms.updateConstraints = function () {
	for (var i=0; i<NetForms.constraints.length; i++ ) {
		var obj = NetForms.constraints[i];
		var expr = "if (document.getElementById('" + obj.sourceId + "')." + obj.sourcePropExpr + " == " + NetForms.toEval(obj.sourceValueExpr) + ")\n";
		expr += "  document.getElementById('" + obj.targetId + "')." + obj.targetPropExpr + " = " + NetForms.toEval(obj.targetValueTrueExpr) + ";\n";
		if (obj.targetValueFalseExpr != null)  {
			expr += "else\n";
			expr += "  document.getElementById('" + obj.targetId + "')." + obj.targetPropExpr + " = " + NetForms.toEval(obj.targetValueFalseExpr) + ";";
		}
		eval(expr);
	}
}

YAHOO.util.Event.onDOMReady(NetForms.initialise);