var Form = new Class({
	Implements: [Options, Events, Log],
	
	options: {
		showLoader: true,
		loaderContainer: null,
		allowIcon: false,
		allowStatus: true,
		allowFileUpload: false,
		formErrorMessage: {
			allow: true,
			container: null,
			allowClose: true,
			heading: null
		},
		formValidMessage: {
			allow: false,
			container: null,
			allowClose: false,
			heading: null
		}
	},
	
	// Variables
	element: null,
	elements: [],
	submitButtons: [],
	resetButtons: [],
	cancelButtons: [],
	errors: [],
	
	// Classes
	formErrorMessage: null,
	formValidMessage: null,
	
	/*
	 * Initialize
	 */
	initialize: function(element, options)
	{
		//this.enableLog();
		//this.disableLog();
		this.log("Form::initialize(" + element + ", " + options + ")");
		
		// Set options
		this.setOptions(options);

		// Set variables
		this.element = element;
		
		// Initialize form error message
		if(this.options.formErrorMessage.allow)
		{
			var container = this.element;
			if(this.options.formErrorMessage.container)
			{
				container = this.options.formErrorMessage.container;
			}
			this.formErrorMessage = new FormErrorMessage(this, container, this.options.formErrorMessage);
		}
		
		// Initialize form valid message
		if(this.options.formValidMessage.allow)
		{
			container = this.element;
			if(this.options.formValidMessage.container)
			{
				container = this.options.formValidMessage.container;
			}
			this.formValidMessage = new FormValidMessage(this, container, this.options.formValidMessage);
		}
		
		// Submit action
		//this.element.addEvent('submit', this.onSubmit.bindWithEvent(this));
		this.element.addEvent('submit', function(event) {
			event.preventDefault();
			this.log("SUBMIT");
			this.onSubmit();
		}.bind(this));

		// Form animation
		this.element.fx = new Fx.Tween(this.element, {
			duration: 500,
			transition: Fx.Transitions.Quad.easeOut,
			property: 'opacity',
			link: 'cancel'
		});
//		this.element.fx.set(0);

		this.element.fx.addEvent('start', function() {

			if(this.element.getStyle('opacity').toInt() == 0)
			{
				this.element.show();
			}
		}.bind(this));

		this.element.fx.addEvent('complete', function() {

			if(this.element.getStyle('opacity').toInt() == 0)
			{
				this.element.hide();
			}
		}.bind(this));
	},
	
	/*
	 * Reset
	 */
	reset: function()
	{
		this.log("Form::reset()");

		// Reset errors
		this.errors = [];

		// Reset form elements
		this.elements.each(function(element) {
			element.reset();
		});
		
		// Reset submit buttons
		this.submitButtons.each(function(element) {
			element.reset();
		});
		
		// Reset reset buttons
		this.resetButtons.each(function(element) {
			element.reset();
		});
		
		// Reset cancel buttons
		this.cancelButtons.each(function(element) {
			element.reset();
		});
		
		// Reset form message
		if(this.formErrorMessage)
		{
			this.formErrorMessage.reset();
		}
		
		// Reset form
		this.element.reset();
	},
	
	/*
	 * Show
	 */
	show: function()
	{
		this.log("Form::show()");
		
//		this.element.fade('in');
		this.element.fx.start(1);
	},
	
	/*
	 * Hide
	 */
	hide: function()
	{
		this.log("Form::hide()");
		
//		this.element.fade('out');
		this.element.fx.start(0);
	},
	
	/*
	 * On submit
	 */
	onSubmit: function()
	{
		this.log("Form::onSubmit()");

		this.fireEvent('onSubmit');

		var validate = this.validate();

		this.showStatus(validate);
		
		if(validate === true)
		{
			if(this.options.formValidMessage.allow)
			{
				this.formValidMessage.hide();
			}

			this.disable();
			this.showLoadState();
			this.submit();
		}
	},
	
	/*
	 * Submit
	 */
	submit: function()
	{
		this.log("Form::submit()");
		
		this.element.submit();
	},
	
	/*
	 * Cancel
	 */
	cancel: function()
	{
		this.log("Form::cancel()");
	},
	
	/*
	 * Validate
	 */
	validate: function()
	{
		this.log("Form::validate()");
		
		// Reset errors
		var errors = new Hash();
		
		var returnValue = true;
		
		// Validate form elements
		this.elements.each(function(element) {
			
			var validate = element.validate();

			if(validate !== true) 
			{
				// Add error
				errors[element.name] = {element: element, message: validate};

				// Set return value
				returnValue = errors;
			}

		}, this);
		
		return returnValue;
	},
	
	/*
	 * Enable
	 */
	enable: function()
	{
		this.log("Form::enable()");
		
		// Enable submit buttons
		this.submitButtons.each(function(element) {
			element.enable();
		});
		
		// Enable reset buttons
		this.resetButtons.each(function(element) {
			element.enable();
		});
	},
	
	/*
	 * Disable
	 */
	disable: function()
	{
		this.log("Form::disable()");
		
		// Disable submit buttons
		this.submitButtons.each(function(element) {
			element.disable();
		});
		
		// Disable reset buttons
		this.resetButtons.each(function(element) {
			element.disable();
		});
	},
	
	/*
	 * Add element
	 */
	addElement: function(element)
	{
		this.log("Form::addElement(" + element + ")");
		
		// Add element
		this.elements.include(element);
	},
	
	/*
	 * Add button
	 */
	addButton: function(button, type)
	{
		this.log("Form::addButton(" + button + ", " + type + ")");
		
		// Add element
		switch(type)
		{
			case 'reset':
				this.resetButtons.include(button);
			break;
			
			case 'cancel':
				this.cancelButtons.include(button);
			break;
			
			default:
				this.submitButtons.include(button);
			break;
		}
	},
	
	/*
	 * Show load state
	 */
	showLoadState: function()
	{
		this.log("Form::showLoadState()");
		
		if(this.options.showLoader)
		{
			this.log("this.options.loaderContainer: " + this.options.loaderContainer);
			
			if(this.options.loaderContainer)
			{
				if(!this.options.loaderContainer.getElement('div.loader'))
				{
					var loader = new Element('div', {'class': 'loader'});
					this.options.loaderContainer.adopt(loader);
				}
			}
		
			this.submitButtons.each(function(submitButton) {
				submitButton.showLoadState();
			}, this);
		}
	},
	
	/*
	 * Hide load state
	 */
	hideLoadState: function()
	{
		this.log("Form::hideLoadState()");
		
		if(this.options.showLoader)
		{
			if(this.options.loaderContainer)
			{
				if(this.options.loaderContainer.getElement('div.loader'))
				{
					$(this.options.loaderContainer).getElement('div.loader').dispose();
				}
			}
			
			this.submitButtons.each(function(submitButton) {
				submitButton.hideLoadState();
			}, this);
		}
	},
	
	/*
	 * Show status
	 */
	showStatus: function(validate)
	{
		this.log("Form::showStatus(" + validate + ")");

		// Error message
		if(this.options.formErrorMessage.allow) 
		{
			if(validate === true)
			{
				// Hide form message
				this.formErrorMessage.hide();
			}
			else if(validate.getLength() > 0)
			{
				this.elements.each(function(element, position) {
					
					if(validate[element.name])
					{
						var error = validate[element.name];

						if(this.errors[element.name])
						{
							this.formErrorMessage.removeMessage(element.name);
						}

						//if(!this.errors[element.name])
						//{
							this.formErrorMessage.addMessage(element.name, position, error.message);
						//}
					}
					else
					{
						if(this.errors[element.name])
						{
							this.formErrorMessage.removeMessage(element.name);
						}
					}
				}, this);
			
				// Show form message
				this.formErrorMessage.show();
				
				// Set errors
				this.errors = validate;
			}
		}
		
		// Form elements
		var generalError = false;
		this.elements.each(function(element) {
			
			var elementError = false;
			
			// Check for error
			if(validate !== true)
			{
				validate.each(function(error) {
					
					if(error.element == element)
					{
						elementError = true;
						generalError = true;
					}
					
				}, this);
			}
			
			// Show element status
			if(this.options.allowStatus) 
			{
				if(!validate)
				{
					element.showStatus(FormElement.NORMAL);
				}
				else if(elementError)
				{
					element.showStatus(FormElement.ERROR);
				}
				else
				{
					element.showStatus(FormElement.VALID);
				}
			}
			
		}, this);

		// Fire error event
		if(generalError) this.fireEvent('onError');
	}
	
});

// Static variables
Form.REGEX_VARCHAR = /^([a-zA-Z0-9\ ]{2,255})+$/;
Form.REGEX_TEXT = /^([\W\w\s]{2,1000})+$/;
Form.REGEX_NAME = /^([\W\w\s]{2,50})+$/;
Form.REGEX_EMAIL = /^([a-zA-Z0-9_\.\-\+%])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
Form.REGEX_PASSWORD = /^([a-zA-Z0-9]{6,15})+$/;
Form.REGEX_PHONE = /(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9,11}$|[0-9\-\s]{10,15}$)/;
//Form.REGEX_PHONE = /(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\-\s]{10}$)/;
//Form.REGEX_GENDER = /(f|m)?/;
Form.REGEX_GENDER = /^(f|m)+$/;
Form.REGEX_URL = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
Form.REGEX_YOUTUBE_VIDEO = /^http:\/\/(?:www\.)?youtube.com\/watch\?(?=.*v=\w+)(?:\S+)?$/;
Form.REGEX_POSTAL = /^([0-9]{4}[\ ]{0,1}[a-zA-Z]{2})+$/;
Form.REGEX_HOUSE_NUMBER = /^([\w\-\ ]{1,10})+$/;
Form.REGEX_CITY = /^([\W\w]{2,40})+$/;
Form.REGEX_IMAGE = /^(.*\.(jpg|png|gif))+$/i;
Form.REGEX_WINCODE = /^([0-9]{7})+$/;
Form.REGEX_FORCE_ERROR = /^([a-z]{0})+$/i;
