
var Jp_Tab = new Class({
	Implements: [Options, Events],
	links: null,
	currentLink: null,
	next: null,
	fx: null,
	fx2: null,
	timeoutId: null,
	fadeLinks: false, //not implemented
	options: {
		show: -1, //start with this element
		delay: 6000,
		duration: 100,
		linkActiveClass: 'on',
		targetHiddenClass: 'hidden',
		defaultTab: null, //element displayed when all tabs are hidden
		property: 'opacity',
		classToHide: null, //a css rule will be written to hide elements with this class while the DOM loads
		links: {
			color: null,
			selectedColor: null,
			hoverColor: null
		},
		resize: true,
		loop: false,
		randomize: false
	},
	initialize: function(options) {
		this.addOptions(options);
		this.beforeDomLoad();
	},
	addOptions: function(options) {
		this.setOptions(options);
	},
	start: function(menu) {
		if (typeof menu == 'string') {
			menu = $(menu);
		}
		if (!menu) return;
		this.links = menu.get('tag') == 'ul' ? menu.getElements('li a') : menu;
		
		if (this.options.links.color && this.options.links.selectedColor && this.options.links.hoverColor) {
			this.fadeLinks = true;
		}
		this.prepare();
		this.resume();
	},
	prepare: function() {
		this.afterDomLoad();
		if (this.options.randomize) {
			this.links.shuffle();
		}
		if (typeof this.options.defaultTab != 'undefined' && this.options.defaultTab) {
			this.options.defaultTab = $(this.options.defaultTab);
		}
		this.currentLink = this.options.show >= 0 ? this.options.show : -1;
		this.setEvents();
		var targetInUrl = window.location.toString().split('#');
		targetInUrl = targetInUrl.length > 1 ? targetInUrl[1] : null;
		if (targetInUrl) {
			this.options.loop = false;
		}
		for (var i = 0; i < this.links.length; i++) {
			var target = this.getTarget(this.links[i]);
//			if (target && this.options.resize) {
//				target.setStyle('height', target.getStyle('height')); //ensure height is set and not on "auto".
//			}
			if (i == this.currentLink && targetInUrl == null || this.links[i].get('href') == '#' + targetInUrl) {
				this.currentLink = i;
				this.links[i].addClass(this.options.linkActiveClass);
				if (target) {
					target.removeClass(this.options.targetHiddenClass);
				}
			}
			else {
				this.links[i].removeClass(this.options.linkActiveClass);
				if (target) {
					target.addClass(this.options.targetHiddenClass);
					new Fx.Tween(target, this.options).set(0);
				}
			}
		}
		if (this.currentLink >= 0) {
			this.currentLink = this.links[this.currentLink];
			if (this.options.defaultTab) {
				this.options.defaultTab.addClass(this.options.targetHiddenClass);
			}
		}
		else {
			this.currentLink = null;
			if (this.options.defaultTab) {
				this.options.defaultTab.removeClass(this.options.targetHiddenClass);
				if (this.options.resize) {
					this.options.defaultTab.setStyle('height', this.options.defaultTab.getStyle('height')); //ensure height is set and not on "auto"
				}
			}
		}
	},
	setEvents: function() {
		this.links.each(function(e) {
			e.addEvent('click', function(evt) {
				if (evt.target == this.currentLink) {
					evt.stop();
					return;
				}
				this.show(evt.target);
			}.bindWithEvent(this));
			
			var target = this.getTarget(e);
			if (target) {
				target.addEvent('mouseenter', function(evt) {
					this.pause();
				}.bindWithEvent(this));
				target.addEvent('mouseleave', function(evt) {
					this.resume();
				}.bindWithEvent(this));
			}
			
			if (this.fadeLinks) {
				e.addEvent('mouseenter', function(evt) {
					evt.stop();
					$(evt.target).setStyle('color', this.options.links.hoverColor);
				}.bindWithEvent(this));
				e.addEvent('mouseleave', function(evt) {
					evt.stop();
					var target = $(evt.target);
					$(evt.target.setStyle('color', target.hasClass(this.options.linkActiveClass) ? this.options.links.selectedColor : this.options.links.color));
				}.bindWithEvent(this));
			}
		}, this);
		this.addEvent('fadedOut', this.onFadedOut.bindWithEvent(this));
		this.addEvent('fadedIn', this.onFadedIn.bindWithEvent(this));
		this.addEvent('resized', this.onResized.bindWithEvent(this));
		this.addEvent('next', this.onNext.bindWithEvent(this));
	},
	show: function(link) {
		this.next = $(link);
		if (this.next == this.currentLink) return;
		if (this.timeoutId) {
			$clear(this.timeoutId);
		}
		//handle link classes
		this.next.addClass(this.options.linkActiveClass);
		if (this.fadeLinks) {
			this.next.setStyle('color', this.links.selectedColor);
		}
		if (this.currentLink) {
			this.currentLink.removeClass(this.options.linkActiveClass);

			if (this.fadeLinks) {
				this.currentLink.setStyle('color', this.options.linkSelectedColor);
				var options = {};
				$extend(options, this.options);
				options.property = 'color';
				options.duration = this.options.duration * 2;
				this.linkFx = new Fx.Tween(this.currentLink, options).start(this.options.links.selectedColor, this.options.links.color);
			}
		}
		
		if (this.fx) {
			this.fx.cancel();
		}
		if (this.fx2) {
			this.fx2.cancel();
		}
		
		//hide current tab
		var currentTab = this.getTarget(this.currentLink);
		currentTab = currentTab ? currentTab : this.options.defaultTab;
		if (currentTab) {
			var options = {};
			$extend(options, this.options);
			options.onComplete = function() {
				this.fireEvent('fadedOut');
			}.bindWithEvent(this);
			var currentOpacity = currentTab.getStyle('opacity');
			this.fx = new Fx.Tween(currentTab, options).start(currentOpacity, 0);
		}
		else {
			this.fireEvent('fadedOut');
		}
	},
	onFadedOut: function() {
		//start resizing
		//hide current tab
		var currentTab = this.getTarget(this.currentLink);
		currentTab = currentTab ? currentTab : this.options.defaultTab;
		this.currentLink = this.next;
		this.next = null;
		var nextTab = this.getTarget(this.currentLink);
		
		if (!nextTab) return;
		
		nextTab.removeClass(this.options.targetHiddenClass);
		if (currentTab) {
			if (this.options.resize) {
				var currentHeight = currentTab.getSize().y + 'px';
				var newHeight = nextTab.getSize().y + 'px';
//				var currentHeight = currentTab.getStyle('height');
//				var newHeight = nextTab.getStyle('height');
//				console.log(currentHeight, newHeight);
				nextTab.setStyle('height', currentHeight);
			}
			
			currentTab.addClass(this.options.targetHiddenClass);
		}
			
		if (this.options.resize) {
			var options = {};
			$extend(options, this.options);
			options.property = 'height';
			options.onComplete = function() {
				this.fireEvent('resized');
			}.bindWithEvent(this);
			this.fx = new Fx.Tween(nextTab, options).start(currentHeight, newHeight);
		}
		
		var options = {};
		$extend(options, this.options);
		options.onComplete = function() {
			this.fireEvent('fadedIn');
		}.bindWithEvent(this);
		var currentOpacity = nextTab.getStyle('opacity');
		this.fx2 = new Fx.Tween(nextTab, options).start(0, 1);
	},
	onFadedIn: function() {
		this.resume();
	},
	onResized: function() {
		var currentTab = this.getTarget(this.currentLink);
		if (currentTab) {
			currentTab.setStyle('height', 'auto');
		}
	},
	getTarget: function(link) {
		link = $(link);
		if (link) {
			var href = link.get('href');
			href = href.split('#');
			if (href.length > 1 && href[1]) {
				return $(href[1]);
			}
		}
		return null;
	},
	resume: function() {
		if (this.options.loop) {
			this.timeoutId = (function() {
				this.fireEvent('next');
			}.bind(this)).delay(this.options.delay, this);
		}
	},
	onNext: function() {
		if (this.fx) {
			this.fx.cancel();
		}
		if (this.fx2) {
			this.fx2.cancel();
		}
		
		var currentLinkIndex = this.getLinkIndex(this.currentLink);
		currentLinkIndex = (++currentLinkIndex >= this.links.length) ? 0 : currentLinkIndex;
		this.show(this.links[currentLinkIndex]);
	},
	pause: function() {
		if (this.options.loop) {
			if (this.timeoutId) {
				$clear(this.timeoutId);
			}
			if (this.fx) {
				this.fx.cancel();
				this.fx.set(this.fx2 ? 0 : 1);
				this.fx = null;
			}
			if (this.v) {
				this.fx2.cancel();
				this.fx2.set(1);
				this.fx2 = null;
			}
		}
	},
	getLinkIndex: function(link) {
		for (var i = 0; i < this.links.length; i++) {
			if (this.links[i] == link) {
				return i;
			}
		}
		return 0;
	},
	beforeDomLoad: function() {
		//avoid flickering in IE
		if (this.options.classToHide) {
			document.write('<style type="text/css">.' + this.options.classToHide + ' {display: none;}</style>');
		}
	},
	afterDomLoad: function() {
		if (this.options.classToHide) {
			$$('.' + this.options.classToHide).removeClass(this.options.classToHide);
		}
	}
});

