/**
 * @author Nathan Kelly - http://www.nathan-kelly.com/
 * @copyright 2010 Nathan Kelly
 * @package nk-multigliders
 * @version 1.0.4
 * @url http://projects.nathan-kelly.com/nk-multigliders/
 * @dependencies
 * 	prototype.js 1.6.0.3+ (http://www.prototypejs.org/)
 *	scriptaculous.js 1.8.2+ (http://script.aculo.us/)
 * @license
 *	Creative Commons Attribution 2.5 Australia License
 *	http://creativecommons.org/licenses/by/2.5/au/
 */

nk_init_multigliders = Class.create({
	initialize: function (o) {
		this.o = Object.extend({
			_rootClass:		'nk-glider-panels',	// the main element that contains the panels
			_panelClass:	'nk-glider-panel',	// the panel elements
			_contentClass:	'nk-glider-content',// the panel content element
			_navClass:		'nk-glider-nav',	// if navigation is enabled this is the element that contains the navigation
			_toggleClass:	'nk-glider-toggle',	// if navigation is enabled these are the toggles that do stuff
			_duration:		0.5,				// the time it takes for a single panle to move from start to finish (can be overridden with class="duration-[value]")
			_frequency:		10,					// the time between movements (can be overridden with class="frequency-[value]")
			_autoGlide:		0,					// should the glider start on dom ready? (default === false but can be overridden with class="autoglide" which === true)
			_glideType:		'a',				// default = a. options: a, b, c, d & fader (override with glidetype-[value])
			_autoRestart:	1,					// explanation coming soon
			_restartDelay:	2,					// explanation coming soon
			_initialPanel:	0,					// which panel should we start on? (default === 0 wich is the first one but can be overridden with class="initialpanel-[value]")
			_overrideLinks:	0,					// makes the entire panel clickable (links to one location), handy for panels that contain multiple elements
		}, o || {});
		// thats it dont edit below unless you need to
		if ( !$$('.' + this.o._rootClass) ) { return; }
		var roots = $$('.' + this.o._rootClass);
		for ( var i = 0; i < roots.length; i++ ) {
			new nk_multigliders(roots[i], this.o);
		}
	}
});

nk_multigliders = Class.create({
	initialize: function (glider, o) {
		this.o 				= o;
		this.scrolling		= false;
		this.scroller		= glider;
		// set options defaults
		this.duration		= this.o._duration;
		this.frequency		= this.o._frequency;
		this.autoGlide		= this.o._autoGlide;
		this.glideType		= this.o._glideType;
		this.autoRestart	= this.o._autoRestart;
		this.restartDelay	= this.o._restartDelay * 1000;
		this.initialPanel	= this.o._initialPanel;
		this.overrideLinks	= this.o._overrideLinks;
		// start options overrides
		this.opts			= this.scroller.className.split(' ');
		// get opts from className array
		for ( i = 0; i < this.opts.length; i++ ) {
			if ( this.opts[i].match(/duration/) ) { this.duration = Number( this.opts[i].substring( this.opts[i].indexOf('-') + 1, this.opts[i].length ).replace('_', '.') ); }
			if ( this.opts[i].match(/frequency/) ) { this.frequency = Number( this.opts[i].substring( this.opts[i].indexOf('-') + 1, this.opts[i].length ).replace('_', '.') ) }
			if ( this.opts[i].match(/autoglide/) ) { this.autoGlide = 1; }
			if ( this.opts[i].match(/glidetype-fader/) ) {
				this.glideType = 'fader';
			} else if ( this.opts[i].match(/glidetype/) ) {
				this.glideType = this.opts[i].substring( this.opts[i].indexOf('-') + 1, this.opts[i].length )
			}
			if ( this.opts[i].match(/autorestart/) ) { this.autoRestart = 1; }
			if ( this.opts[i].match(/restartDelay/) ) { this.restartDelay = Number( this.opts[i].substring( this.opts[i].indexOf('-') + 1, this.opts[i].length ) * 1000 ) }
			if ( this.opts[i].match(/initialpanel/) ) { this.initialPanel = Number( this.opts[i].substring( this.opts[i].indexOf('-') + 1, this.opts[i].length ).replace('_', '.') ); }
			if ( this.opts[i].match(/override-links/) ) { this.overrideLinks = 1; }
			if ( this.opts[i].match(/continuous/) ) { this.continuous = true; }
		}
		// end options overrides
		this.content		= this.scroller.select('.' + this.o._contentClass)[0];
		this.navigation		= $(this.o._navClass + this.scroller.id.substring(this.scroller.id.lastIndexOf('-'), this.scroller.id.length) );
		this.firstPanel		= this.o._panelClass + this.scroller.id.substring(this.scroller.id.lastIndexOf('-'), this.scroller.id.length) + '-' + this.initialPanel;
		this.panels			= this.scroller.select('.' + this.o._panelClass);
		this.panels.each( function (panel, index) {
			panel._index = index;
		});
		//alert( this.glideType  );
		switch ( this.glideType ) {
			case 'fader':
				// fader [type a: fade-in/fade-out]
				this.panels.invoke('hide');
				$(this.firstPanel).show();
				break;
			case 'c':
				// glider [type c: bottom to top]
				break;
			case 'd':
				// glider [type d: top to bottom]

				break;
			case 'b':
				// glider [type b: left to right]
			default:
				// glider [type a: right to left]
				this.content.setStyle({ width: this._width() + 'px' });
		}
		if ( this.navigation ) {
			this.controls	= this.navigation.select('.' + this.o._toggleClass);
			this.itemised	= this.navigation.className.match(/itemised/) ? true : false;
			this.complex	= this.navigation.className.match(/complex/) ? true : false;
			this.events = {
				click: this.click.bind(this),
				clickPanel: this.clickPanel.bind(this)
			};
			if ( this.overrideLinks ) {
				this.panels.invoke( 'observe', 'click', this.events.clickPanel );
			}
			this.controls.invoke( 'observe', 'click', this.events.click );
		}
		this.moveTo( this.firstPanel , this.scroller );
		if ( this.autoGlide ) {
			//this.start(1);
			Event.observe( window, 'load', this.start.bindAsEventListener( this ) );
		}
	},

	clickPanel: function (event) {
		// allows all elemnts of a panel to link to one location
		var form = Event.findElement(event, 'form');
		if ( !form ) {
			Event.stop(event);
			var element = Event.findElement(event, 'li');
			var href = element.down('a').href;
			window.location = href;
		} else {
			this.stop();
			this.restart = null;
		}
	},

	click: function (event) {
		Event.stop(event);
		var element = Event.findElement(event, 'a');
		if ( this.scrolling ) {
			this.scrolling.cancel();
		}
		if ( this.itemised ) {
			this.moveTo( element.href.split("#")[1], this.scroller, {
				duration: this.duration
			});
		} else if ( this.complex ) {
			if ( element.id.match(/prev/) || element.id.match(/next/) ) {
				element.id.match(/prev/) ? this.movePrev() : this.moveNext();
			} else {
				this.moveTo( element.href.split("#")[1], this.scroller, {
					duration: this.duration
				});
			}
		} else if ( element.id.match(/prev/) || element.id.match(/next/) ) {
			element.id.match(/prev/) ? this.movePrev() : this.moveNext();
		}
		if ( this.autoGlide && this.autoRestart ) {
			this.stop();
			if (this.restart != null) {
				clearTimeout(this.restart);
			}
			this.restart = setTimeout( this.update.bind(this), this.frequency * this.restartDelay );
		}
	},

	moveTo: function (element, container) {
		this.current = $(element);
		Position.prepare();
		var co = Position.cumulativeOffset(container), eo = Position.cumulativeOffset($(element));
		var next = this._next();
		var prev = this._prev();
		var append = $(prev);
		switch ( this.glideType ) {
			case 'fader':
				// fader [type a: fade-in/fade-out]
				this.scrolling = new Effect.Appear( this.current, {
					duration: this.duration,
					afterFinish: (function () {
						this.current.show();
						// remove previous panel and re-append it to the panels container
						$(prev).remove();
						this.content.cleanWhitespace().insert({ bottom: append });
						$(append).hide();
					}).bind(this)
				});
				break;
			case 'c':
				// glider [type c: bottom to top]
				this.scrolling = new Effect.BlindUp( this.current, {
					duration: this.duration,
					afterFinish: (function () {
						// remove previous panel and re-append it to the panels container
						$(prev).remove();
						this.content.cleanWhitespace().insert({ bottom: append });
						$(append).show();
					}).bind(this)
				});
				break;
			case 'd':
				// glider [type d: top to bottom]
				// currently unavailable
				break;
			case 'b':
				// glider [type b: left to right]
			default:
				// glider [type a: right to left]
				var can_remove = this.scrolling ? true : false;
				this.scrolling = new Effect.SmoothScroll( container, {
					x: ( eo[0] - co[0] ),
					y: ( eo[1] - co[1] ),
					duration: this.duration
				});
				break;
		}
		if ( this.itemised || this.complex ) {
			var selected = this.controls.each( function (s) {
				$(s).up('li').removeClassName('current');
			});
			if ( this.complex ) {
				selected[this.current._index + 1].up('li').addClassName( 'current' );
			} else {
				selected[this.current._index].up('li').addClassName( 'current' );
			}
		}
		return false;
	},

	_width: function () {
		return ( this.panels[0].getWidth() * this.panels.length );
	},

	_next: function () {
		if ( this.current ) {
			var c = this.current._index;
			var n = ( this.panels.length - 1 == c ) ? 0 : c + 1;
		} else {
			var n = 1;
		}
		return this.panels[n].id;
	},

	_prev: function () {
		if (this.current) {
			var c = this.current._index;
			var p = ( c == 0 ) ? this.panels.length - 1 : c - 1;
		} else {
			var p = this.panels.length - 1;
		}
		return this.panels[p].id;
	},

	moveNext: function () {
		this.moveTo( this._next(), this.scroller );
	},

	movePrev: function () {
		this.moveTo( this._prev(), this.scroller );
	},

	stop: function () {
		clearTimeout( this.timer );
	},

	start: function () {
		this.update();
	},

	update: function () {
		if (this.timer != null) {
			clearTimeout(this.timer);
			this.moveNext();
		}
		this.timer = setTimeout( this.update.bind(this), this.frequency * 1000 );
	}
});

Effect.SmoothScroll = Class.create();
Object.extend( Object.extend( Effect.SmoothScroll.prototype, Effect.Base.prototype ), {
	initialize: function (element) {
		this.element = $(element);
		var options = Object.extend({
			x:    0,
			y:    0,
			mode: 'absolute'
		} , arguments[1] || {}  );
		this.start(options);
	},

	setup: function () {
		this.originalLeft = this.element.scrollLeft;
		this.originalTop = this.element.scrollTop;
		if ( this.options.mode == 'absolute' ) {
			this.options.x -= this.originalLeft;
			this.options.y -= this.originalTop;
		}
	},

	update: function (position) {
		this.element.scrollLeft = this.options.x * position + this.originalLeft;
		this.element.scrollTop  = this.options.y * position + this.originalTop;
	}
});

document.observe('dom:loaded', function () { new nk_init_multigliders(); });

