var FormElement = new Class({
	Implements: [Options, Events, Log],
	
	options: {
		autoValidate: false,
		allowIcon: false,
		allowStatus: true,
		hintText: null,
		optional: false,
		submitOnEnter: true
	},
	
	// Variables
	form: null,
	name: null,
	element: null,
	label: null,
	icon: null,
	hint: null,
	validations: [],
	matches: [],

	
	/*
	 * Initialize
	 */
	initialize: function(form, name, options)
	{
		//this.enableLog();
		this.disableLog();
		this.log("FormElement::initialize(" + form + ", " + name + ", " + options + ")");
		
		this.log("debug formElement 1");
		
		// Set options
		this.setOptions(options);
		
		this.log("debug formElement 2");
		
		// Set variable
		this.form = form;
		this.name = name;
		this.element = this.form.element.getElement('[name=' + this.name + ']');
		
		this.log("debug formElement 3");
		
		if(this.element.getParent().getElement('label'))
		{
			this.label = this.element.getParent().getElement('label');
		}
		
		this.log("debug formElement 4");
		
		if(this.options.allowIcon)
		{
			this.icon = new FormElementIcon(this.form, this.element.getParent());
		}
		
		this.log("debug formElement 5");
		
		if(this.options.hintText)
		{
			this.log("this.element: "+ this.element.get('class'));
			this.log("this.element.getParent(): "+ this.element.getParent());
			this.log("this.element.getParent(): "+ this.element.getParent().get('class'));
			this.log("this.options.hintText: "+ this.options.hintText);
			
			this.hint = new FormElementHint(this.element, this.element.getParent(), this.options.hintText);
		}
		
		this.log("debug formElement 6");
		
		// On focus
		this.element.addEvent('focus', function(event) {
			this.hideStatus();

			this.log("this.options.submitOnEnter: " + this.options.submitOnEnter);
			if(this.element.getProperty('type') != 'textarea' && this.options.submitOnEnter)
			{
				this.element.addEvent('keydown', function(event) {
					if (event.key == 'enter') this.form.element.fireEvent('submit', [event]);
				}.bind(this));
			}

		}.bind(this));
		
		this.log("debug formElement 7");

		// On blur
		this.element.addEvent('blur', function(event) {
			this.element.removeEvents('keydown');
		}.bind(this));
		
		this.log("debug formElement 8");
		
		this.element.addEvent('click', function(event) {
			this.hideStatus();
		}.bind(this));

		this.log("debug formElement 9");
		
		if(this.element.getProperty('type') == 'radio')
		{
			var radioButtons = $(document.body).getElements('[name=' + this.name + ']');

			radioButtons.each(function(radioButton) {

				var id = radioButton.get('id');
				var label = $(document.body).getElement('label[for=' + id + ']');

				this.log("label: "+ label);
				
				label.addEvent('click', function(event) {

					this.hideStatus();
				}.bind(this));
			}.bind(this));
		}
		
		this.log("debug formElement 10");
	},
	
	/*
	 * Reset
	 */
	reset: function()
	{
		this.log("FormElement::reset()");
		
		this.enable();
		this.hideStatus();
		
		// Reset icon
		if(this.icon)
		{
			this.icon.reset();
		}
		
		// Reset hint
		if(this.hint)
		{
			this.hint.reset();
		}
	},

	/*
	 * Focus
	 */
	focus: function()
	{
		this.log("FormElement::focus()");

		this.log("this.name: "+ this.name);

		this.element.focus();
	},
	
	/*
	 * Validate
	 */
	validate: function()
	{
		this.log("FormElement::validate()");
		
		var input = this.element.value;
		var returnValue = true;

		if(this.element.getProperty('type') == 'radio')
		{
			var radioButtons = $(document.body).getElements('[name=' + this.name + ']');

			input = "";
			var isSet = false;
			radioButtons.each(function(radioButton) {

				var value = radioButton.getProperty('checked');
				this.log("value: " + value);

				if(value && !isSet)
				{
					this.log("radioButton: " + radioButton);
					this.log("radioButton.getProperty('value'): " + radioButton.getProperty('value'));
					this.log("radioButton.get('value'): " + radioButton.get('value'));
					this.log("radioButton.get('id'): " + radioButton.get('id'));
					this.log("radioButton.value: " + radioButton.value);
					isSet = true;
					input = radioButton.getProperty('value');
				}

			}.bind(this));
		}

		this.log("this.name: " + this.name);
		this.log("this.element.getProperty('type'): " + this.element.getProperty('type'));
		this.log("input: " + input);
		
		if(!this.options.optional || (this.options.optional && input.length > 0)) 
		{
			this.validations.each(function(validation) {
			
				if(returnValue === true) 
				{
					if(!input.test(validation.regexp)) 
					{
						returnValue = validation.message;
					}
				}
				
			}, this);

			this.matches.each(function(match) {

				if(returnValue === true)
				{
					if(input !== match.element.element.value)
					{
						returnValue = match.message;
					}
				}

			}, this);
		}
		this.log("returnValue: " + returnValue);

		return returnValue;
	},
	
	/*
	 * Disable
	 */
	disable: function()
	{
		this.log("FormElement::disable()");
		
		this.element.set('disabled', true);
		this.element.addClass('disabled');
		
		// Disable label
		if(this.label)
		{
			this.label.addClass('disabled');
		}
		
		// Disable icon
		if(this.icon)
		{
			this.icon.disable();
		}
		
		// Disable hint
		if(this.hint)
		{
			this.hint.disable();
		}
	},
	
	/*
	 * Enable
	 */
	enable: function()
	{
		this.log("FormElement::enable()");
		
		this.element.set('disabled', false);
		this.element.removeClass('disabled');
		
		// Enable label
		if(this.label)
		{
			this.label.removeClass('disabled');
		}
		
		// Enable icon
		if(this.icon)
		{
			this.icon.enable();
		}
		
		// Enable hint
		if(this.hint)
		{
			this.hint.enable();
		}
	},
	
	/*
	 * Add validation
	 */
	addValidation: function(regexp, message)
	{
		this.log("FormElement::addValidation(" + regexp + ", " + message + ")");
		
		var validation = {regexp: regexp, message: message};
		
		// Add validation
		this.validations.include(validation);

		this.log("this.validations.lenght: " + this.validations.length);
	},

	/*
	 * Remove validation
	 */
	removeValidation: function(regexp)
	{
		this.log("FormElement::removeValidation(" + regexp + ")");

		this.validations.each(function(validation) {
			if(validation.regexp == regexp)
			{
				this.validations.erase(validation);
			}
		}.bind(this));

		this.log("this.validations.lenght: " + this.validations.length);
	},
	
	/*
	 * Remove validation
	 */
	removeValidations: function()
	{
		this.log("FormElement::removeValidations()");
		
		// Remove validations
		this.validations = [];
	},

	/*
	 * Add match
	 */
	addMatch: function(element, message)
	{
		this.log("FormElement::addMatch(" + element + ", " + message + ")");

		var match = {element: element, message: message};

		// Add match
		this.matches.include(match);

		this.log("this.matches.lenght: " + this.matches.length);
	},

	/*
	 * Remove match
	 */
	removeMatch: function(element)
	{
		this.log("FormElement::removeMatch(" + element + ")");

		this.matches.each(function(match) {
			if(match.regexp == element)
			{
				this.matches.erase(match);
			}
		}.bind(this));

		this.log("this.matches.lenght: " + this.matches.length);
	},

	/*
	 * Remove matches
	 */
	removeMatches: function()
	{
		this.log("FormElement::removeMatches()");

		// Remove matches
		this.matches = [];
	},
	
	/*
	 * Show status
	 */
	showStatus: function(status)
	{
		this.log("FormElement::showStatus(" + status + ")");
		
		if(this.options.allowStatus)
		{
			this.hideStatus();
		
			var statusClass = FormElement.STATUSES[status];
			this.element.addClass(statusClass);

			if(this.element.getProperty('type') == 'radio')
			{
				var radioButtons = $(document.body).getElements('[name=' + this.name + ']');

				radioButtons.each(function(radioButton) {
					radioButton.addClass(statusClass);
				}.bind(this));
			}
			
			// Label
			if(this.label)
			{
				this.label.addClass(statusClass);

				if(this.element.getProperty('type') == 'radio')
				{
					radioButtons.each(function(radioButton) {

						var id = radioButton.get('id');
						var label = $(document.body).getElement('label[for=' + id + ']');

						label.addClass(statusClass);
					}.bind(this));
				}
			}
			
			// Hint
			if(this.hint)
			{
				this.hint.showStatus(statusClass);
			}
		}
		
		// Show icon status
		if(this.options.allowIcon) 
		{
			this.icon.showStatus(status);
		}
	},
	
	/*
	 * Hide status
	 */
	hideStatus: function()
	{
		this.log("FormElement::hideStatus()");

		this.log("this: "+ this);
		this.log("this.options: "+ this.options);
		this.log("this.options.allowStatus: "+ this.options.allowStatus);

		if(this.options.allowStatus) 
		{
			FormElement.STATUSES.each(function(status) {
				
				if(this.element.hasClass(status))
				{
					this.element.removeClass(status);

					if(this.element.getProperty('type') == 'radio')
					{
						var radioButtons = $(document.body).getElements('[name=' + this.name + ']');

						radioButtons.each(function(radioButton) {
							radioButton.removeClass(status);
						}.bind(this));
					}

					// Label
					if(this.label)
					{
						this.label.removeClass(status);

						if(this.element.getProperty('type') == 'radio')
						{
							radioButtons.each(function(radioButton) {

								var id = radioButton.get('id');
								var label = $(document.body).getElement('label[for=' + id + ']');

								label.removeClass(status);
							}.bind(this));
						}
					}
					
					// Hint
					if(this.hint)
					{
						this.hint.hideStatus();
					}
				}
				
			}, this);
		}
		
		// Hide icon status
		if(this.options.allowIcon) 
		{
			this.icon.hideStatus();
		}
	}
	
});

// Static variables
FormElement.NORMAL = 0;
FormElement.VALID = 1;
FormElement.WARNING = 2;
FormElement.ERROR = 3;

FormElement.STATUSES = [];
FormElement.STATUSES[FormElement.VALID] = 'valid';
FormElement.STATUSES[FormElement.WARNING] = 'warning';
FormElement.STATUSES[FormElement.ERROR] = 'error';
