/**
 * @author trixta
 */
(function($){
	
	function numsort (a, b) {
	  return a - b;
	}
	var uniqueID = 0;
	$.widget('ui.tabtree', {
		options: {
			buttonSel: 'a',
			panelSel: false,
			focusOnExpand: true,
			focusSel: true,
			createPanelwrapper: false, 
			toggleButton: false,
			multiSelectable: false,
			selectEvents: 'ariaclick',
			bindStyle: 'bind',
			bindContext: false,
			defaultSelected: 0,
			slideShow: false,
			restartSlideShow: true,
			activeButtonClass: 'js-selected',
			activePanelClass: 'js-expanded',
			handleDisplay: true //initial | true | false
		},
		_create: function(){
			var that 			= this,
				o 				=  this.options,
				elem 			= this.element,
				isSelectedArray = o.defaultSelected.length,
				isHTMLSelected
			;
			
			this.selectedIndexes = [];			
			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.getHrefHash(),
						panel 	= $(idRef)
					;
					
					panel.labelWith(button);
					button.attr({'aria-controls': idRef.replace('#', '')});
					return panel[0];
				});
							
			this.panels = $($.unique(this.panels.get()));
						
			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.hasClass(o.activeButtonClass)) ||
							( !isHTMLSelected && (isSelectedArray) ? 
									$.inArray(i, o.defaultSelected) !== -1 : 
									(!isHTMLSelected && o.defaultSelected === i)) ) ? 
							'expand' :
							'collapse'
					;
					that[initAction].call(that, this, {type: 'init'});
				});
			
			if($.support.waiAria){
				this.buttons.attr({role: 'button'});
				if (this.buttons[0] && $.nodeName(this.buttons[0], 'a')) {
					this.buttons.each(function(){
						var jElm = $(this);
						this.setAttribute('data-href', jElm.attr('href'));
						jElm.removeAttr('href');
					});
				}
				this.panels.attr({role: 'group'}).addClass('a11y-js-overflow');
			}	
			uniqueID++;
			if(o.bindStyle === 'live'){
				this.buttons.context = (o.bindContext) ? $(o.bindContext, this.element)[0] : this.element[0];
				this.buttons.selector = '.tabtree-button_'+ uniqueID;
				this.buttons.addClass('tabtree-button_'+ uniqueID);
				if(!this.buttons.context) {
					console.log(o.bindContext +' not found in tab-module');
				}
			}
			
			if(o.selectEvents){
				this.buttons
					[o.bindStyle](o.selectEvents, function(e){
						var action = (o.toggleButton) ?
							'toggle' :
							'expand'
						;
						clearInterval(that.slideShowtimer);
						that[action].call(that, this, e);
						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);
				
				this.element.inOut(
					function(){
						clearInterval(that.slideShowtimer);
					}, function(){
					if(o.restartSlideShow){
						clearInterval(that.slideShowtimer);
						that.slideShowtimer = setInterval(function(){
							that.showPrevNext.call(that, 1);
						}, o.slideShow);
					}
				});
			}
			
			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).hasClass(this.options.activeButtonClass)) ?
				'collapse' : 'expand';
			this[action](button, e);
		},
		collapse: function(button, e, _panel, _opener){
			e = e || {type: 'collapse'};
			button = $(button);
			
			//if button/panel is already inactive
			if(!button.hasClass(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
							}
			;
			
			if(!o.multiSelectable){
				uiObj.expandElements = _opener || 
					{
						panel: $([]),
						button: $([])
					}
				;
			}
			
			this.removeIndex(panel);
			if(this._trigger(type, e, $.extend({}, this.ui(), uiObj)) === false){
				this.addIndex(panel);
				return undefined;
			}
			
			this.setState(buttons, uiObj.panel, 'inactive');
			
			if(o.handleDisplay === true || (e.type == 'init' && o.handleDisplay)){
				if(o.hideStyle === 'visibility'){
					uiObj.panel
						.parent()
						.css({overflow: 'hidden', height: 0})
						.end()
						.css({visibility: 'hidden'})
					;
				} else {
					uiObj.panel.hide();
				}
			}
			
			uiObj.button = button;
			
			$.ui.SR.update();
			
			return uiObj;
		},
		addIndex: function(index){
			if(!isFinite(index) && index.jquery){
				index = this.panels.index(index[0]);
			}
			if($.inArray(index, this.selectedIndexes) === -1){
				this.selectedIndexes.push(index);
				this.selectedIndexes.sort(numsort);
			}
		},
		removeIndex: function(index){
			if(!isFinite(index) && index.jquery){
				index = this.panels.index(index[0]);
			}
			this.selectedIndexes = $.grep(this.selectedIndexes, function(num, i){
				return (index !== num);
			});
		},
		expand: function(button, e){
			e = e ||
				{type: 'expand'};
			button = $(button);
			
			//if button/panel is already active
			if(e.type != 'init' && button.hasClass(this.options.activeButtonClass)){
				return false;
			}
			
			var type 			= (e.type == 'init') ? 
								'expandinit' :
								'expand',
				that 			= this,
				o 				= this.options,
				uiObj 			= {},
				panel 			= this.getPanel(button),
				buttons			= this.getButtons(panel),
				collapseButton 	= this.buttons.filter('.'+ o.activeButtonClass),
				posStyle,
				panelWrapper
			;
			uiObj.button = buttons;
			uiObj.panel = panel;
			if(!o.multiSelectable){
				uiObj.collapseElements = {
							button: collapseButton, 
							panel: this.getPanel(collapseButton)
						};
				
			}
			this.addIndex(panel);
			
			if(this._trigger(type, e, $.extend({}, this.ui(), uiObj)) === false){
				this.removeIndex(panel);
				return false;
			}
			
			
			//collapse all other panels, if not multiSelectable
			if(e.type != 'init' && !o.multiSelectable){
				collapseButton.each(function(){
					that.collapse.call(that, this, e, false, {button: buttons, panel: panel});
				});
			}
			this.setState(buttons, panel, 'active');
			
			
			if(o.handleDisplay === true || (e.type == 'init' && o.handleDisplay == 'initial')){
				if(o.hideStyle === 'visibility'){
					panel
						.parent()
						.css({overflow: '', height: ''})
						.end()
						.css({visibility: ''})
					;
				} else {
					panel.show();
				}
				
			}
			
			$.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);
			}
			return undefined;
		},
		getButtons: function(panel){
			return this.buttons.filter('[aria-controls='+ panel.getID() +']');
		},
		getPanel: function(button){
			return this.panels.filter('#'+ button.attr('aria-controls') );
		},
		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){
			if(!this.options.focusSel){return false;}
			var o 			= this.options,
				focusElem 	= (o.focusSel === true) ? panel.firstExpOf('semanticAtomSrFocusable') : $(o.focusSel, panel)
			;
			focusElem.setFocus({context: (panel[0].parentNode || {}).parentNode});
			return undefined;
		},
		ui: function(){
			return {
				instance: this,
				panels: this.panels,
				buttons: this.buttons,
				selectedIndexes: this.selectedIndexes
			};
		}
	});
	
})(jQuery);
