/**
 * @author trixta
 */
(function($){
	
	$.widget('ui.tabtree', {
		_init: function(){
			var that = this,
				o =  this.options,
				elem = this.element,
				isHTMLSelected
			;
						
			this.slideShowtimer = null;
			
			this.buttons = $(o.buttonSel, elem[0]);
			
			this.panels = (o.panelSel) ? 
				$(o.panelSel, this.element[0]).each(function(i){
					var button 	= $(that.buttons[i]),
						panel 	= $(this).labelWith(button)
					;
					button.controlsThis(panel);
				}) : 
				this.buttons.map(function(){
					var button 	= $(this),
						idRef 	= button.attr('href'),
						panel 	= $(idRef)
					;
					
					panel.labelWith(button);
					button.attr({'aria-controls': idRef.replace('#', '')});
					return panel[0];
				});
							
			this.panels = $($.unique(this.panels.get()));
			
			if(o.focusDelay === 'auto'){
				o.focusDelay = (o.handleDisplay && o.handleDisplay !== 'initial') ? 300 : 401; // 400 ist default fx-duration
			}
			
			if(o.addButtonRole){
				this.buttons.attr({role: 'button'});
				this.panels.attr({role: 'group'}).addClass('a11y-js-overflow');
			}
			
			this.panels
				.css({outline: 'none'})
				.attr({tabindex: '-1'});
			
			if(o.createPanelwrapper){
				this.panels.wrap('<div class="a11y-panelwrapper" />');
			}
			
			//get defaultselected
			isHTMLSelected = !!this.buttons.filter('.'+ o.activeButtonClass)[0];
							
			this.buttons
				.each(function(i){
					var button = $(this),
						initAction = ((isHTMLSelected && button.is('.'+ o.activeButtonClass)) ||
							(!isHTMLSelected && o.defaultSelected === i)) ? 
							'expand' :
							'collapse'
					;
					that[initAction].call(that, this, {type: 'init'});
				});
				
			if(o.removeHref && (!$.browser.msie || parseFloat($.browser.version, 10) > 6)){
				this.buttons.removeAttr('href');
			}
			
			if(o.selectEvents){
				this.buttons
					[o.bindStyle](o.selectEvents, function(e){
						var action = (o.toggleButton) ?
							'toggle' :
							'expand';
						that[action].call(that, this, e);
						clearInterval(that.slideShowtimer);
						return false;
					});
			}
			//focus panels onclick if no click event is added
			if(!o.selectEvents || o.selectEvents.indexOf('click') == -1){
				this.buttons[o.bindStyle]('click', function(){
					clearInterval(that.slideShowtimer);
					if(o.focusOnExpand){
						that.focusPanel.call(that, $($(this).attr('aria-controls')), 1);
					}
					return false;
				});
			}
			
			if(o.slideShow && isFinite(o.slideShow)){
				this.slideShowtimer = setInterval(function(){
					that.showPrevNext.call(that, 1);
				}, o.slideShow);
			}
			
			if(o.addToHistory === 'auto'){
				o.addToHistory = !!($.hashHistory && !o.multiSelectable);
			}
			if(o.addToHistory){
				this.startHash = $.hashHistory.get();
				this.changeByHash(this.startHash, {type: 'hashInit'});
				this.startSelectedButton = this.buttons.filter('.'+ o.activeButtonClass);
				
				this.panels.each(function(){
					var jElm = $(this);
					//$('<a id="tab-'+ jElm.getID() +'" />').insertBefore(this).attr({tabindex: '-1'});
				});
				$(document).bind('hashHistoryChange', function(e, data){
					that.changeByHash(data.hash, $.extend({}, e, data));
				});
			}
			this._trigger('init', {type: 'init'}, this.ui());
		},
		
		showPrevNext: function(dir){
			var index = this.buttons
				.index(this.buttons.filter('.'+ this.options.activeButtonClass)[0]) + dir;
			if(index < 0){
				index = this.buttons.length - 1;
			} else if(index >= this.buttons.length){
				index = 0;
			}
			this.expand(this.buttons.get(index), {type: 'show-'+ dir});
		},
		toggle: function(button, e){
			var action = ($(button).is('.'+ this.options.activeButtonClass)) ?
				'collapse' : 'expand';
			this[action](button, e);
		},
		collapse: function(button, e, _panel){
			e = e || {type: 'collapse'};
			button = $(button);
			
			//if button/panel is already inactive
			if(!button.is('.'+ this.options.activeButtonClass) && e.type != 'init'){
				return false;
			}
			
			var panel 		= _panel || this.getPanel(button),
				buttons 	= this.getButtons(panel),
				type 		= (e.type == 'init') ? 
								'collapseinit' :
								'collapse',
				that 		= this,
				o 			= this.options,
				uiObj 		= {
								button: buttons,
								panel: panel
							},
				returnVal = this._trigger(type, e, $.extend({}, this.ui(), uiObj))
			;
			
			if(returnVal === false){return;}
			
			this.setState(buttons, uiObj.panel, 'inactive');
			
			if(o.handleDisplay === true || (e.type == 'init' && o.handleDisplay)){
				uiObj.panel.hide();
			}
			
			uiObj.button = button;
			
			
			if($.ui.SR){
				$.ui.SR.update();
			}
			return uiObj;
		},
		expand: function(button, e){
			e = e ||
				{type: 'expand'};
			button = $(button);
			
			//if button/panel is already active
			if(e.type != 'init' && button.is('.'+ this.options.activeButtonClass)){
				return false;
			}
			
			var type 			= (e.type == 'init') ? 
								'expandinit' :
								'expand',
				that 			= this,
				o 				= this.options,
				panel 			= this.getPanel(button),
				buttons			= this.getButtons(panel),
				collapseButton 	= this.buttons.filter('.'+ o.activeButtonClass),
				collapsePanel	= this.getPanel(collapseButton),
				returnVal	 	= this._trigger(type, e, $.extend({}, this.ui(), {
						button: buttons, 
						panel: panel, 
						collapseElements: {
							button: collapseButton, 
							panel: collapsePanel
						}
					})),
				posStyle,
				panelWrapper
			;
			
			if(returnVal === false){
				return false;
			}
			
			
			//collapse all other panels, if not multiSelectable
			if(e.type != 'init' && !o.multiSelectable){
				collapseButton.each(function(){
					that.collapse.call(that, this, e);
				});
			}
			this.setState(buttons, panel, 'active');
			
			
			if(o.handleDisplay === true || (e.type == 'init' && o.handleDisplay == 'initial')){
				panel.show();
			}
			
			if($.ui.SR){
				$.ui.SR.update();
			}
			
			if(o.addToHistory && e.type !== 'init' && e.type !== 'hashHistoryChange'){
				$.hashHistory.add('tab-'+ panel.getID());
			}
			
			if(/click|hashHistoryChange/.test(e.type) && o.focusOnExpand){
				that.focusPanel(panel, o.focusDelay);
			}
			
		},
		getButtons: function(panel){
			return this.buttons.filter('[aria-controls='+ panel.getID() +']');
		},
		getPanel: function(button){
			return this.panels.filter('#'+ button.attr('aria-controls') );
		},
		changeByHash: function(hash, e){
			if(!hash.indexOf || (hash.indexOf('tab-') !== 0 && this.startHash !== hash)){return;}
			e = e || {type: 'hashHistory'};
			var button = this.buttons.filter('[aria-controls='+ hash.replace(/^tab-/, '') +']');
			if(!button[0] && hash === this.startHash){
				button = this.startSelectedButton;
			}
			if(button && button[0]){
				this.expand(button, e);
			}
		},
		setState: function(button, panel, state){
			var o	 	= this.options,
				set 	= (state == 'active') ? 
							{
								c: 'addClass',
								
								index: '-1',
								aria: 'true'
							} :
							{
								c: 'removeClass',
								index: '0',
								aria: 'false'
							}
			;
			if((!o.toggleButton)){
				button.attr({'tabindex': set.index, 'aria-disabled': set.aria})[set.c]('ui-disabled');
			} else {
				button.attr({'tabindex': '0'});
			}
			button[set.c](o.activeButtonClass).attr('aria-expanded', set.aria);
			panel[set.c](o.activePanelClass).attr('aria-expanded', set.aria);
		},
		focusPanel: function(panel, time){
			var o 			= this.options,
				focusElem 	= (o.focusSel === true || !o.focusSel) ? panel : $(o.focusSel, panel)
			;
			
			focusElem.setFocus({
				addTabindex: true,
				parent: panel,
				time: time || 1
			});
		},
		ui: function(){
			return {
				instance: this
			};
		}
	});
	
	$.ui.tabtree.defaults = {
		buttonSel: 'a',
		panelSel: false,
		focusOnExpand: true,
		focusSel: '> :visible:first',
		focusDelay: 'auto',
		addButtonRole: true,
		removeHref: true,
		createPanelwrapper: false, 
		toggleButton: false,
		multiSelectable: false,
		selectEvents: 'ariaclick',
		bindStyle: 'bind',
		defaultSelected: 0,
		slideShow: false,
		activeButtonClass: 'ui-active',
		activePanelClass: 'ui-expanded',
		handleDisplay: true, //initial | true | false
		addToHistory: false //'auto' || true ||  false
	};
})(jQuery);
