/**
 * @author Nick Bartkowiak <nick@smallworldlabs.com>
 * @copyight Copyright (c) 2008 Small World Labs, Inc.
 */

/**
 * Class that handles the front-end processing of each individual form component.
 */
var SitePageFormHandler = Class.create (
{
	/**
	 * Initializes the class by prepopulating the class's global variables.
	 *
	 * @param string form The name of the form that the class is to interact with.
	 *
	 * @uses SitePageFormHandler::url
	 * @uses SitePageFormHandler::form
	 * @uses SitePageFormHandler::is_valid
	 */
	initialize: function(form)
	{
		/**
		 * @var string The url that the form handler will send the AJAX calls to. This is always the URL of the form itself.
		 */
		this.url = window.location.href;

		/**
		 * @var string The name of the form that is being interacted with.
		 */
		this.form = form;

		/**
		 * @var boolean The validity of the form. Default is set to true, but is altered to false if the form fails to validate.
		 */
		this.is_valid = true;

		/**
		 * @var boolean Tells the form whether or not to redirect the user after a successful processing.
		 */
        this.redirect = true;
	},

	/**
	 * TinyMCE has a specialized way of processing a form when a form element of the type "submit" is clicked. Since we are bypassing that submission process in lieu of an AJAX submission process controlled by this object, we have to use this method to run these TinyMCE commands manually. This was tricky to find and I think tinyMCE was trying to be clever, but ended up just making it more difficult to produce dynamic, AJAX powered forms.
	 *
	 * @uses tinyMCE::execCommand()
	 * @uses tinyMCE::triggerSave()
	 */
	parseTinyMCE: function()
	{
		tinyMCE.execCommand('mceRemoveControl', true, 'MessageContent');
		tinyMCE.triggerSave();
	},

	/**
	 * This private method simply alters the interface to properly message to the user what fields are invalid and what must be done to validate them. It will also return valid fields to their valid visual state.
	 *
	 * @param array fields Array of all the valid and invalid fields associated with the form.
	 */
	_updateFields: function(fields)
	{
		if (fields['invalid'].length > 0)
		{
			fields['invalid'].each(function(o, i)
			{
				if ($(o))
				{
					if ($(o).type !== undefined && $(o).type != 'hidden')
					{
						$(o+"_error").show();
						$(o+"_highlight").addClassName('invalid');
					}
				}
				else
				{
					checkRadio = $$('input[name="'+o+'"]');
					if (checkRadio.length == 0)
					{
						checkRadio = $$('input[name="'+o+'[]"]');
					}
					if (checkRadio.length > 0)
					{
						checkRadio.each(function(p, k)
						{
							$(o+"_error").show();
							$(o+"_highlight").addClassName('invalid');
						});
					}
				}
			});
		}

		if (fields['valid'].length > 0)
		{
			fields['valid'].each(function(o, i)
			{
				if ($(o))
				{
					if ($(o).type !== undefined && $(o).type !== 'hidden')
					{
						$(o+"_error").hide();
						$(o+"_highlight").removeClassName('invalid');
					}
				}
				else
				{
					checkRadio = $$('input[name="'+o+'"]');
					if (checkRadio.length == 0)
					{
						checkRadio = $$('input[name="'+o+'[]"]');
					}
					if (checkRadio.length > 0)
					{
						checkRadio.each(function(p, k)
						{
							$(o+"_error").hide();
							$(o+"_highlight").removeClassName('invalid');
						});
					}
				}
			});
		}
	},

	/**
	 * Using a list of valid and invalid form fields, this private method will alter the validity of the submission to false if there are invalid fields present. It will also run the _updateFields method to alter the user interface accordingly.
	 *
	 * @param array fields Array of all the valid and invalid fields associated with the form.
	 *
	 * @uses SitePageFormHandler::is_valid
	 * @uses SitePageFormHandler::_updateFields
	 */
	_processValidation: function(fields)
	{
		if (fields['invalid'].length > 0)
		{
			this.is_valid = false;
		}

		this._updateFields(fields);
	},

	/**
	 * The "submit" method has two main functions: to test the form for validity and to post the form for processing. It also has lighter third function, which will both validate and upon successful validation, go ahead and post the form for processing. It essentially combines the first two main functions.
	 *
	 * Depending on which mode is called, this method will send an AJAX call to either validate or process the form. "Validate" mode will process the validation and nothing more. It will change the global validation variable to true or false and alter the user interface. "Process" mode will will simply post the form and redirect the user to the success page. "Validate and Process" mode will process the validation and upon a successful validation, will call the onCompleteSubmit function, which is extended in the template, which will rerun the "submit" method in "Process" mode.
	 *
	 * @param string mode The form of processing that needs to be done: "validate", "process", or "validate_and_process".
	 *
	 * @uses SitePageFormHandler::form
	 * @uses SitePageFormHandler::url
	 * @uses SitePageFormHandler::_processValidation
	 * @uses SitePageFormHandler::onCompleteValidate
	 * @uses SitePageFormHandler::onCompleteSubmit
	 */
	submit: function(mode)
	{
		var _this = this;
		var ajax_mode = mode == 'validate_and_process' ? 'validate' : mode;
		var obj = $(this.form+'_form').serialize(true);
		var par = Object.toJSON(obj);

		var myAjax = new Ajax.Request(this.url,
		{
			method:'post',
			parameters:
			{
				'form': this.form,
				'mode': ajax_mode,
				'pars': par
			},
			onComplete: function(response)
			{
				var fields = response.headerJSON;
				switch (mode)
				{
				case 'validate' :
					_this._processValidation(fields);
					_this.onCompleteValidate(i);
					break;
				case 'process' :
					if (_this.redirect)
					{
						window.location = response.headerJSON;
					}
					break;
				case 'validate_and_process' :
					_this._processValidation(fields);
					_this.onCompleteSubmit();
					break;
				}
			}
		});
	}

});
