	
	function ErrorManager() {
		this._sErrors = new titan.util.Struct();
	}
	ErrorManager.prototype.addError = function(_field,_message) {
		this._sErrors.structInsert(_field,_message);
	}
	ErrorManager.prototype.getErrors = function() {
		return(this._sErrors);
	}
	ErrorManager.prototype.getErrorList = function() {
		return this._sErrors.getItems().keys();
	}
	ErrorManager.prototype.getErrorCount = function() {
		return(this._sErrors.structCount())
	}
	ErrorManager.prototype.toString = function() {

		var _sErrors = '';
		var _keys = this.getErrorList();

		for(i=0;i<_keys.length;i++){			
			_sErrors = _sErrors + ( '\n'+ this.getErrors().structFind(_keys[i]) );		
		}

		return _sErrors;
	}
	
	
	function FieldManager(_element) {
		
		this.setValue(''); // for new elements, start with a blank value
		this.setID(_element.id);
		this.setName(_element.name);
		this.setType(_element.type);  // needs to be set before appendValue()		
		this.setMaxLength(_element.maxLength);
		this.setLabel(_element.getAttribute('label')? _element.getAttribute('label'): this.getName());
		this.setRequired(_element.getAttribute('required')? _element.getAttribute('required'): false);
		this.setValidation(_element.getAttribute('validation')? _element.getAttribute('validation'): 'none');
		
		// seperate functions for different types?
		//alert(_element.value);
		
		switch ( this.getType() ) {

			/*
			case 'select-multiple':
				alert('select-multiple');
				alert(_element.value);
				break;
			*/

			case 'radio':
				if ( _element.checked ) {
					this.appendValue($F(_element));
				}
				break;

			case 'checkbox':
				//alert('checkbox');
				if ( _element.checked ) {
					this.appendValue($F(_element));
				}
				break;

			default:
				//alert(_element.value);
				this.appendValue($F(_element));
				break;
		}
	}
	FieldManager.prototype.setID = function(_id) { this._id = _id; }
	FieldManager.prototype.getID = function() { return '_id' in this? this._id: ''; }	
	FieldManager.prototype.setName = function(_name) { this._name = _name; }
	FieldManager.prototype.getName = function() { return '_name' in this? this._name: ''; }	
	FieldManager.prototype.setLabel = function(_label) { this._label = _label; }
	FieldManager.prototype.getLabel = function() { return '_label' in this? this._label: ''; }	
	FieldManager.prototype.setType = function(_type) { this._type = _type; }	
	FieldManager.prototype.getType = function() { return '_type' in this? this._type: ''; }	
	FieldManager.prototype.setRequired = function(_required) { this._required = _required; }
	FieldManager.prototype.getRequired = function() { return '_required' in this? this._required: ''; }	
	FieldManager.prototype.setValidation = function(_validation) { this._validation = _validation; }
	FieldManager.prototype.getValidation = function() { return '_validation' in this? this._validation: ''; }	
	FieldManager.prototype.setError = function(_error) { this._error = _error; }
	FieldManager.prototype.getError = function() { return '_error' in this? this._error: ''; }	
	FieldManager.prototype.setValue = function(_value) { this._value = _value; }
	FieldManager.prototype.appendValue = function(_value) {
		if (_value.length) {
			var _delim = this.getValue().length? ',': '';
			this.setValue( this.getValue() + _delim + _value ); 
		}
	}
	FieldManager.prototype.getValue = function() { return '_value' in this? this._value: ''; }	
	FieldManager.prototype.setMaxLength = function(_maxlength) { this._maxlength = _maxlength; }
	FieldManager.prototype.getMaxLength = function() { return '_maxlength' in this? this._maxlength: ''; }
	FieldManager.prototype.toString = function() {
		var sField = 'Field:';
		sField = sField + ' id=' + this.getName();
		sField = sField + ' || type=' + this.getType();
		sField = sField + ' || required=' + this.getRequired();
		sField = sField + ' || value=' + this.getValue();		
		sField = sField + ' || validation=' + this.getValidation();
		return sField;
	}
	
	
	function FormManager() {
		this._oErrorManager = new ErrorManager();
		this._sFields = new titan.util.Struct();
		this._aSubmitElements = new Array();
	}
	
	
	
	FormManager.prototype.setElement = function(_element) {
		
		// will need to do some logic based on if it exists and what type it is
		
		//alert(_sFields.structFind(_element.id));
		
		
		
		if (this._sFields.structFind(_element.id)) {
			
			var _field = this._sFields.structFind(_element.id);
			
			//alert('it is there: '+_element.id);
			
			//alert(_field.getValue());
			
			if(_element.type == 'hidden'){
				// if this is a hidden field and already exists in the fields struct
				// then we can assume it has the field meta data on it (required, validation, etc.
				// make sure to append any values that exist on the hidden field
				_field.setValidation(_element.getAttribute('validation')? true: false);
				_field.setRequired(_element.getAttribute('required')? _element.getAttribute('required'): false);
				_field.setLabel(_element.getAttribute('label')? _element.getAttribute('label'): _element.getAttribute('name'));
				_field.appendValue(_element.value);
			}
			else {
				
				if ( (_element.type == 'radio' || _element.type == 'checkbox') ) {
					_field.setType(_element.type);					
					if ( _element.checked ) {
						_field.appendValue(_element.value);
					}
				}
				else {
					if (_element.type == 'submit') { 
						_element = $(_element);
						_element.disable();
						this.addSubmitElement(_element);
					}
					_field.appendValue(_element.value);
				}
			}
			
			
			
		}
		else {			
			var oFieldManager = new FieldManager(_element);
			this._sFields.structInsert( _element.id, oFieldManager );
		}

		/*		
		var oFieldManager = new FieldManager(_element);
		this._sFields.structInsert( _element.id, oFieldManager );
		*/
		
	}
	FormManager.prototype.getFieldList = function() {
		return this._sFields.getItems().keys();
	}
	FormManager.prototype.getFields = function() {
		return this._sFields;
	}
	FormManager.prototype.getErrorManager = function() {
		return this._oErrorManager;
	}
	FormManager.prototype.hasErrors = function() {
		if ( this.getErrorManager().getErrorCount() > 0 ) {			
			return true;
		}
		else {
			return false;
		}
	}
	
	 FormManager.prototype.addSubmitElement = function(_element) {
		var _next = this._aSubmitElements.length;
		this._aSubmitElements[_next] = _element;
	}
		
	FormManager.prototype.enableSubmit = function(){
		var _submitElements = $A(this._aSubmitElements); 
		_submitElements.each( function(_submitElement) { 
		_submitElement.enable(); 
		}); 
	}
	
	
	FormManager.prototype.validateFields = function() {
		
		var _sForm = '';
		var _keys = this.getFieldList();

		for(i=0;i<_keys.length;i++){

			var _field = this.getFields().structFind(_keys[i]);

			//alert(_field.getLabel() + _field.getRequired());

			if ( _field.getRequired() == 'true' && _field.getValue() == '' ) {
				this.getErrorManager().addError('r_' + _keys[i],_field.getLabel() + ' is a required field.');
			}
			
			//alert(_field.getValue().length + ':' + _field.getValue());
			
			if (_field.getValue() != '') {
			
			switch ( _field.getValidation() ) {

				case 'date':
					if ( !titan.util.isSimpleDate(_field.getValue()) ) {
						this.getErrorManager().addError( 'v_' + _keys[i], _field.getLabel() + ' must be formatted as a valid date.' );
					}
				break;

				case 'datetime':
					if ( !titan.util.isDateTime(_field.getValue()) ) {
						this.getErrorManager().addError( 'v_' + _keys[i], _field.getLabel() + ' must be formatted as a valid date/time value.' );
					}
				break;
				
				case 'email':
					if ( _field.getValue() != '' && !titan.util.isEmail(_field.getValue()) ) {
						this.getErrorManager().addError( 'v_' + _keys[i], _field.getLabel() + ' must be a valid email.' );
					}
				break;
				
				case 'integer':
					if ( _field.getValue() != '' && !titan.util.isInteger(_field.getValue()) ) {
						this.getErrorManager().addError( 'v_' + _keys[i], _field.getLabel() + ' must be an integer.' );
					}
				break;

					case 'numeric':
						if (_field.getValue() != '' && !titan.util.isNumeric(_field.getValue())) {
							this.getErrorManager().addError('v_' + _keys[i], _field.getLabel() + ' must be a numeric value.');
						}
						break;
						
				default:
				
				break;
			}
			
			}
				
			
			
		}
	}
	
	FormManager.prototype.toString = function() {
		
		var _sForm = '';
		var _keys = this.getFieldList();

		for(i=0;i<_keys.length;i++){
			_sForm = _sForm + ( '\n'+ this.getFields().structFind(_keys[i]) );
		}
		
		return _sForm;	
	}
	
	
	function validateForm(_form) {
	
		var oFormManager = new FormManager();

		for	(var i = 0; i < _form.length; i++) {
			var _e = _form.elements[i];
			oFormManager.setElement(_e);
		}

		oFormManager.validateFields();
		
		if ( oFormManager.hasErrors() ) {
			alert(oFormManager.getErrorManager());
			
			// renable submit buttons
			oFormManager.enableSubmit();
			
			return false;
		}
		
		return true;
	}

		
