/**
 * Class to hold meta data about the form
 * To do: need to add a case value to the switch for password fields
 */
PACIFICFOX.Form = function( arg ) { 
	/**
	 * Private properties
	 */
	var propertyCollection = new Array();
	var formIdentity = formIdentity;

	/**
	 * Public properties
	 */
	this.error = new PACIFICFOX.Error();
	this.obj = document.getElementById( arg.formIdentity );
	this.displayError = ( typeof arg.displayError == "undefined" ? true : arg.displayError );

	/**
	 * Private methods
	 */

	/**
	 * Priviliged methods, may be invoked publicly and may access private variables
	 */
	this.addProperty = function( arg ) {
		// name, friendlyName, required, minimumLength, maximumLength, regularExpression, format, message
		arg[ "form" ] = this.obj;
		// this.obj, name, friendlyName, required, minimumLength, maximumLength, regularExpression, format, message
		var property = new PACIFICFOX.FormProperty( arg );
		propertyCollection.push( property );
		return property;
	}
	this.getProperty = function( name ) {
		var propertyCollection = this.getPropertyCollection();
		for ( var i = 0; i < propertyCollection.length; i++ ) {
			if ( propertyCollection[ i ].getName() == name ) {
				return propertyCollection[ i ];
			}
		}
	}
	this.getPropertyCollection = function( name ) {
		return propertyCollection;
	}
	this.getFormIdentity = function( name ) {
		return formIdentity;
	}
};
/**
 * Public methods
 * validate() starts validating this form
 */
PACIFICFOX.Form.prototype.validate = function() { 
	var propertyCollection = this.getPropertyCollection();
	var errorFieldHasFocus = false;
	// loop over all properties
	for ( var i = 0; i < propertyCollection.length; i++ ) {
		var property = propertyCollection[ i ];
		// get the value from the form object
		property.setValueFromObject();
		// trim the value is required
		if ( property.mustTrim() ) {
			property.trim();
			// also trim the form field value
			var myValue = property.getObjectValue();
			myValue = myValue.replace( /^\s+|\s+$/, "" );
			property.getObject()[ 0 ].value = myValue;
		}
		// perform the right validation based upon the type of object
		// i.e. text, checkbox, radio etc.
		switch ( property.getObjectType() ) {
			case "text": {
				if ( property.isRequired() && !property.hasValue() ) {
					var message = property.getFriendlyName() + " is a required field, please enter a value";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				else {
					// if there is a minimum length specified and the current length is less
					if ( property.hasMinimumLength() ) {
						// if the property is not required but has a value
						if ( ( !property.isRequired() && property.hasValue() && property.getValue().length < property.getMinimumLength() ) || ( property.isRequired() && property.getValue().length < property.getMinimumLength() ) ) {
							var message = property.getFriendlyName() + " requires a minimum characters of " + property.getMinimumLength() + ", current length is " + property.getValue().length;
							this.error.addError( { message:message, type:"minimumLength" } );
							property.error.addError( { message:message, type:"minimumLength" } );
						}
					}
					// if there is a maximum length specified and the current length is greater
					if ( property.hasMaximumLength() && property.getValue().length > property.getMaximumLength() ) {
						var message = property.getFriendlyName() + " allows a maximum characters of " + property.getMaximumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"maximumLength" } );
						property.error.addError( { message:message, type:"maximumLength" } );
					}
				}
				break;
			}
			case "password": {
				if ( property.isRequired() && !property.hasValue() ) {
					var message = property.getFriendlyName() + " is a required field, please enter a value";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				else {
					// if there is a minimum length specified and the current length is less
					if ( property.hasMinimumLength() && property.getValue().length < property.getMinimumLength() ) {
						var message = property.getFriendlyName() + " requires a minimum characters of " + property.getMinimumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"minimumLength" } );
						property.error.addError( { message:message, type:"minimumLength" } );
					}
					// if there is a maximum length specified and the current length is greater
					if ( property.hasMaximumLength() && property.getValue().length > property.getMaximumLength() ) {
						var message = property.getFriendlyName() + " allows a maximum characters of " + property.getMaximumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"maximumLength" } );
						property.error.addError( { message:message, type:"maximumLength" } );
					}
				}
				break;
			}
			case "file": {
				if ( property.isRequired() && !property.hasValue() ) {
					var message = property.getFriendlyName() + " is a required field, please select a file from your computer";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				else {
					// if there is a minimum length specified and the current length is less
					if ( property.hasMinimumLength() && property.getValue().length < property.getMinimumLength() ) {
						var message = property.getFriendlyName() + " requires a minimum characters of " + property.getMinimumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"minimumLength" } );
						property.error.addError( { message:message, type:"minimumLength" } );
					}
					// if there is a maximum length specified and the current length is greater
					if ( property.hasMaximumLength() && property.getValue().length > property.getMaximumLength() ) {
						var message = property.getFriendlyName() + " allows a maximum characters of " + property.getMaximumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"maximumLength" } );
						property.error.addError( { message:message, type:"maximumLength" } );
					}
				}
				break;
			}
			case "select-one": {
				if ( property.isRequired() && !property.hasValue() ) {
					var message = property.getFriendlyName() + " is a required field, please select a option";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				break;
			}
			case "select-multiple": {
				var obj = property.getObject();
				if ( property.isRequired() && obj[ 0 ].selectedIndex == -1 ) {
					var message = property.getFriendlyName() + " is a required field, please select one or more options";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				break;
			}
			case "radio": {
				if ( property.isRequired() && !property.isChecked() ) {
					var message = property.getFriendlyName() + " is a required field, please check a box";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				break;
			}
			case "checkbox": {
				if ( property.isRequired() && !property.isChecked() ) {
					var message = property.getFriendlyName() + " is a required field, please check a box";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				break;
			}
			case "textarea": {
				if ( property.isRequired() && !property.hasValue() ) {
					var message = property.getFriendlyName() + " is a required field, please enter a value";
					this.error.addError( { message:message, type:"required" } );
					property.error.addError( { message:message, type:"required" } );
				}
				else {
					// if there is a minimum length specified and the current length is less
					if ( property.hasMinimumLength() && property.getValue().length < property.getMinimumLength() ) {
						var message = property.getFriendlyName() + " requires a minimum characters of " + property.getMinimumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"minimumLength" } );
						property.error.addError( { message:message, type:"minimumLength" } );
					}
					// if there is a maximum length specified and the current length is greater
					if ( property.hasMaximumLength() && property.getValue().length > property.getMaximumLength() ) {
						var message = property.getFriendlyName() + " allows a maximum characters of " + property.getMaximumLength() + ", current length is " + property.getValue().length;
						this.error.addError( { message:message, type:"maximumLength" } );
						property.error.addError( { message:message, type:"maximumLength" } );
					}
				}
				break;
			}
			default: {
				alert( "An unknown object of type " + property.getObjectType() + " encountered. Object: Form, method: validate" );
				return false;
			}
		} // end switch
		// test if the value contains invalid characters
		if ( property.hasRegularExpression() && property.hasInvalidCharacter() ) {
			var message = property.getFriendlyName() + " contains invalid characters";
			this.error.addError( { message:message, type:"invalidCharacter" } );
			property.error.addError( { message:message, type:"invalidCharacter" } );
			// check if there is an invalid character message to append
			if ( property.hasMessageType( "invalidCharacter" ) ) {
				var message = property.getMessageType( "invalidCharacter" );
				this.error.addError( { message:message } );
				property.error.addError( { message:message } );
			}
		}
		// test if the value is correctly formatted
		if ( property.hasValue() && property.hasFormat() && !property.isCorrectFormat() ) {
			var message = property.getFriendlyName() + " is not correctly formatted";
			this.error.addError( { message:message, type:"invalidFormat" } );
			property.error.addError( { message:message, type:"invalidFormat" } );
			// check if there is an invalid format message to append
			if ( property.hasMessageType( "invalidFormat" ) ) {
				var message = property.getMessageType( "invalidFormat" );
				this.error.addError( { message:message } );
				property.error.addError( { message:message } );
			}
		}
		// test if the value is in valid range
		if ( property.hasRange() ) {
			if ( !property.isValidRange() ) {
				var message = property.getFriendlyName() + " is not a valid range, valid range(s); " + property.getRangeAsString();
				this.error.addError( { message:message, type:"invalidRange" } );
				property.error.addError( { message:message, type:"invalidRange" } );
			}
		}
		// see if any other messages need to be appended
		if ( property.error.hasErrorType( "required" ) && property.hasMessageType( "required" ) ) {
			var message = property.getMessageType( "required" );
			this.error.addError( { message:message } );
			property.error.addError( { message:message } );
			property.error.type[ "required" ] = false;
		}
		if ( property.error.hasErrorType( "minimumLength" ) && property.hasMessageType( "minimumLength" ) ) {
			var message = property.getMessageType( "minimumLength" );
			this.error.addError( { message:message } );
			property.error.addError( { message:message } );
			property.error.type[ "minimumLength" ] = false;
		}
		if ( property.error.hasErrorType( "maximumLength" ) && property.hasMessageType( "maximumLength" ) ) {
			var message = property.getMessageType( "maximumLength" );
			this.error.addError( { message:message } );
			property.error.addError( { message:message } );
			property.error.type[ "maximumLength" ] = false;
		}
		
		// if this property has an error
		if ( property.error.hasError() ) {
			// call any user defined methods
			if ( property.onerror != null ) {
				property.onerror.call( null, property );
			}
			// set focus to the first error field
			if ( !errorFieldHasFocus ) {
				// we cna only move focus to an enabled property
				if ( property.isEnabled() ) {
					property.getObject()[ 0 ].focus();
					errorFieldHasFocus = true;
				}
			}
		}
		else {
			// call any user defined methods
			if ( property.onvalidate != null ) {
				property.onvalidate.call( null, property );
			}
		}
	} // end for loop
	if ( this.error.hasError() ) {
		if ( this.displayError ) {
			alert( "There are some problems with the form, please correct;\n" + this.error.getAsList() );
		}
		return false;
	} 
	else {
		return true;
	}
};
