/**
 * @fileoverview	EasyGUI TabCtrl Class
 * This Class creates a fully functional TabCtrl
 * If you want to style your own TabCtrl please consult
 * the EasyGUI XP Users Guide.
 * 
 * @author	Gaetan Lauff <glauff@plansoft.de>
 * @package	js.widgets
 *
 * @version	$Id: class.tabctrl.js 293 2008-02-13 13:57:10Z glauff $
 */
var EasyGUI_EKTabCtrl = Class.create();

/**
 * @Class EasyGUI_TabCtrl
 * @constructor
 * @param	{string}	id	ID of Widget
 * @returns	void
 * @access	public
 */
Object.extend( Object.extend( EasyGUI_EKTabCtrl.prototype, EasyGUI_widget.prototype ),
{
	panels: null,
	tabs: [],
	tabArea: null,
	leftButton: null,
	rightButton: null,
	selectedIndex: 0,
	activateScrollCtrl: false,
	hiddenTabs: [],
	
	init: function() 
	{
		if ( isEmptyValue(this.element.className) ) {
			this.element.className = 'easygui-tabctrl';
		}
		this.realWidth =  this.element.getWidth();
		
		/**
		 * Holds value of selected Tab
		 * @type	string
		 * @private
		 */
		this.selected 	= Element.getAttributeValue( this.element, 'selected' );
		this.stacked 	= Element.getAttributeValue( this.element, 'stacked', false );
		this.stackSize 	= Element.getAttributeValue( this.element, 'stacksize', 1 );
		
		/**
		 * Holds all Panels
		 * @type 	array
		 * @private
		 */
		this.panels = Element.getChildNodesByTagName( this.element, 'div' );
		
		if ( this.panels.length == 0 ) {
			return;
		}
		/**
		 * Holds all Tabs
		 * @type	array
		 * @private
		 */
		this.tabs = [];
		
		/**
		 * @type	object
		 * @private
		 */
		this.tabAreas = [];
		
		this.tabAreas.push(new Element('div'));
		this.tabAreas[0].className = this.getStyleDefinition( 'area' );
		
		//var firstPanel = Element.getFirstChildByTagName( this.element, 'DIV' );
		firstPanel = this.element.down('div');
		firstPanel.insert({before: this.tabAreas[0]});
		
		//firstPanel.parentNode.insertBefore( this.tabAreas[0], firstPanel );
		
		/**
		 * @type	integer
		 * @private
		 */
		this.selectedIndex = 0;
		this.element.style.visibility = 'hidden';
		
		var offsetWidth = 0;
		
		// Fix for TabCtrl nested inside another TabCtrl
		var tabId = Element.isInTab(this.element);
		
		if (tabId)
			Element.show(tabId);
		
		for (var i=0; i < this.panels.length; i++) {
			if (this.panels[i].id == this.selected) {
				this.selectedIndex = i;
			}
			
			var tab = Element.getFirstChildByTagName( this.panels[i], 'A' );
			tab.setAttribute('panelid', this.panels[i].id );
			
			/*
			 * This is for handling old isycat/easygui style tabctrls
			 */
			var isyheader = Element.getFirstChild( this.panels[i] );
			var isytext = "";
			
			if ( isyheader && isyheader.nodeName == "SPAN" ) {
				isyheaderTable = Element.getFirstChildByTagName( isyheader, 'TABLE' );
				
				isytext = Element.getInnerText( isyheaderTable.rows[0].cells[0] );
				this.panels[i].removeChild( isyheader );
			} 
			
			tabtext = Element.getInnerText( tab );
						
			if (!tabtext)
				tab.innerHTML = isytext;
			
			var header = tab.cloneNode(true);
			
			if (header.style.visibility == 'hidden') {
				Element.hide( header );
				Element._show( header );
			}
			
			if (is.ie5)
				header.style.width = '10px';
				
			header.className = this.getStyleDefinition( 'tab');
			header.style.position = 'relative';
			header.style.whiteSpace = 'nowrap';
			
			Event.observe( header, 'click', this.switchTab.bindAsEventListener(this), false);
			
			// Find a better solution one day to handle all user defined event handlers
			header.onclick = this.panels[i].onclick;
			//header.onfocus = function() { this.blur(); };
			Event.observe(header, "focus", this.onFocus.bindAsEventListener(this) );
			
			this.panels[i].onclick = function() { return true; };
			
			header.setAttribute('panelid', this.panels[i].id );
			header.setAttribute('widgetid', this.id );
			this.panels[i].setAttribute('widgetid', this.id );
			
			this.tabAreas[0].appendChild( header );
			this.tabs[this.tabs.length] = header;
			
			offsetWidth += header.offsetWidth;
			
			// Zuerst muss man zuverlässig rausfinden wieviele Stacks man braucht.
			// Dazu 
			if ( offsetWidth > this.element.offsetWidth - 50) {
				this.activateScrollCtrl = true;
				this.hiddenTabs[this.hiddenTabs.length] = header;
			}
			
			this.panels[i].className = this.getStyleDefinition( 'panel' );
			
			this.panels[i].style.position = 'relative';
			this.panels[i].style.overflow = 'auto';
			this.panels[i].style.zIndex = 101;

			this.panels[i].removeChild( tab );
		}
		
		// Das hier muss in eine Funktion gekapselt werden,
		// denn bei gestackten muss man noch mehr ausrechnen
		//var realHeight 	= this.getOffsetHeight();
		var tabsHeight 	= this.tabs[this.selectedIndex].offsetHeight;
		
		//var height = realHeight - tabsHeight;
		/*
		for(var i=0; i < this.panels.length; i++)
			this.panels[i].style.height = height + 'px';
		*/
		Form.insertHidden( this.id + '_EK_WIDGET_VALUE', '' );
		
		this.selected = this.tabs[this.selectedIndex].getAttribute('tabpanel');
		this.renderScrollCtrl( tabsHeight );
		
		
	},
	
	onFocus : function( evt )
	{
		var element = $GE(evt);
		element.blur();
	},
	
	renderScrollCtrl: function( tabsHeight )
	{
		if ( this.activateScrollCtrl )
		{
			if ( this.stacked ) {
			} else {
				var tabArea = new Element('div');
				
				this.element.insert({
					top: tabArea
				});
				
				tabArea.setStyle({
					'position': 'relative',
					'width': this.element.getWidth() + 'px'
				});
				
				this.leftButtonArea = new Element('div',{
					/*'class': 'easygui-tabctrl-scroll-left'*/
				});
				
				this.leftButtonArea.setStyle({
					'position': 'absolute',
					'width': '18px', 
					'height': '18px',
					'left': '0',
					'top': '0'
				});
				
				this.leftButton = new Element('button');
				this.leftButton.setStyle({
					'width': '18px',
					'height': '18px'
				});
				
				this.leftButton.insert('<span style="font-size: 10px"><b>&lt;</b></span>');
				
				this.leftButtonArea.insert( this.leftButton );
				
				
				Event.observe( this.leftButton, "focus", this.onFocus.bindAsEventListener(this) );
				Event.observe( this.leftButton, 'click', this.scrollLeft.bindAsEventListener(this) );
				
				this.rightButtonArea = new Element('div', {
					/*'class': 'easygui-tabctrl-scroll-right'*/
				});
				
				this.rightButtonArea.setStyle({
					'position': 'absolute',
					'width': '18px',
					'height': '18px',
					'right': '0',
					'top': '0'
				});
				
				this.rightButton = new Element('button');
				
				this.rightButton.setStyle({
					'width': '18px',
					'height': '18px'
				});
				
				this.rightButton.insert('<span style="font-size: 10px"><b>&gt;</b></span>');
				
				this.rightButtonArea.insert( this.rightButton );
				
				Event.observe( this.rightButton, "focus", this.onFocus.bindAsEventListener(this) );
				Event.observe( this.rightButton, 'click', this.scrollRight.bindAsEventListener(this) );
				
				var tabStripWidth = this.tabAreas[0].getWidth();
				tabStrip =  this.tabAreas[0].remove();
				
				tabStrip.style.marginLeft = '18px';
				tabStrip.style.marginRight = '18px';
				tabStrip.style.width = tabStripWidth - 18 + "px";
				
				tabArea.insert( tabStrip );
				
				tabArea.insert({
					top: this.leftButtonArea
				});
				
				tabArea.insert({
					top: this.rightButtonArea
				});
				
				this.leftButton.disabled = true;
			}
		}
	},
	
	onScrollLeftButtonOver : function() {
		this.leftButton.addClassName('over');
	},
	
	onScrollLeftButtonOut: function() {
		this.leftButton.removeClassName('over');
	},
	
	onScrollRightButtonOut : function() {
		this.rightButton.removeClassName('over');
	},
	
	onScrollRightButtonOver : function() {
		this.rightButton.addClassName('over');
	},
	
	finalize: function() 
	{
		this.initialized = true;
		
		if ( this.panels.length == 0 )
			return;
		
		// Fix for TabCtrl nested inside another TabCtrl
		var tabId = Element.isInTab(this.element);
		
		if (tabId)
			Element.show(tabId);
		
		if ( this.hiddenTabs.length > 0 ) {
			if ( this.stacked ) {
				// Das ist die kritische Breite
				var newArea = false;
				var newWidth = 0;
				
				for (var i=0; i < this.hiddenTabs.length; i++ ) {
					var header = $(this.hiddenTabs[i]);
					newWidth += header.getWidth();
					
					if ( !newArea || newWidth > this.realWidth ) {
						newArea = new Element('div',{
							className : this.getStyleDefinition( 'area' )
						});
						
						var tabArea = this.element.down('div.' + this.getStyleDefinition('area'));
						tabArea.insert({before: newArea});
						newWidth = 0;
					}
					
					newArea.insert( header.remove() );
				}
			} else {
				for (var i=0; i < this.hiddenTabs.length; i++ ) {
					this.hiddenTabs[i].style.display = "none";
				}
			}
		}
		
		var realHeight = this.getOffsetHeight();
		
		var tabsHeight = 0;
		var className = this.getStyleDefinition('area');
		
		$$('div.' + this.getStyleDefinition('area')).each( function(area) {
			tabsHeight += area.getHeight();
		});
		
		var height = realHeight - tabsHeight;
		
		for(var i=0; i < this.panels.length; i++) {
			this.panels[i].style.height = height + 'px';
		}
			
		var selectedIndex = this.getSelectedIndex();
		
		if ( this.tabs[selectedIndex].style.display == "none"  ) 
		{
			for (var i=0; i < this.tabs.length; i++ ) {
				this.scrollRight();
				
				if ( this.tabs[selectedIndex].style.display == "" )
					break;
			}
		}
		
		this.switchTab( this.selected );
		Element._show( this.element );
	},
	
	getSelected: function()
	{
		return this.selected;
	},
	
	getSelectedIndex: function()
	{
		for ( var i=0; i < this.tabs.length; i++ )
			if ( this.tabs[i].getAttribute('panelid') == this.selected )
			 	return i;
		
		return 0;
	},
	
	/**
	 * Updates the widget
	 * @private
	 */
	updateWidget: function ()
	{
		this.selected = Element.getAttributeValue( this.element, 'selected' );
		
		if (this.selected)
			this.switchTab( this.selected );
	},
	
	/**
	 * Returns tab
	 *
	 * @param	{object} tab
	 * @returns object
	 */
	getTab: function( node )
	{	
		var tab = $GE(node);
		
		if ( typeof( node ) == 'string' ) {
			for (var i=0; i < this.panels.length; i++)
				if ( this.panels[i].id == node )
					this.selectedIndex = i;
	
			tab = this.tabs[this.selectedIndex];
		} else {
			
			if ( node.nodeName == 'DIV' ) {
				for (var i=0; i < this.tabs.length; i++) {
					var tabpanel = this.tabs[i].getAttribute('tabpanel');
					
					if (tabpanel == node.id)
						tab = this.tabs[i];
				}
			}
		}
		
		return $(tab);
	},
	
	/**
	 * Switches Tab from one to another
	 *
	 * @param	{object} tab
	 * @returns	void
	 */
	switchTab: function( evt )
	{
		var tab = this.getTab( evt );
		tab.blur();
		/*
			Thoughts about the stack order
		var aStyle = this.getStyleDefinition('area');
		var area = tab.up('div.' + aStyle );
		var sourceArea = area;
		
		while ( area.next('div.' + aStyle ) !== undefined )
			area = area.next('div.' + aStyle );
		*/
		/*if ( area )
			area.insert({
				after: sourceArea.remove()
			});
		*/
		
		//console.log(sourceArea);
		
		for (var i = 0; i < this.panels.length; i++) {
			Element.hide( this.panels[i] );
			//Element._hide( this.panels[i] );
		}
		
		for (var i = 0; i < this.tabs.length; i++) {
			this.tabs[i].className = this.getStyleDefinition( 'tab' );
		}
		
		if (is.ie5)
			var correctTop = Element.getStyle( tab, 'top' );
		
		tab.className += ' ' + this.getStyleDefinition('tab') + '-active';
		
		if (is.ie5)
			tab.style.top = correctTop;
			
		var id = tab.getAttribute('tabpanel');
		
		Element.show( $( id ) );
		//Element._show( $( id ) );
		
		if ( this.initialized ) {
			this.selected = id;
			Form.Element.setValue( this.id + '_EK_WIDGET_VALUE', id );
		}
		
		if ( typeof evt == "object" ) //&& evt instanceof Event )
			Event.stop( evt );
	},

	/**
	 * hides a Tab
	 * @access	public
	 */
	hideTab: function( tab )
	{
		var tab 	= this.getTab( tab );
		var id 		= tab.getAttribute('tabpanel');
		var panel 	= $GE( id );
		
		Element.hide( panel );
		Element.hide( tab );
        
        for ( var i=0; i < this.tabs.length; i++ )
		{
			if ( this.tabs[i].style.display != 'none' ) {
				this.switchTab( this.tabs[i].getAttribute('panelid'));
				break;
			}
		}
	},
	
	/**
	 * shows a hidden Tab again
	 * @access	public
	 */
	showTab: function( tab )
	{
		var tab= this.getTab( tab );
		Element.show(tab);
	},
	
	/**
	 * 
	 */
	scrollLeft: function( evt )
	{
		for ( var i=( this.tabs.length - 1 );i >= 0; i-- ) 
		{
			if ( this.tabs[i].style.display != 'none' ) {
				this.tabs[i].style.display = 'none';
				break;
			}
		}
		
		for ( --i; i >= 0 ; i-- )
		{
			if ( this.tabs[i].style.display == 'none' ) {
				this.tabs[i].style.display = '';
				break;
			}
		}
		// First Tab
		if ( i == 0 ) {
			this.leftButton.disabled = true;
		}
			
		this.rightButton.disabled = false;
	},
	
	/**
	 *
	 */
	scrollRight: function( evt )
	{		
		for ( var i=0; i < this.tabs.length; i++ )
		{
			if ( this.tabs[i].style.display != 'none' ) {
				this.tabs[i].style.display = 'none';
				break;
			}
		}
		
		for ( ++i; i < this.tabs.length; i++ )
		{
			if ( this.tabs[i].style.display == 'none' ) {
				this.tabs[i].style.display = '';
				break;
			}
		}
		// Last Tab
		if ( i == ( this.tabs.length - 1 ) )
			this.rightButton.disabled = true;
			
		this.leftButton.disabled = false;
	},
	
	/**
	 * Sets new Text to tab
	 *
	 * @param	{string}	tab 	id of tab
	 * @param	{string}	text	new text
	 * @access	public
	 */
	setTabText: function( tab, text )
	{
		var tab = this.getTab( tab );
		tab.innerHTML = text;
	},
	
	/**
	 * Adds a selection changed handler
	 * @returns	void
	 * @private
	 */
	addSelectionChangedHandler: function()
	{
		if (!this.selectionChangedHandler)
			return;
			
		Event.observe( this.element, 'click', this.onSelectionChanged.bindAsEventListener(this) , false );
	},
	
	/**
	 * Removes a tab from the Ctrl
	 * @todo implement
	 */
	removeTab: function( tab )
	{
		this.hideTab( tab );
	},
	
	/**
	 * Disables a Tab
	 * @todo implement
	 */
	disableTab: function( tab )
	{
		;
	},
	
	/**
	 * Enables a Tab
	 * @todo implement
	 */
	enableTab: function( tab )
	{
		;
	}
});

var EasyGUI_TabCtrl = Class.create();

Object.extend( Object.extend( EasyGUI_TabCtrl.prototype, EasyGUI_widget.prototype ),
{
	render : function() {
		var modus = this.element.readAttribute('modus') || 'normal';
		
		if ( modus == 'normal' ) {
			Object.extend( this, new EasyGUI_EKTabCtrl( this.id ) );
		} else {
			Object.extend( this, new EasyGUI_ExtTabCtrl( this.id ) );
		}
		
		this.init();
	}
});