if(!console) {
	var console={
		log: function(oObj) {}
	};
}

var Formidable = {

	oLoading: null,
	displayLoader: function() {
		
		if(this.Browser.name == "internet explorer") {
			this.oLoading.style.position = "absolute";
			this.oLoading.style.top = Math.round(
				document.body.scrollTop
				+ (Formidable.Position.windowSize().height / 2)
				- (Element.getHeight(this.oLoading) / 2)
			);
		}

		try {
			document.body.appendChild(this.oLoading);
		} catch(e) {}
	},
	removeLoader: function() {
		try {
			DOM.remove(this.oLoading);
		} catch(e) {}
	},

	initialize: function(oConfig) {
		Object.extend(this, oConfig);
		this.Browser.getBrowserInfo();

		this.oLoading = $img({
			style: "position: fixed; right: 50%; top: 50%; margin: 0; padding: 0; z-index: 999999999;",
			src: this.path + "res/images/loading.gif"
		});
	},
	SUBMIT_FULL: 1,
	SUBMIT_REFRESH: -1,
	SUBMIT_TEST: -2,
	SUBMIT_DRAFT: -3,
	
	Classes: {},		// placeholder for classes definitions; used like this: var oObj = new Formidable.Classes.SomeObject(params)
	Context: {
		Forms: {},		// placeholder for subscribed forms in the page
		Objects: {}		// placeholder for page-level objects ( like modalbox )
	},

	Lister: {
		Pager: {
			goTo: function(sFormUniqueId, iPage) {

				var aForm = Formidable.f(sFormUniqueId);
				var oForm = aForm.domNode();

				oForm[aForm.Misc.HiddenIds.Lister.page].value=iPage;
				aForm.submitRefresh();
			}
		},
		Sort: {
			by: function(sName, sDirection, sFormUniqueId) {
				
				var aForm = Formidable.f(sFormUniqueId);
				var oForm = aForm.domNode();

				oForm[aForm.Misc.HiddenIds.Lister.sortField].value=sName;
				oForm[aForm.Misc.HiddenIds.Lister.sortDirection].value=sDirection;
				oForm.action=aForm.Misc.Urls.Lister.sortAction;

				aForm.submitRefresh();
			}
		}
	},
	f: function(sFormId) {		// shortcut for getting form instance
		return this.Context.Forms[sFormId];
	},
	o: function(sObjectId) {
		return this.Context.Objects[sObjectId];
	},
	executeInlineJs: function(oJson) {
		console.log("executeInlineJs", oJson);
		$H(oJson).each(function(sJs) {
			eval(unescape(sJs));
		}.bind(this));
	},
	Browser: {
		name: "",
		version: "",
		os: "",
		total: "",
		thestring: "",
		place: "",
		detect: navigator.userAgent.toLowerCase(),
		checkIt: function(string) {
			this.place = this.detect.indexOf(string) + 1;
			this.thestring = string;
			return this.place;
		},
		getBrowserInfo: function() {
			//Browser detect script originally created by Peter Paul Koch at http://www.quirksmode.org/
			if (this.checkIt('konqueror')) {
				this.name = "konqueror";
				this.os = "linux";
			}
			else if (this.checkIt('safari')) this.name = "safari"
			else if (this.checkIt('omniweb')) this.name = "omniweb"
			else if (this.checkIt('opera')) this.name 	= "opera"
			else if (this.checkIt('webtv')) this.name 	= "webtv";
			else if (this.checkIt('icab')) this.name 	= "icab"
			else if (this.checkIt('msie')) this.name 	= "internet explorer"
			else if (!this.checkIt('compatible')) {
				this.name = "netscape"
				this.version = this.detect.charAt(8);
			}
			else this.name = "unknown";

			if (!this.version) this.version = this.detect.charAt(this.place + this.thestring.length);

			if (!this.os) {
				if (this.checkIt('linux')) this.os 		= "linux";
				else if (this.checkIt('x11')) this.os 	= "unix";
				else if (this.checkIt('mac')) this.os 	= "mac"
				else if (this.checkIt('win')) this.os 	= "windows"
				else this.os 							= "unknown";
			}
		}
	},
	Position: {
		windowSize: function() {
			if ( typeof( window.innerWidth ) == 'number' ){
				my_width  = window.innerWidth;
				my_height = window.innerHeight;
			}else if ( document.documentElement && 
					 ( document.documentElement.clientWidth ||
					   document.documentElement.clientHeight ) ){
				my_width  = document.documentElement.clientWidth;
				my_height = document.documentElement.clientHeight;
			}
			else if ( document.body && 
					( document.body.clientWidth || document.body.clientHeight ) ){
				my_width  = document.body.clientWidth;
				my_height = document.body.clientHeight;
			}

			return {width: my_width, height: my_height};
		},
		bodySize: function() {
			var w = 0;
			var h = 0;

			if(document.body.scrollWidth) {
				w = document.body.scrollWidth;
			} else {
				w = document.documentElement.offsetWidth;
				if(window.scrollMaxX) {
					w += window.scrollMaxX;
				}
			}

			if (document.body.scrollHeight) {
				h = document.body.scrollHeight;
			} else {
				h = document.documentElement.offsetHeight;
			}

			return {width: w, height: h};
		}
	}
};

Formidable.Classes.FormBaseClass = Base.extend({
	//domNode: null,		// FORM html object reference in DOM
	domNode: function() {
		//return $(this.config.id);
		return document.forms[this.sFormIdToUse];
	},
	ajaxCache: {},
	ViewState: [],
	Objects: {},		// placeholder for instanciated JS objects in the FORM

	constructor: function(oConfig) {
		Object.extend(this, oConfig);
		//this.domForm = document.forms[this.sFormIdToUse];
	},
	o: function(sObjectId) {	// shortcut for getting object instance

		if(sObjectId == "tx_ameosformidable") {
			return Formidable;
		} else if(Formidable.f(sObjectId)) {
			return Formidable.f(sObjectId);
		} else if(this.Objects[sObjectId]) {
			return this.Objects[sObjectId];
		} else if(this.Objects[this.sFormIdToUse + "[" + sObjectId + "]"]) {
			return this.Objects[this.sFormIdToUse + "[" + sObjectId + "]"];
		}

		return $(sObjectId);
	},
	updateViewState: function(oExecuter) {
		this.ViewState.push(oExecuter);
	},
	
	executeServerEvent: function(sEventId, sSubmitMode, sParams, sHash, sJsConfirm) {

		var bThrow = false;

		if(sJsConfirm != false) {
			bThrow = confirm(unescape(sJsConfirm));
		} else {
			bThrow = true;
		}

		if(bThrow) {
			window.status = "Server Event thrown";

			$(this.sFormIdToUse + "[AMEOSFORMIDABLE_SERVEREVENT]").value=sEventId;

			if(sParams != false) {
				$(this.sFormIdToUse + "[AMEOSFORMIDABLE_SERVEREVENT_PARAMS]").value=sParams;
				$(this.sFormIdToUse + "[AMEOSFORMIDABLE_SERVEREVENT_HASH]").value=sHash;
			}
			
			
			if(sSubmitMode) {
				this.doSubmit(sSubmitMode);
			} else {
				this.domNode().submit();
			}
		}
	},
	_clientData: function(oData) {
		
		if(oData) {
			if(typeof oData == "string") {
				if(oData.slice(0, 12) == "clientData::") {
					console.log("_clientData::", oData);
					sObjectId = oData.slice(12);
					oObj = this.o(sObjectId);
					if(oObj && typeof oObj.getValue == "function") {
						oData = oObj.getValue();
					}
				}
			} else if(typeof oData == "object") {
				for(var i in oData) {
					oData[i] = this._clientData(oData[i]);
				}
			}
		}

		return oData;
	},
	executeClientEvent: function(sObjectId, bPersist, oTask) {
		console.log("Executing client event", "sObjectId:", sObjectId, "bPersist:", bPersist, "oTask", oTask);

		if(oTask.object) {
			// it's a single task to execute
			var oObject = this.o(oTask.object);

			if(oObject) {
				if(oObject[oTask.method]) {

					oObject[oTask.method](
						this._clientData(oTask.data)
					);

					if(bPersist) {
						this.updateViewState(oTask);
					}
				} else {
					console.log("executeClientEvent: single task: No method named " + oTask.method + " on " + oTask.object);
				}
			} else {
				console.log("executeClientEvent: single task: No object named " + oTask.object);
			}
		} else {
			// it's a collection of tasks to execute
			var _this = this;

			$H(oTask).each(function(value, key) {
				
				var oObject = _this.o(oTask[key].object);

				if(oObject && oObject[oTask[key].method]) {
					oObject[oTask[key].method](
						_this._clientData(oTask[key].data)
					);

					if(bPersist) {
						_this.updateViewState(oTask[key]);
					}
				} else {
					console.log("executeClientEvent: multi tasks: No object named " + oTask[key].object);
				}

			});
		}
	},

	executeAjaxEvent: function(sObjectId, sEventId, sSafeLock, bCache, bPersist, aParams, aRowParams) {

		console.log("executeAjaxEvent");

		var aValues = {};
		if(aParams) {
			for(var sKey in aParams) {
				sName = aParams[sKey];
				
				var oElement = this.o(sName);

				if(oElement) {
					aValues[sName] = oElement.getValue();
				} else if((oElement = $(this.rdtIdByName(sName)))) {
					aValues[sName] = $F(oElement);
				} else {
					aValues[sName] = "";
				}
			}
		}

/*		Object.extend(aRowParams).each(function(sA, sB) {
			console.log("rowparam", sA, ":", sB);
		}.bind(this));*/

		if(aRowParams) {
			for(var sName in aRowParams) {
				aValues[sName] = aRowParams[sName];
			}
		}

		var sValue = JSONstring.make(aValues, true);
		var sUrl = this.Misc.Urls.Ajax.event + "&formhash=" + this.sSessionDataHashKey + "&eventid=" + sEventId + "&safelock=" + sSafeLock + "&value=" + escape(sValue);

		if(bCache && this.ajaxCache[sUrl] != undefined) {
			this.executeAjaxResponse(
				this.ajaxCache[sUrl]
			);
		} else {
			
			Formidable.displayLoader();

			new Ajax.Request(
				sUrl,
				{
					method:'get',
					onSuccess: function(transport) {
						eval("var oJson=" + transport.responseText + ";");
						if(bCache) {
							this.ajaxCache[sUrl] = oJson;
						}
						
						Formidable.removeLoader();

						this.executeAjaxResponse(oJson, bPersist);
					}.bindAsEventListener(this),

					onFailure: function(){
						alert('Something went wrong...');
					}.bindAsEventListener(this)
				}
			);
		}
	},
	executeAjaxResponse: function(oResponse, bPersist) {
		if(oResponse.object) {
			// it's a single task to execute
			var oObject = this.o(oResponse.object);

			if(oObject) {
				if(oObject[oResponse.method]) {
					console.log("calling", oResponse.method, "on", oResponse.object);
					oObject[oResponse.method](oResponse.data);

					if(bPersist) {
						this.updateViewState(oResponse);
					}
				} else {
					console.log("executeAjaxResponse: single task: No method named " + oResponse.method + " on " + oResponse.object);
				}
			} else {
				console.log("executeAjaxResponse: single task: No object named " + oResponse.object);
			}
		} else {
			// it's a collection of tasks to execute
			var _this = this;

			$H(oResponse).each(function(value, key) {
				
				var oObject = _this.o(oResponse[key].object);

				if(oObject) {
					if(oObject[oResponse[key].method]) {
						oObject[oResponse[key].method](oResponse[key].data);

						if(bPersist) {
							_this.updateViewState(oResponse[key]);
						}
					} else {
						console.log("executeAjaxResponse: multi tasks: No method named " + oResponse[key].method + " on " + oResponse[key].object);
					}
				} else {
					console.log("executeAjaxResponse: multi tasks: No object named " + oResponse[key].object);
				}

			});
		}
	},
	initPersistedData: function(oData) {
		for(var key in oData) {
			if(this.o(key)) {
				try {
					this.o(key).rebirth(oData[key]);
				} catch(e) {
					// rebirth not implemented on this object
				}
			}
		}
	},
	rdtIdByName: function(sName) {
		return this.sFormIdToUse + "[" + sName + "]";
	},
	submitDraft: function() {
		this.doSubmit(Formidable.SUBMIT_DRAFT);
	},

	submitTest: function() {
		this.doSubmit(Formidable.SUBMIT_TEST);
	},

	submitRefresh: function() {
		this.doSubmit(Formidable.SUBMIT_REFRESH);
	},

	submitFull: function() {
		this.doSubmit(Formidable.SUBMIT_FULL);
	},

	submitOnEnter: function(sFromUniqueId, myfield, e) {

		var keycode;
		
		if(window.event) {
			keycode = window.event.keyCode;
		} else if (e) {
			keycode = e.which;
		} else {
			return true;
		}
		
		if(keycode == 13) {
			this.doSubmit(Formidable.SUBMIT_FULL);
			return false;
		} else {
			return true;
		}
	},


	doSubmit: function(iMode) {

		if(!iMode) { iMode = "";}

		var aEventNames = {};

		aEventNames[Formidable.SUBMIT_FULL]		= "FULL SUBMIT";
		aEventNames[Formidable.SUBMIT_REFRESH]	= "REFRESH SUBMIT";
		aEventNames[Formidable.SUBMIT_DRAFT]	= "DRAFT SUBMIT";
		aEventNames[Formidable.SUBMIT_TEST]		= "TEST SUBMIT";
		
		var sSubmitFormId = false;

		if(!sSubmitFormId) {

			// submit form and each subform !

			window.status = aEventNames[iMode] + " of : " + this.sFormIdToUse + "," + this.aForms;

			for(sElementName in this.aForms) {
				$(this.aForms[sElementName] + "[AMEOSFORMIDABLE_SUBMITTED]").value=iMode;
			}

			// submitting Main form
			$(this.sFormIdToUse + "[AMEOSFORMIDABLE_SUBMITTED]").value=iMode;

		} else {

			window.status = aEventNames[iMode] + " of : " + sSubmitFormId;
			$(sSubmitFormId + "[AMEOSFORMIDABLE_SUBMITTED]").value=iMode;
		}

		if(this.ViewState.length > 0) {
			// saving viewstate
			$(this.sFormIdToUse + "[AMEOSFORMIDABLE_VIEWSTATE]").value=JSONstring.make(this.ViewState, true);
		} else {
			$(this.sFormIdToUse + "[AMEOSFORMIDABLE_VIEWSTATE]").value="";
		}

		this.domNode().submit();
	},
	doNothing: function(oSource) {
		return true;
	},
	scrollTo: function(sName) {
		var oObj = this.o(sName);
		if(oObj) {
			Element.scrollTo(oObj.domNode());
			console.log("scrolled to", sName, oObj);
		}
	},
	sendToPage: function(sUrl) {
		document.location.href = sUrl;
	},
	toggleDebug: function() {
		var oDiv=$(this.sFormToUseUniqueId + '_debugzone');
		
		if(oDiv && oDiv.style.display == 'none'){
			oDiv.style.display='block';
			
			aDivs = document.getElementsByClassName("ameosformidable_debugcontainer_void");
			for(sKey in aDivs) { aDivs[sKey].className = "ameosformidable_debugcontainer";}
			
			aDivs = document.getElementsByClassName("ameosformidable_debughandler_void");
			for(sKey in aDivs) { aDivs[sKey].className = "ameosformidable_debughandler";}

		} else {
			oDiv.style.display='none';
			
			aDivs = document.getElementsByClassName("ameosformidable_debugcontainer");
			for(sKey in aDivs) { aDivs[sKey].className = "ameosformidable_debugcontainer_void";}
			
			aDivs = document.getElementsByClassName("ameosformidable_debughandler");
			for(sKey in aDivs) { aDivs[sKey].className = "ameosformidable_debughandler_void";}
		}
	},
	toggleBacktrace: function(iNumCall) {

		var oDiv = $(this.sFormToUseUniqueId + '_formidable_call' + iNumCall + '_backtrace');

		if(oDiv && oDiv.style.display == 'none') {
			oDiv.style.display='block';
		} else {
			oDiv.style.display='none';
		}
	},
	debug: function(sMessage) {
		alert(sMessage);
	}
});



Formidable.Classes.RdtBaseClass = Base.extend({
	oForm: null,
	config: {},
	constructor: function(oConfig) {
		this.config = oConfig;
		this.oForm = Formidable.f(this.config.formuniqueid);
	},
	domNode: function() {
		return $(this.config.id);
	},
	replaceData: function(sData) {
		this.clearData();
		this.domNode().value = sData;
	},
	clearData: function(oData) {
		this.domNode().value = "";
	},
	getValue: function() {
		return $F(this.domNode());
	},
	displayBlock: function() {
		this.domNode().style.display="block";
	},
	displayNone: function() {
		this.domNode().style.display="none";
	},
	displayDefault: function() {
		this.domNode().style.display="";
	},
	visible: function() {
		//this.displayBlock();
		this.domNode().style.visibility="visible";
	},
	hidden: function() {
		//this.displayBlock();
		this.domNode().style.visibility="hidden";
	},
	enable: function() {
		Form.enable(this.config.id);
	},
	disable: function() {
		Form.disable(this.config.id);
	},
	toggleDisplay: function() {
		if(this.domNode().style.display=="none") {
			this.displayBlock();
		} else {
			this.displayNone();
		}
	},
	toggleVisibility: function() {
		if(this.domNode().style.visibility=="hidden") {
			this.visible();
		} else {
			this.hidden();
		}
	},
	rebirth: function(oValue) {
		/* none in superclass */
	}
});