/*!
* @file
* @brief    sigplus Image Gallery Plus image slider engine with MooTools
* @author   Levente Hunyadi
* @version  1.2.6
* @remarks  Copyright (C) 2009-2010 Levente Hunyadi
* @remarks  Licensed under GNU/GPLv3, see http://www.gnu.org/licenses/gpl-3.0.html
* @see      http://hunyadi.info.hu/projects/sigplus
*/

/*
* sigplus Image Gallery Plus plug-in for Joomla
* Copyright 2009-2010 Levente Hunyadi
*
* sigplus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sigplus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Initialize image slider.
*/	
function imageSlider(gallery, settings) {
	Element.extend({
		getOuterSize: function () {
			var size = this.getSize().size;
			return {
				width: size.x + this.getStyle('margin-left').toInt() + this.getStyle('margin-right').toInt(),  // width with padding and border
				height: size.y + this.getStyle('margin-top').toInt() + this.getStyle('margin-bottom').toInt()  // height with padding and border
			};
		}
	});

	/**
	* Maximum computed size of elements in collection including border and padding width.
	*/
	Elements.extend({
		getMaxOuterSize: function() {
			var w = 0;
			var h = 0;
			this.each( function(el) {
				var totalsize = el.getOuterSize();
				w = Math.max(w, totalsize.width);
				h = Math.max(h, totalsize.height);
			});
			return { width: w, height: h };
		}
	});

	// default configuration properties
	var defaults = {
		rowCount: 1,                // number of rows per slider page
		columnCount: 4,             // number of columns per slider page
		showButtons: true,          // whether to show navigation buttons
		showLinks: true,            // whether to show navigation links
		showPageCounter: true,      // whether to show page counter
		showOverlayButtons: true,   // whether to show navigation buttons that overlay image thumbnails
		alignment: 'left',          // 'left' (default), 'center' or 'right'
		orientation: 'horizontal',  // 'horizontal' (default) or 'vertical'
		navigation: 'top',          // 'top' (default), 'bottom' or 'both'
		firstText: 'First',         // the text of the navigate to first link
		prevText: 'Previous',       // the text of the navigate to previous link
		nextText: 'Next',           // the text of the navigate to next link
		lastText: 'Last',           // the text of the navigate to last link
		pageText: '%1$d of %2$d',   // the content to replace "image 1 of 2" with %1$d and %2$d for placeholders
		duration: 800               // duration for scroll animation [ms]
	};
	settings = $extend(defaults, settings);
	if (settings.itemCount) {  // number of items per slider page set explicitly
		switch (settings.orientation) {
			case 'vertical':
				settings.rowCount = settings.itemCount;
				settings.columnCount = 1;
				break;
			default:  // case 'horizontal':
				settings.rowCount = 1;
				settings.columnCount = settings.itemCount;
		}
	}

	var itemDimensions;             // maximum width and height of items in viewport
	var sliderDimensions;
	var viewportDimensions;
	var sliderIndexPosition = 0;    // index of item in slider taking the current first position

	/**
	* Align an element in parent container according to alignment settings.
	*/
	function _align(el) {
		switch (settings.alignment) {
			case 'center':
				el.addClass('imageSliderCenter'); break;
			case 'right':
				el.addClass('imageSliderRight'); break;
			default:  // left
				el.addClass('imageSliderLeft');
		}
	}
	
	/**
	* Get dimensions for image slider items.
	*/
	function _getItemDimensions() {
		var listitems = gallery.getElements('li');
		var images = gallery.getElements('li img');
		if ( images.length == listitems.length ) {  // use image dimensions if list has only images
			return images.getMaxOuterSize();
		} else {
			return listitems.getMaxOuterSize();
		}
	}
	
	/**
	* Setup slider viewport.
	*/
	function _setup() {
		gallery.addClass('imageSlider');
		switch (settings.alignment) {
			case 'left':
				gallery.addClass('imageSliderLeft'); break;
			case 'right':
				gallery.addClass('imageSliderRight'); break;
		}

		// add items to a scrollable viewport ribbon
		var viewportarea = gallery.getElement('div.imageSliderViewportArea');
		if (!viewportarea) {
			var viewportarea = new Element('div', {
				'class': 'imageSliderViewportArea'
			});
			viewportarea.injectBefore(gallery.getElement('ul'));
			viewportarea.adopt(gallery.getElement('ul'));
		}
		viewportarea.addClass('imageSliderScrollableViewportArea');

		// wrap items to show in viewport window, which has fixed size and hides overflowing dimensions of sliding ribbon
		var viewport = gallery.getElement('div.imageSliderViewport');
		if (!viewport) {
			var viewport = new Element('div', {
				'class': 'imageSliderViewport'
			});
			viewport.injectBefore(viewportarea);
			viewport.adopt(viewportarea);
		}
		viewport.addClass('imageSliderScrollableViewport');

		itemDimensions = _getItemDimensions();
		viewportDimensions = {
			width: settings.columnCount * itemDimensions.width,
			height: settings.rowCount * itemDimensions.height
		};
		var count = gallery.getElements('li').length;
		switch (settings.orientation) {
			case 'vertical':
				sliderDimensions = {
					width: settings.columnCount * itemDimensions.width,
					height: Math.ceil(count / settings.columnCount) * itemDimensions.height
				};
				break;
			default:  // case 'horizontal':
				sliderDimensions = {
					width: Math.ceil(count / settings.rowCount) * itemDimensions.width,
					height: settings.rowCount * itemDimensions.height
				};
		}
		
		gallery.getElements('li').each(function(li) {
			// resize list items to maximum item width and height
			li.setStyles({
				width: itemDimensions.width,
				height: itemDimensions.height
			});
			var imagesize = li.getElement('img').getOuterSize();
			var outerwrapper = new Element('div', {
				'class': 'imageSliderAlignment',
				'styles': {
					width: imagesize.width,
					height: imagesize.height
				}
			});
			var innerwrapper = new Element('div', {
				'class': 'imageSliderAlignment',
				'styles': {
					width: imagesize.width,
					height: imagesize.height
				}
			});
			innerwrapper.adopt(li.getChildren());
			innerwrapper.injectInside(outerwrapper);
			outerwrapper.injectInside(li);
		});

		// resize sliding ribbon in viewport
		viewportarea.removeClass('imageSliderViewportAreaFlow');
		if (settings.rowCount > 1 && settings.columnCount > 1) {
			viewportarea.addClass('imageSliderViewportAreaMatrix');
		} else {
			switch (settings.orientation) {
				case 'vertical':
					viewportarea.addClass('imageSliderViewportAreaColumn');
					break;
				default:  // case 'horizontal':
					viewportarea.addClass('imageSliderViewportAreaRow');
			}
		}
		viewportarea.setStyles({
			width: sliderDimensions.width,
			height: sliderDimensions.height
		});

		// resize viewport
		viewport.setStyles({
			width: viewportDimensions.width,
			height: viewportDimensions.height
		});

		_align(viewport);
		_setupNavigation();
	}	

	function _setupNavigation() {
		if (settings.showButtons || settings.showLinks || settings.showPageCounter) {
			var pageCount = Math.ceil( gallery.getElements('li').length / (settings.rowCount * settings.columnCount) );
			var navFirst = '<a class="pg_first" href="#" title="'+ settings.firstText +'">' + (settings.showButtons ? '<span></span>' : '') + (settings.showLinks ? settings.firstText : '') +'</a>';  // span is a floatable placeholder element that has navigation image as background
			var navPrev = '<a class="pg_prev" href="#" title="' + settings.prevText + '">' + (settings.showButtons ? '<span></span>' : '') + (settings.showLinks ? settings.prevText : '') + '</a>';
			var navNext = '<a class="pg_next" href="#" title="' + settings.nextText + '">' + (settings.showLinks ? settings.nextText : '') + (settings.showButtons ? '<span></span>' : '') + '</a>';
			var navLast = '<a class="pg_last" href="#" title="' + settings.lastText + '">' + (settings.showLinks ? settings.lastText : '') + (settings.showButtons ? '<span></span>' : '') + '</a>';
			var navCounter = settings.showPageCounter ? settings.pageText.replace('%1$d', '<span class="current">1</span>').replace('%2$d', '<span class="total">'+ pageCount +'</span>') : '';
			var nav = new Element('div', {
				'class': 'imageSliderPaging',
				'styles': {
					width: viewportDimensions.width
				}
			});
			nav.setHTML(navFirst + ' ' + navPrev + ' ' + navCounter + ' ' + navNext + ' ' + navLast);
			_align(nav);

			switch (settings.navigation) {
				case 'both':
					nav.clone().injectTop(gallery);
					nav.injectInside(gallery);
					break;
				case 'top':
					nav.injectTop(gallery);
					break;
				default:  // case 'bottom':
					nav.injectInside(gallery);
			}
		}

		if (settings.showOverlayButtons) {
			var navOverlayPrev = new Element('div', {
				'class': 'pg_prev',
				'href': '#'
			});
			var navOverlayPrevButton = new Element('div', {
				'class': 'pg_prev',
				'title': settings.prevText,
				'styles': {
					'visibility': 'hidden'
				}
			});
			navOverlayPrevButton.injectInside(navOverlayPrev);
			var navOverlayNext = new Element('div', {
				'class': 'pg_next',
				'href': '#'
			});
			var navOverlayNextButton = new Element('div', {
				'class': 'pg_next',
				'title': settings.nextText,
				'styles': {
					'visibility': 'hidden'
				}
			});
			navOverlayNextButton.injectInside(navOverlayNext);
			switch (settings.orientation) {
				case 'vertical':
					if (itemDimensions.height < 120) {
						navOverlayPrev.addClass('pg_top_small');
						navOverlayNext.addClass('pg_bottom_small');
					} else {
						navOverlayPrev.addClass('pg_top_large');
						navOverlayNext.addClass('pg_bottom_large');
					}
					break;
				default:  // case 'horizontal':
					if (itemDimensions.width < 120) {
						navOverlayPrev.addClass('pg_left_small');
						navOverlayNext.addClass('pg_right_small');
					} else {
						navOverlayPrev.addClass('pg_left_large');
						navOverlayNext.addClass('pg_right_large');
					}
			}
			var viewport = gallery.getElement('div.imageSliderViewport');
			navOverlayNext.injectTop(viewport);
			navOverlayPrev.injectTop(viewport);
			
			navOverlayPrev.addEvent('mouseenter', function () {
				navOverlayPrevButton.setStyle('visibility','visible');
			});
			navOverlayPrev.addEvent('mouseleave', function () {
				navOverlayPrevButton.setStyle('visibility','hidden');
			});
			navOverlayNext.addEvent('mouseenter', function () {
				navOverlayNextButton.setStyle('visibility','visible');
			});
			navOverlayNext.addEvent('mouseleave', function () {
				navOverlayNextButton.setStyle('visibility','hidden');
			});
		}

		if (settings.showButtons || settings.showLinks || settings.showOverlayButtons) {
			gallery.getElements('.pg_first').each(function (a) {
				a.addEvent('click', function (event) {
					_scroll('first'); new Event(event).stop();
				});
			});
			gallery.getElements('.pg_prev').each(function (a) {
				a.addEvent('click', function (event) {
					_scroll('prev'); new Event(event).stop();
				});
			});
			gallery.getElements('.pg_next').each(function (a) {
				a.addEvent('click', function (event) {
					_scroll('next'); new Event(event).stop();
				});
			});
			gallery.getElements('.pg_last').each(function (a) {
				a.addEvent('click', function (event) {
					_scroll('last'); new Event(event).stop();
				});
			});
		}
	}
	
	/**
	* Execute image slider animation.
	*/
	function _scroll(dir) {
		var p = settings.rowCount * settings.columnCount;
		var n = gallery.getElements('li').length;  // total number of items in slider
		var t = (n%p ? n-n%p : n-p);               // greatest possible index for the first position
		switch (dir) {
			case 'first':
				sliderIndexPosition = 0; break;
			case 'prev':
				sliderIndexPosition = (sliderIndexPosition >= p) ? sliderIndexPosition - p : 0; break;
			case 'next':
				sliderIndexPosition = (sliderIndexPosition < t) ? sliderIndexPosition + p : t; break;
			case 'last':
				sliderIndexPosition = t;  break;
			 default:
				return;
		};
		switch (settings.orientation) {
			case 'vertical':
				var prop = 'top';
				var off = -(sliderIndexPosition / settings.columnCount * itemDimensions.height);
				break;
			default:  // case 'horizontal':
				var prop = 'left';
				var off = -(sliderIndexPosition / settings.rowCount * itemDimensions.width);
		}
		var viewportarea = gallery.getElement('div.imageSliderViewportArea');
		if (window.ie) {  // IE8 triggers an error with Fx.Style animation
			viewportarea.setStyle(prop, off);
		} else {
			var fx = new Fx.Style(viewportarea, prop, {duration:settings.duration});
			fx.start(off);
		}
		_updatePaging();
	}

	/**
	* Update which navigation links are enabled.
	*/
	function _updatePaging() {
		var p = settings.rowCount * settings.columnCount;
		var n = gallery.getElements('li').length;  // total number of items in slider
		var t = (n%p ? n-n%p : n-p);               // greatest possible index for the first position
		if (settings.showPageCounter) {
			gallery.getElements('span.current').each(function (el) {
				el.setText(Math.ceil(sliderIndexPosition / (settings.rowCount*settings.columnCount)) + 1);
			});
		}
		if (settings.showButtons || settings.showLinks || settings.showOverlayButtons) {
			if (sliderIndexPosition > 0) {  // show "prev" link if there is a sufficient number of items
				gallery.getElements('.pg_first').each(function (el) {
					el.removeClass('imageSliderPagingDisabled');
				});
				gallery.getElements('.pg_prev').each(function (el) {
					el.removeClass('imageSliderPagingDisabled');
				});
			} else {
				gallery.getElements('.pg_first').each(function (el) {
					el.addClass('imageSliderPagingDisabled');
				});
				gallery.getElements('.pg_prev').each(function (el) {
					el.addClass('imageSliderPagingDisabled');
				});
			}
			if (sliderIndexPosition < t) {  // show "next" link if there is a sufficient number of items
				gallery.getElements('.pg_next').each(function (el) {
					el.removeClass('imageSliderPagingDisabled');
				});
				gallery.getElements('.pg_last').each(function (el) {
					el.removeClass('imageSliderPagingDisabled');
				});
			} else {
				gallery.getElements('.pg_next').each(function (el) {
					el.addClass('imageSliderPagingDisabled');
				});
				gallery.getElements('.pg_last').each(function (el) {
					el.addClass('imageSliderPagingDisabled');
				});
			}
		}
	}

	_setup();
	_updatePaging();
};
