/**
 * myMooTabs - Notifications
 *
 * @version		1.2.3
 *
 * @requires MooTools v1.2 or later
 *
 * myMooTabs is a simple but flexible way of displaying tabbed data.  
 * It is possible to animate the transitions from one tab content to the other
 *
 * Licensed under the MIT:
 *
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2010 Peter Barkway [ peter@baytree-cs.com]
 *
 * @license		MIT-style license
 * @author		Peter Barkway <peter [at] baytree-cs.com>
 * @copyright	Author
 *
 * Usage:
 *
 *  window.addEvent('domready', function() {
 *      myTabs = new myMooTabs();
 *  });
 *
 *	<ul id="mmtMenu">
 *		<li id="tab1" class="current">Tab 1</li>
 *		<li id="tab2" >Tab 2</li>
 *		<li id="tab3" >Tab 3</li>
 *		<li id="tab4" >Tab 4</li>
 *	</ul>
 *	<div id="mmtDisplayContent"></div>
 *
 *	<div id="_tab1">Tab 1 content</div>
 *	<div id="_tab2">Tab 2 content</div>
 *	<div id="_tab3">Tab 3 content</div>
 *	<div id="_tab4">Tab 4 content</div>
 *
 * display effects: scroll_x, scroll_y, fade
 *
 */

var myMooTabs = new Class({
	Implements: [Options, Events, Chain],

	options: {
    useTabs								: true,
    useCarousel						: false,
    allowResize						: false,
    activationEvent				: 'click', 		// you can set this to ‘mouseover’ or whatever you like
	  currentClass					: 'current',  // change this to match your css
    elementSelector				: 'li',
		tabContainer					: 'mmtMenu',
		contentWrapper				: 'mmtDisplayContent',
		contentPrefix					: '_',
		carouselContainer			: 'mmtCarousel', // if not using tabs then we need to find the content another way
		disableKeys						: 0,
		onOpen								: function(){},
		onClose								: function(){},
		display								: {
															'duration': '300',
															'effect': '',
															'transition': ''
														},
		buttonPrevSelector		: 'button-prev',
		buttonNextSelector		: 'button-next'
	},
  
	initialize: function(options) {
		this.setOptions(options);
		this.prevTab = -1;
		this.curTab = 0;
		this.lastDisplay = 0;
		this.closing = 0;
		this.opening = 0;
		this.positions = [];
		this.childDivs = [];
		this.buttons = [];
		this.scroll = 0;
		
		if((/scroll/i).test(this.options.display['effect'])) this.scroll = 1;


		if(!this.options.disableKeys) {
			this.myMTKeyboard = new Keyboard({
				events: { 
					'left': function(){
									Keyboard.stop;
									this.showPrev();
								}.bind(this),
					'down': function(){
									Keyboard.stop;
									this.showPrev();
								}.bind(this),
					'up': function() {
									Keyboard.stop;
									this.showNext();
								}.bind(this),
					'right': function() {
									Keyboard.stop;
									this.showNext();
								}.bind(this)
				}
			});
		}
		if(MooTools.version>=1.3 && !this.myMTKeyboard.isActive()) this.myMTKeyboard.activate();
		else {}
		
// Get all the tabs that are within the tab container if using tabs, otherwise reverse engineer the buttons array
		if(this.options.useTabs) {
			this.buttons = $(this.options.tabContainer).getElements(this.options.elementSelector);
		} else {
			this.buttons = $(this.options.carouselContainer).getElements(this.options.elementSelector);		
		}
		if(this.options.useCarousel) this.setupButtons(); // if carousel buttons to be used then set them up

// prepare wrapper dimensions by getting the size of 1st tab content
		var julie = ((this.options.useTabs)?$(this.options.contentPrefix+this.buttons[0].id):$(this.buttons[0].id)).getSize();
		var myWidth = julie.x;
		var myHeight = julie.y;
		
		$(this.options.contentWrapper).setStyles({
			overflow: 'hidden',
			width: myWidth,
			height: myHeight
		});

// Inject the content container for scolling purposes and set the width/height
		if(this.scroll) {
			this.contentContainer = new Element('div').inject($(this.options.contentWrapper));
			if((/_y/i).test(this.options.display['effect'])) {
				this.contentContainer.setStyles({'width': 'auto', 'height': (myHeight * this.buttons.length) + 'px'});
			} else {
				this.contentContainer.setStyles({'width': (myWidth * this.buttons.length) + 'px', 'height':'auto'});
			}
		}

// Create the tweening options that are allowed
		this.tweens = {
			'box': new Fx.Morph(this.contentContainer, ((MooTools.version>=1.3)?((MooTools.version>=1.3)?Object.merge:$merge):$merge)({
					'duration': this.options.display['duration'],
					'unit': 'px',
					'transition': this.options.display['transition'],
					'link': 'cancel'
				})
			),
			'scroll': new Fx.Scroll($(this.options.contentWrapper), ((MooTools.version>=1.3)?((MooTools.version>=1.3)?Object.merge:$merge):$merge)({
					'duration': this.options.display['duration'],
					'transition': this.options.display['transition'],
					'link': 'cancel'
				})
			),
			'fade': new Fx.Tween(this.options.contentWrapper, ((MooTools.version>=1.3)?Object.merge:$merge)({
					'property': 'opacity',
					'duration': this.options.display['duration'],
					'link': 'cancel',
					onCancel: function() { if(!this.scroll) {if(this.closing) this.childDivs[this.lastDisplay].setStyle('display', 'none');}}.bind(this),
					onComplete: function() { if(!this.scroll) {if(this.prevTab >= 0 && this.closing) this.childDivs[this.prevTab].setStyle('display', 'none');}; this.lastDisplay = this.curTab;}.bind(this)
				})
			)
		};


// loop through the tabs
    ((MooTools.version>=1.3)?Array.each:$each)(this.buttons, function(tab, index) {
// Might as well do this on behalf of the user in case they forget
    	$(tab.id).setStyle("cursor","pointer"); 
    	
// If the current tab then make sure we capture the index number and then set the content to display
    	if($(tab.id).hasClass(this.options.currentClass)) {
    		this.curTab = index;
    		$(tab.id).toggleClass(this.options.currentClass);
    	}
// to be on the safe side, in case user has not set, make sure existing content can not be seen
   		((this.options.useTabs)?$(this.options.contentPrefix+tab.id):$(tab.id)).setStyles({
   			display:'none',
   			float:'left'
   		});
   		
// Move the tab content into our display area.  If scrolling is required we must make sure the dimensions are correct
   		var j = (this.options.useTabs)?$(this.options.contentPrefix+tab.id):$(tab.id);
			var mySize  = j.measure(function(){
		    return this.getScrollSize();
			});
				if((/_y/i).test(this.options.display['effect'])) {
					j.setStyles({'width': myWidth + 'px', 'height':(this.options.allowResize)?'auto':myHeight + 'px' });
				} else {
					j.setStyles({'width': myWidth + 'px', 'height':(this.options.allowResize)?'auto':myHeight + 'px'});
				}
 // Create cloned content in our target area
   		this.childDivs.push(j.clone(1,1).inject((this.scroll)?this.contentContainer:this.options.contentWrapper));
// get rid of old copy
   		j.dispose(); 

// If scrolling required then we need to get the positions of the tab content so we can move to target point
			if(this.scroll) {
				this.childDivs.getLast().setStyle('display','block');
				this.positions.push(this.childDivs.getLast().getPosition(this.contentContainer)); 
			}			

// Add specified event for tab activation
    	$(tab.id).addEvent(this.options.activationEvent, function(e){
				if(e) e.stop();
				this.closeTab(index);			
    	}.bind(this));			

    }.bind(this));

// Show the content for the current tab
   	$(this.buttons[this.curTab].id).toggleClass(this.options.currentClass); 
		this.showTab();
  },

// Can be used externally for clean close
	destroy: function() {
		this.prevTab = -1;
		this.curTab = 0;
		this.closing = 0;
		this.opening = 0;
		this.positions = [];
		this.childDivs = [];
		this.buttons = [];
		if(!this.options.disableKeys) {
			if(MooTools.version>=1.3) this.myMTKeyboard.relinquish();
		}
	},

	finishOpen: function() {
		this.fireEvent('onOpen').callChain();
		this.opening =  0;
	},

	finishClose: function() {
		this.fireEvent('onClose').callChain();
		this.closing = 0;
		this.showTab();
	},

	/*
	Property: showTab
		Show the content of the tab
	*/	
	showTab: function(){
		this.opening = 1;
		this.childDivs[this.curTab].setStyle('display', 'block');
		if(!this.options.allowResize) {this.childDivs[this.curTab].setStyle('overflow', 'hidden');}
		if(this.options.allowResize) {
			if((/_y/i).test(this.options.display['effect']))
				$(this.options.contentWrapper).setStyle('width', this.childDivs[this.curTab].getSize().x); // sets the height of currrent tab content so that each one can be different size
			else {
				$(this.options.contentWrapper).setStyle('height', this.childDivs[this.curTab].getSize().y); // sets the height of currrent tab content so that each one can be different size
				if(!this.scroll)
					$(this.options.contentWrapper).setStyle('height', 'auto'); // don't know why I have to put this here yet but am investigating
			}
		} else {
			$(this.options.contentWrapper).setStyle('height', 'auto'); // don't know why I have to put this here yet but am investigating
		}
		
		switch(this.options.display['effect']) {
			case 'scroll_y':
			case 'scroll_x':
				this.tweens.scroll.cancel();
				this.tweens.scroll.start(this.positions[this.curTab].x,this.positions[this.curTab].y).chain(this.finishOpen.bind(this));
				break;
						
			case 'fade':
				this.tweens.fade.start(1).chain(this.finishOpen.bind(this));
				break;

			default:
				this.finishOpen();
				break;
		}
	},

	/*
	Property: closeTab
		Hide the content of the tab
	*/	
	closeTab: function(i){
		if(i == this.curTab) return;
		this.closing = 1;
   	$(this.buttons[this.curTab].id).toggleClass(this.options.currentClass);
   	$(this.buttons[i].id).toggleClass(this.options.currentClass);
		this.prevTab = this.curTab;
		this.curTab = i;

		switch(this.options.display['effect']) {
			case 'fade':
				this.tweens.fade.start(0).chain(this.finishClose.bind(this));
				break;

			default:
				this.finishClose();
				break;
		}
	},

	/*
	Property: showNext
		show next slide
	*/	
	showNext: function(){
		if(this.curTab < this.buttons.length-1)
			this.closeTab(this.curTab+1);			
		else
			this.closeTab(0);			
	},

	/*
	Property: showPrev
		show previous slide
	*/	
	showPrev: function(){
		if(this.curTab > 0)
			this.closeTab(this.curTab-1);			
		else 
			this.closeTab(this.buttons.length-1);			
	},
	
	/*
	Property: setupButtons
		Configure carousel buttons
	*/	
	setupButtons: function(){
		if ($(this.options.buttonNextSelector) && $(this.options.buttonPrevSelector)) {
			$(this.options.buttonPrevSelector).addEvent('click', function () {
				this.showPrev();
			}.bind(this));
			$(this.options.buttonNextSelector).addEvent('click', function () {
				this.showNext();
			}.bind(this));
		} 
	}

});

