 /*																																										*/
if( typeof pln == 'undefined' || typeof nvi == 'undefined' ){

	/**
	 @requires pln.js
	 @requires nvi.core.js
	 @requires class.nvi.basic.panel.js
	 @description if not found, alert the developers and do nothing;
	*/
	if( typeof pln == 'undefined' ) alert( "This file required the PLN Javascript Library ( pln.js ) and it need to be loaded before this file." );
	if( typeof nvi == 'undefined' ) alert( "This file required the NVI CORE ( nvi.core.js ) and it need to be loaded before this file." );
	if( typeof class_nvi_basic_panel == 'undefined' ) alert( "This file required the Class Nvi Basic Panel and it need to be loaded before this file." );

}else{



	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 @name 			Toggle Control Class
	 @version		1.00
	*/
	function class_toggle_control(  ){
		
		var _host = this ;		
		var _event = 'click' ;
		var _constant = {
			OPEN : { state : 'OPEN' , css : 'toggle_open' } ,
			CLOSE : { state : 'CLOSE' ,	css : 'toggle_close' } ,
			PARTIALLY_OPEN : { state : 'PARTIALLY_OPEN' , css : 'toggle_partially_open' } ,
			DEACTIVATED : { state : 'DEACTIVATED' , css : 'toggle_deactivated' }
		} ;
		var _state = _constant.CLOSE.state ;
		var _localCollection = { views : {} , group : {} } ;
		var _default = false ;
		var _displayParent = true ;
		
		this.__constructor = function( $id ){
			__super.__constructor( $id ) ;
		}	
		
		this.toString = function(){ return "Nvi Toggle Control Class" ; }	
		
		this.initialize = function(){

			// Do i have child in one of my views and if i dont not have any,
			// i set the control to activated and i remove action... kind of a disabled...

			var enable = false ;
			for( var viewId in _localCollection.views ){
				try{
					if( pln.node.getLength( pln.node.getById( viewId ) ) > 0 ){
						enable = true ;
						break ;
					}
				}catch( e ){}
			}
			if( !enable ){
				// Set the style to DEACTIVATED and remove all other class linked to this js class that can be fond on the node.
				pln.node.removeClassName( this.getElement() , _constant.OPEN.css ) ;
				pln.node.removeClassName( this.getElement() , _constant.CLOSE.css ) ;
				pln.node.removeClassName( this.getElement() , _constant.PARTIALLY_OPEN.css ) ;
				pln.node.addClassName( this.getElement() , _constant.DEACTIVATED.css ) ;

			}else{
				class_toggle_control.collection.control[ this.getId() ] = { instance : this , updateStatus : updateStatus } ;
				pln.events.addListener( this.getElement() , _event , this , this.toggle ) ;
				
				// We open an element by default
				if( _default ){
					this.toggle() ;
					
					// If we also display parent, we check if this toggle control is part of an other control
					if( _displayParent ){
						var collection = class_toggle_control.collection.control ;
						for( i in collection ){
							// We check if this instance is part of another toglle control instance
							var instance = collection[ i ].instance ;
							if( instance != this ){
								var views = instance.getRegisteredViews() ;
								for( var j in views ){
									// If this control is part of another control view, we toggle that instance.
									// This will need to be modified later since, if a tree is in a tabulation, in an accordion, they will all open
									// and they may be some default conflict...
									if( pln.node.isChildOf( this.getElement() , pln.node.getById( j ) ) ){
										instance.toggle() ;
										break ;
									}
								}
							}
						}
					}
				}
			}
			__super.initialize() ;
		}
		this.terminate = function(){
			pln.events.removeListener( this.getElement() , _event , this , this.toggle ) ;
		}			
	
		/**
		 @private
		 @description	This is method is defined outside of the class instance
						and it's to make custom animation. If declared outside as a function, it 
						will receive as arguments 1) the element , 2) The toggle status ( either closing or opening )
		 @return		Nothing ;
		*/
		this.animate ;
	
		/**
		 @private
		 @description	Return the reversed current state of the control.
		 @return		String ;
		*/
		function inverseStatus(){
			if( _state == _constant.CLOSE.state || _state == _constant.PARTIALLY_OPEN.state ){
				return _constant.OPEN.state ;
			}
			return _constant.CLOSE.state ;
		}
	
		/**
		 @private
		 @description	Display or hide all views assigned to this control.
		 @return		Nothing ;
		*/	
		function displayViews( display , exception ){
			var exception = pln.isObject( exception ) ? exception : {} ;
			if( pln.isBoolean( display ) ){
			
				for( var i in _localCollection.views ){
					if( !pln.isset( exception[ i ] ) ){

						var reference = class_toggle_control.collection.view[ i ] ;
						reference.status = display ? _constant.OPEN.state : _constant.CLOSE.state ;
						if( pln.isFunction( _host.animate ) ){
							// Call user defined custom animation function 
							_host.animate( i , display ? 'opening' : 'closing' ) ;
						}else{
							pln.node.setProperty( i , 'display' , display ? 'block' : 'none' ) ;
						}
						nvi.eventManager.dispatchEvent( _host.getId() , display ? nvi.eventManager.events.__opened : nvi.eventManager.events.__closed ) ;
					}
				}
			}
		}
		
		/**
		 @private
		 @description	Hide all views of other controls in groups that this control is registered to.
		 @return		Nothing ;
		*/		
		function changeGroupMemberStatus(){
			var id = _host.getId() ;
			for( var i in _localCollection.group ){
				var group = class_toggle_control.collection.group[ i ] ;
				for( var j in group ){
					if( j != id ){
						if( pln.isset( group[ j ] ) && pln.isFunction( group[ j ].displayViews ) ){
							group[ j ].displayViews( false , _localCollection.views ) ;
						}
					}
				}
			}
		}
		
		/**
		 @private
		 @description	Add or remove state css class form this control
		 @return		Nothing ;
		*/		
		function manageClassName( action ){
			pln.node[ action + 'ClassName' ] ( _host.getElement() , _constant[ _state ].css ) ;
		}
		
		/**
		 @private
		 @description	Call the updateStatus method of all control instanciated 
						with this class.
		 @return		Nothing ;
		*/
		function updateAllControls(){
			var collection = class_toggle_control.collection.control ;
			for( i in collection ) collection[ i ].updateStatus() ;
		}
		
		/**
		 @private
		 @description	This method is use to update the logic of this control
						to reflect the state of its views.
		 @return		Nothing ;
		*/		
		function updateStatus(){
			manageClassName( 'remove' ) ;

			var closed = [] ;
			var opened = [] ;
			
			for( var i in _localCollection.views ){
				var status = class_toggle_control.collection.view[ i ].status ;
				( status == _constant.CLOSE.state ? closed : opened ).push( 1 ) ;
			}
			
			if( closed.length == 0 ) _state = _constant.OPEN.state ;
			if( opened.length == 0 ) _state = _constant.CLOSE.state ;
			if( opened.length > 0 && closed.length > 0) _state = _constant.PARTIALLY_OPEN.state ;

			manageClassName( 'add' ) ;
			
			delete closed ; 
			delete opened ;
		}
		
		/**
		 @private
		 @description	Validate the closeAllView property of all group that this control is registered to.
		 @return		Boolean ;
		*/			
		function canCloseAll(){
			for( var i in _localCollection.group ){
				return class_toggle_control.collection.group[ i ].closeAllView ;
			}
		}	
		
		/**
		 @private
		 @description	Set the currrent property of all group that this control is registered to this instance
		 @return		Nothing ;
		*/		
		function setCurrent( instance ){
			for( var i in _localCollection.group ){
				class_toggle_control.collection.group[ i ].current = instance ; 
			}
		}
		
		/**
		 @private
		 @description	Get the current instance that is activated from all group that this control is registered to.
		 @return		Object ; ( instance of class_toggle_control )
		*/			
		function getCurrent(){
			for( var i in _localCollection.group ){
				return class_toggle_control.collection.group[ i ].current ; 
			}
			return null ;
		}		

		/**
		 @public
		 @description	Since this class do not represent a physical html item linked with the server
						we overwrite the updateview method to disable it.
		 @return		Nothing ;
		*/
		this.updateView = function(){}

		/**
		 @public
		 @description	Hide/show views of this control.
		 @return		Nothing ;
		*/
		this.toggle = function(){
			var current = getCurrent() ;
			if( ( ( current == this && _state == _constant.OPEN.state && canCloseAll() == true ) || ( current == this && _state == _constant.CLOSE.state ) ) || current != this ){
				manageClassName( 'remove' ) ;			
				_state = inverseStatus() ;
				displayViews( _state != _constant.CLOSE.state ) ;
				changeGroupMemberStatus() ;
				updateAllControls() ;
				setCurrent( this ) ;				
			}
		}

		/**
		 @public
		 @description	By calling this method, we set this instance of the toggle class as the 
						default( selected item ) of it's group( if any ), it become the first 
						element selected when a page load. There can only be one default item 
						per group, any call to this method will overwrite the previously 
						selected default instance.
		 @returns		Nothing ;
		*/		
		this.setAsDefault = function( displayParent ){
			_default = true ;
			if( pln.isBoolean( displayParent ) ) _displayParent = displayParent ;
		}
		
		/**
		 @public
		 @description	Assign a view to this control. A control can have multiple 
						views but the same view cannot be registered twice.
		 @return		Nothing ;
		*/		
		this.assignView = function( viewId ){

			// Global view registration
			var collection = class_toggle_control.collection.view ;
			if( !pln.isset( collection[ viewId ] ) ){
				collection[ viewId ] = { 
					status : _constant.CLOSE.state ,
					motion : null
				} ;
			}
			
			// Local view registration
			if( pln.isString( viewId ) && !pln.isset( _localCollection.views[ viewId ] ) ){
				_localCollection.views[ viewId ] = {} ;
			}
		}
		
		/**
		 @public
		 @description	Return a list of registered views (html elements that this instance controls)
		 @returns		Object ;
		*/		
		this.getRegisteredViews = function(){
			return _localCollection.views ;
		}		

		/**
		 @public
		 @description	Register this control to a group. Grouping control mean they 
						will behave like a tabulation navigation: when a control is 
						activated, it will close all the others controls of the same 
						group.
		 @return		Nothing ;
		*/	
		this.registerToGroup = function( groupId ){
			if( pln.isString( groupId ) ){
				var collection = class_toggle_control.collection.group ;
				if( !pln.isset( collection[ groupId ] ) ) collection[ groupId ] = { closeAllView : false , current : null } ;
				if( !pln.isset( collection[ groupId ][ this.getId() ] ) ){
					collection[ groupId ][ this.getId() ] = { instance : this , displayViews : displayViews } ;
					_localCollection.group[ groupId ] = {} ;
				}else{
					nvi.logManager.log( 'The following control ( ' + this.getId() + ' ) is already registered to the following group: ' + groupId , 'Report' , 'class_toggle_control' , 'registerToGroup' );			
				}
			}
		}
		
		/**
		 @public
		 @description	Get the desired data and returned it( when called) to 
						the Nvi Shared Ressources Manager
		 @returns		Object ;
		*/		
		this.getSharedRessources = function(){
			return {
				type : 'toggle' ,
				id : this.getId() ,
				parameters : {}
			} ;
		}		
		
		//
		this.duplicate = function( label /* , element or view id */ ){
			//
			//
			var tempId = 'toggle_dynamic__' + pln.getUniqueId() ;
			var newViewId = 'view__' + tempId ;
			
			var element = this.getElement() ;
			var newTab = pln.node.duplicate( element ) ;
			pln.node.setProperty( newTab , 'id' , tempId ) ;
			// Add close button
			
			var labelElement = pln.node.getByAttributeValue( 'class' , 'title' , newTab ) ;
			if( pln.isArray( labelElement ) ) labelElement = labelElement[ 0 ] ;
			pln.node.setProperty( labelElement , 'innerHTML' , label ) ;
			
			var tempTab = nvi.panelManager.createInstance( tempId , class_toggle_control , true  ) ;
			for( i in _localCollection.views ){
				//
				var newView = pln.node.duplicate( pln.node.getById( i ) ) ;
				pln.node.setProperty( newView , 'innerHTML' , 'NEW VIEW for ' + newViewId ) ;
				pln.node.setProperty( newView , 'id' , newViewId ) ;
				
				tempTab.assignView( newViewId ) ;
			}
			for( i in _localCollection.group ) tempTab.registerToGroup( i ) ;
			
			tempTab.initialize();
			//
			tempTab.toggle() ;
			
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// Static goup and control collection
	class_toggle_control.collection = { group : {} , view : {} , control : {} } ;
	
	/**
	 @public
	 @description	If the closeAllView is set to true by calling this method, 
					you will be able to close all view of group.
	 @return		Nothing ;
	*/
	class_toggle_control.enableCloseAllView = function( groupId ){
		class_toggle_control.collection.group[ groupId ].closeAllView = true ;
	}
	

	/**
	  @definition	We are extending this class with the basic panel class
	*/	
	class_toggle_control.extend = class_nvi_basic_panel ;

}