/*****************************************************************************
 *
 * Copyright © 2009 Simon Robb
 *
 * All rights reserved
 *
 ****************************************************************************/

(function ($) {
	$.fn.Slideshow = function (params) {
		var defaults = {
			initialIndex: 0,					// The panel to start on by index
			autoCycle: true,					// Begin scrolling on init
			cycleInterval: 8000,				// How long between scrolls
			panelWidth: '100',					// Width of a panel
			panelHeight: '100',					// Height of a panel
			panelsVisible: 1,					// Number of panels visible at once
			length: 700,						// Length of animation
			onChangeBegin: function (obj) {},	// Called at the beginning of panel change
			onChangeComplete: function (obj) {}	// Called after changing panel is complete
        };
        
        var settings = {};
        settings = $.extend({}, defaults, params);
		
        // return this;
        return this.each(function (i) {
            var $$ = $(this);
			settings.element = $$;

		   	var ss = new Slideshow (settings);
		
			// Store the carousel for public interaction
			$$.data ('slideshow', ss);
		});
	};
	
	/**
	 * The class constructor
	 * @constructor
	 */
	window.Slideshow = function (settings) {
		/**
		 * Class settings
		 */
		this._settings = settings;
		
		/**
		 * Member variables
		 */
		this._panels = this._settings.element.find ('li');
		this._index = 0;
		this._value = 0;
		this._count = this._panels.length;
		
		// Ensure that items are positioned correctly
		this._settings.element
			.css ('position', 'relative')
			.css ('width', this._settings.panelWidth)
			.css ('height', this._settings.panelHeight);
			
		this._panels
			.css ('position', 'absolute')
			.css ('zIndex', 0)
			.css ('opacity', 0);
		
		// Functionality
		var ss = this;
		if (this._settings.nextButton) 
			this._settings.nextButton.click (function () {ss.next(); ss.stop ()});
		if (this._settings.prevButton)
			this._settings.prevButton.click (function () {ss.previous(); ss.stop ()});
		
		// Show the initial panel
		if (this._settings.initialValue) {
			index = 0;
			$.each (this._panels, function (i,panel) {
				if ($(panel).attr ('value') == car._settings.initialValue)
					index = i;
			});
			this.goto (index, true);
		} else {
			this.goto (this._settings.initialIndex, true);
		}
		
		// Begin cycling if necessary
		if (this._settings.autoCycle)
			this.play ();
	};
	
	Slideshow.prototype = {
		next: function () {
			if (this._index >= this._count - 1 - this._settings.panelsVisible + 1) {
				this.first ();
			} else {
				this.goto (this._index + 1);
			}
		},
		
		previous: function () {
			if (this._index <= 0) {
				this.last ();
			} else {
				this.goto (this._index - 1);
			}
		},
		
		first: function () {
			this.goto (0);
		},
		
		last: function () {
			this.goto (this._count - this._settings.panelsVisible);
		},
		
		goto: function (i, noAnimate) {
			var $$ = this;
			
			// Call callback function
			$$._settings.onChangeBegin ($.extend ({}, $$, {_index: i}));
			
			if (noAnimate) {
				this._panels
					.eq(this._index)
					.css ('opacity', 0)
					.css ('zIndex', 0);
					
				this._panels
					.eq(i)
					.css ('opacity', 1)
					.css ('zIndex', 1);

				// Call callback function
				$$._settings.onChangeComplete ($.extend ({}, $$, {_index: i}));	
				
			}
				
			else {
				var oldPanel = this._panels.eq(this._index);
				var newPanel = this._panels.eq(i);
				
				newPanel
					.stop ()
					.css ('zIndex', 2)
					.animate ({
							'opacity': 1
						},
						this._settings.length,
						function () {
							oldPanel
								.css ('opacity', 0)
								.css ('zIndex', 0);
							newPanel
								.css ('zIndex', 1);
								
							// Call callback function
							$$._settings.onChangeComplete ($.extend ({}, $$, {_index: i}));
						}
					);
				}
			
			// Update class index
			this._index = i;
			
			// Update class value
			this._value = $(this._panels[i]).attr ('value');
			
			// Reflect change in paging
			if (this._settings.pagingControl) 
				this._settings.pagingControl
					.find ('li')
					.removeClass ('current')
					.eq (i)
					.addClass ('current');
		},
		
		play: function () {
			var car = this;
			
			// Reset if necessary
			this.stop ();
				
			this._timer = setInterval (function () { car.next (); }, this._settings.cycleInterval);
		},
		
		stop: function () {
			if (this._timer)
				clearInterval (this._timer);
		},
		
		getIndex: function () {
			return this._index;
		},
		
		getValue: function () {
			return this._value;
		}
	};
})(jQuery);

