/**
 * @fileoverview Library for Form and Form Element handling
 * extends the prototype library by Sam Stephenson
 *
 * @author	Gaetan Lauff	<glauff@plansoft.de>
 *
 * @version $Id: lib.form.js 257 2007-03-20 11:41:17Z glauff $
 */
Object.extend( Form, 
{
	/* Overwrite Prototype Function to pass through disabled elements */
	serializeElements: function(elements, getHash) 
	{
    	var data = elements.inject({}, function(result, element) 
    	{
    		if (/*!element.disabled &&*/ element.name) 
    		{
        		var key = element.name, value = $(element).getValue();
	        	
        		if (value != undefined) 
        		{
	          		if (result[key]) 
	          		{
	            		if (result[key].constructor != Array) result[key] = [result[key]];
	            		{
	            			result[key].push(value);
	            		}
	          		}
	          		else 
	          		{
	          			result[key] = value;
	          		}
	        	}
      		}
      	
      		return result;
    	});

   		return getHash ? data : Hash.toQueryString(data);
  	},
  	
	getHidden: function(form) 
	{
	    var elements = Form.getElements($(form));
	    var queryComponents = new Array();
	
	    for (var i = 0; i < elements.length; i++) {
	      var queryComponent = Form.Element.serialize(elements[i]);
	      if (queryComponent)
	        queryComponents.push(queryComponent);
	    }
	
	    return queryComponents;
  	},
  	
	validate: function(form) 
	{
		var form = $(form);
		var elements = Form.getElements(form);
		
    	for (var i = 0; i < elements.length; i++) {
      		var element = elements[i];
      		
      		if ( !Form.Element.required( element ) || !Form.Element.validate( element ) ) {
      			/**
      			gui.enableDialog();
        	
        		if ( tabid = Element.isInTabCtrl( element ) ) {
        			TabCtrl.switchTab( tabid );
        		}
        		*/
      			Field.focus( element );
      			return false;
      		}
    	}
    	
    	return true;
  	},
  	
  	/**
	 * Returns the form index of a given form name
	 * @param	{string}	formName	Form Name
	 * @return	The Form Index of the given form name
	 * @access	public
	 */
	getIdx: function( form )
	{
		if (form == null) {
			formIdx = 0;
		}
	
		if ( document.forms.length == 0 ) {
			return false;
		}
			
		for (var i=0; i < document.forms.length; i++) {
			if (document.forms[i].name == form) {
				formIdx = i;
			}
		}
		
		return formIdx;
	},
	
  	/**
	 * Inserts a new hidden form field for submission into a specific form
	 * @param	{string}	type	Type of Form Field
	 * @param	{string}	name	Name of Form Field
	 * @param	{string}	value	Value of Form Field
	 * @param	{string}	form	Name of Form where to insert the formField (if omitted the first form will be taken)
	 * @returns	The newly created form field, if the field alreadey exists the value is set and the existing field is returned
	 * @access	public
	 */
	insertNew: function (type, name, value, form )
	{
		var idx = Form.getIdx( form );
		var form = document.forms[idx];
		
		if (value == null)
			value = '';
		
		if ( form[name] != null ) {
			form[name].value = value;
			return form[name];
		}
		
		var field = Form.Element.getNewInput( name, value, type );
		form.appendChild( field );
		
		return field;
	},
	
	/**
	 * Inserts a new Hidden Form Field
	 */
	insertHidden: function( name, value, form )
	{
		return Form.insertNew( 'hidden', name, value, form );
	}
});

Object.extend( Form.Element,
{
	validate: function( element )
	{
		var element 	= $(element);
		
		var obj 		= new Object();
		obj.validator 	= '';
		
		var rules 		= Element.getAttributeValue( element, 'validationrules' );
		
		if ( rules )
		{
			var obj 	= Util.getJSObject( rules );
		}

		eval( "var validator = new EasyGUI_" + obj.validator + "Validator( obj );" );
	
		if ( !validator )
		{
			eval( "var validator = new " + obj.validator + "( obj );" );
	
			if ( !validator )
			{
				throw new Error('EasyGUI Form Validator: The validator: ' + obj.validator + ' you indicated on Element: ' + element.id + ' is not implemented !');
			}
		}

		return ( validator.validate( element ) );
	},
	
	required: function( element ) 
	{
		var element = $(element);
		
		if ( !Element.getAttributeValue( element, 'required' ) )
		{
			return true;
		}
			
		var value 	= $F(element);
		var valid = false;
		
		var rules 		= Element.getAttributeValue( element, 'validationrules' );
		
		if ( rules )
		{
			var obj 	= Util.getJSObject( rules );
			var custommsg = dialog.getMessage( obj.messages['required'] );
		} 
		else 
		{
			var custommsg = dialog.getMessage( Element.getAttributeValue(element, 'validationerrormsg', '') );			
		}
		
		switch ( element.type ) {	
			case 'checkbox':
				valid = element.checked;
				defaultmsg 	= element.id + " is required to be checked !";
				break;
				
			case 'select-one':
				valid = (element.selectedIndex != 0);
				defaultmsg	= element.id + " You have to make a selection !";
				break;
				
			case 'select-multiple':
				var selectallitems = Element.getAttributeValue( element, 'selectallitems' );
				
				if ( selectallitems ) 
				{
					valid = ( element.options.length > 0 );
				} 
				else 
				{
					valid = ( element.selectedIndex != -1);
				}
				
				defaultmsg = element.id + " You have to make at least one selection !";
				break;
				
			default:
				valid = ( value != '' );
				defaultmsg 	= element.id + " is a required field !";
				break;
		}
		
		if (!valid) 
		{
			var msg = ( custommsg == '' ) ? defaultmsg : custommsg;
			alert( msg );
		}
		
		return valid;
	},
	
	/**
	 * Sets value of a Form Field for submission
	 * @param	{string}	fieldName
	 * @param	{string}	fieldValue
	 * @param	{string}	formName	Name of form in which the value should be set. If omitted the first form in the document tree will be taken.
	 * @returns	void
	 * @throws 	EasyGUI Error
	 * @access	public
	 */
	setValue: function(field, value, form)
	{
		try 
		{
			if (form == null)
			{
				form = 0;
			}
		
			var form = document.forms[form];
	
			if (form[field] != null)
			{
				form[field].value = value;
			}
		} 
		catch (e) 
		{
			if (e instanceof Error)
			{
				throw new Error('Form::setValue(): ' + e.name + ' ' + e.message);
			}
		}
	},
	
	/**
	 * Creates a new input field
	 * @param	{string}	fieldName	Name of input field
	 * @param	{string}	fieldValue	Value of input field
	 * @param	{string}	fieldType	Type of input field (hidden, radio, text, checkbox)
	 * @returns	The created DOM Object
	 * @access	public
	 */
	getNewInput: function( name, value, type )
	{
		switch ( type.toLowerCase() ) 
		{
			case 'submit':
			case 'hidden':
			case 'password':
			case 'text':
			case 'checkbox':
			case 'radio':
				break;
				
			default:
				type = 'text';
				break;
		}
		
		try 
		{
			var field 	= document.createElement('input');
		
			field.type 	= type;
			field.id	= name;
			field.name	= name;
			field.value	= value;
		
			return field;
		} 
		catch (e) 
		{
			if (e instanceof Error)
			{
				throw new Error('Form::getNewInput(): ' + e.name + ' ' + e.message);
			}
		}
	},
	
	/**
	 * Checks if a form element value is an empty string or null
	 * @param	{object}	element	DOM Element (Form Element)
	 * @returns	True if the value is set to empty string or null, false otherwise.
	 * @access	public
	 */
	isEmpty: function( element )
	{
		var element = $(element);
		var value 	= $F(element);
		
		return ( value == '' || value == null );
	},

	
	disable: function( element ) 
	{
		$(element).disabled = 'true';
	},
	
	enable: function( element ) 
	{
		$(element).disabled = '';
	}
});

Object.extend( Form.Element.Serializers, 
{
	inputSelector: function(element) 
	{
		if (element.checked) 
		{
			return ( element.value == 'on' || element.value == '' ) ? 'true' : element.value;
		}
			
		return (element.type.toLowerCase() == 'radio') ? "" : 'false';
	},
	
	selectMany: function(element) 
	{
		var value = [];
		
		var addremove = element.getAttribute('addremove');
		var selectall = element.getAttribute('selectallitems');
		var selected  = false;
		
		if ( addremove || selectall ) 
		{
			selected = true;
			for (var i = 0; i < element.length; i++) 
			{
				var opt = element.options[i];
				var optValue = opt.value;
				
				if ( !optValue && !('value' in opt ) )
				{
					optValue = opt.text;
				}
					
				value.push(optValue);
			}
		} 
		else 
		{
			var options = [];
			for (var i = 0; i < element.length; i++) 
			{
				var opt = element.options[i];
				
				if (opt.selected) 
				{
					selected = true;
					var optValue = opt.value;
					
					if (!optValue && !('value' in opt)) 
					{
						optValue = opt.text;
					}
						
					options.push(optValue);
				}
			}
			
			value.push(options.join('|'));
		}
		
		return (selected) ? value : [''];
	}
});