/**
 * Fornece métodos para ações realizados em campos do tipo GroupedList.
 * 
 * @author Renan de Lima Barbosa <renandelima@gmail.com>
 * @author Renê de Lima Barbosa <renedelima@gmail.com>
 */
var GroupedList = function(){
	
	this.optgroups = {};
	this.options = {};
	
	this.createList = function( boolOptgroup , id )
	{
		if( boolOptgroup )
		{
			var optgroups = document.getElementById( id ).getElementsByTagName("OPTGROUP");
			var	optLength = optgroups.length;
		
			if( !this.optgroups[id] )
			{
				this.optgroups[id] = [];
				
				for( var j = 0; j < optLength; j++ ){
	
					this.optgroups[id].push( { label: optgroups[j].label , options: [] } );
					
					var options = optgroups[j].childNodes;
					
					for( var i = 0; i < options.length; i++ ){
						this.optgroups[id][ (this.optgroups[id].length-1) ].options.push( { value: options[i].value , text: options[i].text } );
					}
				}
			}
		}
		else
		{
			var options = document.getElementById( id ).options;
			var	optLength = options.length;
			
			if( !this.options[id] )
			{
				this.options[id] = [];
				
				for( var i = 0; i < optLength; i++ )
				{
					this.options[id].push( { value: options[i].value , text: options[i].text } );
				}
			}
		}
	}
	
	/**
	 * Move os itens selecionados de um select para outro.
	 * 
	 * @param object select origem
	 * @param object select destino
	 * @param string ordem a ser aplicado ao select destino
	 * @return void
	 */
	this.moveSelected = function( oFrom, oTo, sOrder )
	{
		var optgroups = oTo.getElementsByTagName("OPTGROUP");
		
		if( optgroups.length )
		{
			this.createList( true , oFrom.id );
			this.createList( true , oTo.id );
					
			for( var i = 0; i < oFrom.options.length; i++ )
			{ 
				if ( oFrom.options[i].selected == true )
				{
					for( var j = 0; j < optgroups.length; j++)
					{
						if( optgroups[j].label == oFrom.options[i].parentNode.label )
						{
							var option = document.createElement("OPTION");
							option.innerHTML = oFrom.options[i].text;
							option.value = oFrom.options[i].value;
					
							optgroups[j].appendChild( option );
							//optgroups[j].appendChild( new Option( oFrom.options[i].text, oFrom.options[i].value, false, false ) );
							
							this.update( oFrom.id , oTo.id , { value: oFrom.options[i].value, text: oFrom.options[i].text } , j , true );
							oFrom.options[i] = null;
							j = optgroups.length;
						}
					}
				}
			}
		}
		else
		{
			this.createList( false , oFrom.id );
			this.createList( false , oTo.id );
			
			for( var i = 0; i < oFrom.options.length; i++ )
			{ 
				if ( oFrom.options[i].selected == true )
				{
					oTo.options[oTo.options.length] = new Option( oFrom.options[i].text, oFrom.options[i].value, false, false );
					this.update( oFrom.id , oTo.id , { value: oFrom.options[i].value, text: oFrom.options[i].text } );
					oFrom.options[i] = null;
				}
			}
		}
	}
	
	/**
	 * Move todos os itens de um select para outro.
	 * 
	 * @param object select origem
	 * @param object select destino
	 * @return void
	 */
	this.moveAll = function( oFrom , oTo )
	{
		var optgroups = oTo.getElementsByTagName("OPTGROUP");
		
		if( optgroups.length )
		{
			
			this.createList( true , oFrom.id );
			this.createList( true , oTo.id );
			while ( oFrom.options.length > 0 )
			{
				for( var j = 0; j < optgroups.length; j++)
				{
					if( optgroups[j].label == oFrom.options[0].parentNode.label ){
						
						var option = document.createElement("OPTION");
						option.innerHTML = oFrom.options[0].text;
						option.value = oFrom.options[0].value;
					
						optgroups[j].appendChild( option );
					
						//optgroups[j].appendChild( new Option( oFrom.options[0].text, oFrom.options[0].value, false, false ) );
						this.update( oFrom.id , oTo.id , { value: oFrom.options[0].value, text: oFrom.options[0].text } , j , true );
						oFrom.options[0] = null;
						j = optgroups.length;
					}
				}
			}
		}
		else
		{
			this.createList( false , oFrom.id );
			this.createList( false , oTo.id );
			
			while ( oFrom.options.length > 0 )
			{
				oTo.options[oTo.options.length] = new Option( oFrom.options[0].text, oFrom.options[0].value, false, false );
				this.update( oFrom.id , oTo.id , { value: oFrom.options[0].value, text: oFrom.options[0].text } );
				oFrom.options[0] = null;	
			}
		}
	}
	
	this.update = function( from , to , option , position , boolOptgroup )
	{
		if( boolOptgroup )
		{
			this.optgroups[to][position].options.push( option );
			
			var	length = this.optgroups[from][position].options.length;
				
			for( var i = length-1; i > -1 ; i-- )
			{
				if( this.optgroups[from][position].options[i].value == option.value )
				{
					this.optgroups[from][position].options.splice( i , 1 );
				}
			}
		}
		else
		{
			this.options[to].push( option );
			var length = this.options[from].length;
			
			for( var i = length-1; i > -1 ; i-- )
			{
				if( this.options[from][i].value == option.value )
				{
					this.options[from].splice( i , 1 );
				}
			}
		}
	}
	
	this.selection = function( id , value )
	{
		var select = document.getElementById( id );
		var length = select.options.length;
		
		if ( length == 0 )
			return;
		
		this.filter( id , "" );
		
		for( var i = 0; i < length; i++ )
		{
	 		select.options[i].selected = value;
		}
	}
	
	this.selectAll = function( id )
	{
		this.selection( id , true );
		this.optgroups = {};
		this.options = {};
	}
		
	this.deSelectAll = function( id )
	{
		this.selection( id , false );
		this.optgroups = {};
		this.options = {};
	}
	
	this.filter = function( id , value )
	{
		if( document.getElementById( id ).getElementsByTagName("OPTGROUP").length )
		{
			this.createList( true , id );
			this.filterOptgroup( id , value );
		}
		else
		{
			this.createList( false , id );
			this.filterOption( id , value );
		}
	}
	
	this.filterOptgroup = function( id , value )
	{
		var optgroups = document.getElementById( id ).getElementsByTagName("OPTGROUP");
		var	optLength = optgroups.length;
		
		for( var i = optLength-1; i > -1  ; i-- )
		{
			optgroups[i].parentNode.removeChild( optgroups[i] );
		}
		
		//Return to "select" the started values and create de array of options filtereds
		for( var i = 0; i < this.optgroups[id].length; i++ )
		{
			var optgroup = document.createElement("OPTGROUP");
			optgroup.label = this.optgroups[id][i].label;
			
			for( var j = 0; j < this.optgroups[id][i].options.length; j++ )
			{
				if( this.optgroups[id][i].options[j].text.toUpperCase().indexOf( value.toUpperCase() ) > -1 || !value.length )
				{
					var option = document.createElement("OPTION");
					option.innerHTML = this.optgroups[id][i].options[j].text;
					option.value = this.optgroups[id][i].options[j].value;
					
					optgroup.appendChild( option );
				}
			}
			document.getElementById( id ).appendChild( optgroup );
		}	
	}
	
	this.filterOption = function( id , value )
	{
		var options = document.getElementById( id ).options;
		var	optLength = options.length;
		
		for( var i = optLength-1; i > -1  ; i-- )
		{
			options[i].parentNode.removeChild( options[i] );
		}
		
		//Return to "select" the started values and create de array of options filtereds
		for( var i = 0; i < this.options[id].length; i++ )
		{
			if( this.options[id][i].text.toUpperCase().indexOf( value.toUpperCase() ) > -1 || !value.length )
			{
				var option = new Option( this.options[id][i].text , this.options[id][i].value , false, false );
				document.getElementById( id )[document.getElementById( id ).options.length] = option;
			}
		}	
	}
	return this;
		
};
