/**
 * When I noticed the growing popularity of JS-Slide and JS-Fade effects I have
 * decide to develop a plugin for jQuery. This plugin will help you to add thise
 * effects to the site in more simple way.
 * Note: If the mousewheel plugin has been included on the page then the slider will
 * also respond to the mouse wheel.
 *
 * @name jQuery ulSlide plugin
 * @license GPL
 * @version 1.4.8
 * @date January 31, 2011
 * @category jQuery plugin
 * @author Kotelnitskiy Evgeniy (evgennniy@gmail.com)
 * @copyright (c) 2011 Kotelnitskiy Evgeniy (http://4coder.info/en/)
 * @example Visit http://4coder.info/en/code/jquery-plugins/ulslide/ for more informations about this jQuery plugin
 */
(function ($) {
	ulslide_last_id = 0;

	$.fn.ulslide = function (settings) {
		var thisObj = this;
		if (thisObj.length == 0) return false;
		var thisEl = thisObj[0];
		if (!$(thisEl).attr('id')) {
			ulslide_last_id++;
			$(thisEl).attr('id', 'ulslide-' + ulslide_last_id);
		}
		var id = $(thisEl).attr('id');

		// Settings
		settings = $.extend({
			effect: {
				type: 'slide', // slide, fade or carousel (use showCount for carousel)
				axis: 'x',     // x, y
				distance: 20   // Distance between frames
			},
			duration: 600,     // Changing duration
			direction: 'f',    // f, b
			autoslide: false,  // Autoscrolling interval (ms)
			current: 0,

			width: thisObj.width(),
			height: 'auto',    // pixels or 'auto'

			statusbar: true,
			lazyload: false,   // testing
			ajax: false,

			mousewheel: false, // Scroll on "mousewheel"

			// Selectors:
			pager: false,
			nextButton: false,
			prevButton: false,
			pausePlayButton: false,
			printCurrentTo: false,

			//framesOnPage: 2, 
			onAnimateStart: function (settings, thisEl) { },
			onAnimate: function (settings, thisEl) { },
			onAjaxStart: function (settings, thisEl) { },
			onAjaxStop: function (settings, thisEl) { }
		}, settings);

		// Deprecated Options
		if (typeof settings['affect'] != 'undefined') settings['effect']['type'] = settings['affect'];
		if (typeof settings['axis'] != 'undefined') settings['effect']['axis'] = settings['axis'];
		if (typeof settings['padding'] != 'undefined') settings['effect']['distance'] = settings['padding'];
		if (typeof settings['navigator'] != 'undefined') settings['pager'] = settings['navigator'];
		if (typeof settings['print_current'] != 'undefined') settings['printCurrentTo'] = settings['print_current'];
		if (typeof settings['bnext'] != 'undefined') settings['nextButton'] = settings['bnext'];
		if (typeof settings['bprev'] != 'undefined') settings['prevButton'] = settings['bprev'];
		// end Deprecated Options

		if (typeof settings['effect']['distance'] == 'undefined') settings['effect']['distance'] = 20;
		settings['fwidth'] = settings['width'] + settings['effect']['distance'];
		settings['prev'] = settings['current'];
		settings['count'] = $('> *', thisObj).length;

		if (settings['lazyload']) {
			$('img', thisObj).each(function (i) {
				var img = $(this);
				img.attr('rel', img.attr('src'));
				if (i > 0) {
					img.removeAttr("src");
				}
			});
			/*settings['_lazyloaded'][0] = true;*/
		}


		function carouselGetFramePos(i, current) {
			if (i >= settings['effect']['showCount'] - current) {
				var l = settings['count'] - settings['effect']['showCount'];
				var ci = (i + current - settings['effect']['showCount']) - l;
				return ci;
			}
			else return i + current;
		}

		// CSS for elements		
		$('> *', thisObj).each(function (i) {
			var liel = $(this);
			liel.addClass('slide-node slide-node-' + i);
			liel.css("position", 'absolute');
			liel.css("margin", '0');
			liel.css("distance", '0');
			liel.css("width", settings['width']);
			liel.css("overflow", "hidden");

			if (settings['effect']['type'] == 'carousel') {
				var ci = carouselGetFramePos(i, settings['current']);

				liel.css("top", '0');
				liel.css("left", (ci * settings['fwidth']));
			}
			else {
				if (i == settings['current']) {
					liel.css("top", '0');
					liel.css("left", '0');
				}
				else {
					liel.css("top", '0');
					liel.css("left", -(settings['width'] + settings['effect']['distance']));
				}
			}
		});

		// CSS for container
		thisObj.css("list-style", "none");
		thisObj.css("distance", "0");
		thisObj.css("position", "relative");
		thisObj.css("overflow", "hidden");
		thisObj.css("padding", 0);

		if (settings['effect']['type'] == 'carousel') {
			thisObj.css("width", settings['fwidth'] * settings['effect']['showCount'] - settings['effect']['distance']);
		}
		else {
			thisObj.css("width", settings['width']);
		}


		if (settings['height'] == 'auto') {
			thisObj.css("height", $('> *:eq(' + settings['current'] + ')', thisObj).height());
		}
		else thisObj.css("height", settings['height']);
		settings['prevHeight'] = settings['height'];

		thisEl.getSlide = function getSlide(num) {
			return $('> *:eq(' + num + ')', thisEl);
		};

		function next() {
			var c = thisEl.uslCurrent();
			settings['direction'] = 'f';
			if (c + 1 < settings['count']) {
				thisEl.uslRefresh(c + 1);
			} else {

				thisEl.uslRefresh(0);
			}
		}

		function prev() {
			var c = thisEl.uslCurrent();
			settings['direction'] = 'b';
			if (c > 0) {
				thisEl.uslRefresh(c - 1);
			} else {
				thisEl.uslRefresh(settings['count'] - 1);
			}
		}

		if (settings['height'] == 'auto')
			thisEl.currentHeight = thisEl.getSlide(settings['current']).height();
		else thisEl.currentHeight = settings['height'];

		thisEl.uslCurrent = function (new_value) {
			if (new_value == undefined) {
				return settings['current'];
			}
			else {
				var old = thisEl.uslCurrent();
				var c = new_value;

				settings['current'] = new_value;
				return new_value;
			}
		};

		thisEl.autoslideNext = function () {
			if (settings['autoslide']) {
				if (settings['direction'] == 'f') next();
				else prev();
			}
		};

		thisEl.initAutoslide = function () {
			if (settings['TimeoutID']) clearTimeout(settings['TimeoutID']);
			settings['TimeoutID'] = setTimeout("jQuery('#" + $(thisEl).attr('id') + "')[0].autoslideNext()", settings['autoslide']);
		};

		thisEl.clearAutoslide = function () {
			if (settings['TimeoutID']) {
				clearTimeout(settings['TimeoutID']);
			}
		};

		thisEl.uslRefresh = function (slide_index, fast, callback) {
			if (!thisEl.ready) {
				//console.log(settings['id'] + ': ! thisEl.ready');
				setTimeout("$('#" + $(thisEl).attr('id') + "')[0].uslRefresh()", 400);
				return;
			}
			thisEl.ready = false;

			if (typeof (slide_index) != 'undefined') {
				thisEl.uslCurrent(slide_index);
			}

			thisEl.clearAutoslide();
			var prev = thisEl.getSlide(settings['prev']);
			var current = thisEl.getSlide(settings['current']);
			current.css('display', 'block');

			function doRefresh() {
				settings['onAnimateStart'](settings, thisEl); // notification
				//console.log(settings['id'] + ': doRefresh');

				if (settings['height'] == 'auto') {
					thisEl.currentHeight = thisEl.getSlide(settings['current']).height();
					settings['prevHeight'] = thisEl.getSlide(settings['prev']).height();
				}

				function finish_animate() {
					if (settings['printCurrentTo']) {
						$(settings['printCurrentTo']).html(settings['current'] + 1);
					}

					if ((settings['prev'] != settings['current']) && (settings['effect']['type'] != 'carousel')) {
						prev.css('display', 'none');
					}

					thisObj.animate({
						'height': thisEl.currentHeight
					}, 250/*, function() { alert(settings['id'] + ': finish_animate()' + thisEl.currentHeight); }*/);

					//settings['prev'] = settings['current'];
					if (settings['autoslide']) thisEl.initAutoslide();
					settings['onAnimate'](settings, thisEl); // notification
					settings['prev'] = settings['current'];
					thisEl.uslRefreshClasses();
					thisEl.ready = true;

					if (typeof callback != 'undefined') callback();
				}

				if (settings['prev'] == settings['current']) {
					finish_animate();
					return;
				}

				if (settings['effect']['type'] == 'slide') {
					if (settings['effect']['axis'] == 'x') {
						if (settings['prev'] != settings['current']) {
							if (settings['direction'] == 'f') {
								prev.animate({
									'left': -(settings['width'] + settings['effect']['distance'])
								}, settings['duration']);
								current.css('left', settings['width'] + settings['effect']['distance']);
							}
							else {
								prev.animate({
									'left': settings['width'] + settings['effect']['distance']
								}, settings['duration']);
								current.css('left', -(settings['width'] + settings['effect']['distance']));
							}
						}
						current.animate({
							'left': 0
						}, settings['duration'], function () {
							finish_animate();
						});
					}
					else {
						if (settings['prev'] != settings['current']) {
							if (settings['direction'] == 'f') {
								prev.animate({
									'top': thisEl.currentHeight + settings['effect']['distance']
								}, settings['duration'], function () {
									prev.css('left', -(settings['width'] + settings['effect']['distance']));
								});
								current.css('top', -(settings['prevHeight'] + settings['effect']['distance']));
							}
							else {
								prev.animate({
									'top': -(thisEl.currentHeight + settings['effect']['distance'])
								}, settings['duration'], function () {
									prev.css('left', -(settings['width'] + settings['effect']['distance']));
								});
								current.css('top', settings['prevHeight'] + settings['effect']['distance']);
							}
						}
						current.css('left', 0);
						current.animate({
							'top': 0
						}, settings['duration'], function () {
							finish_animate();
						});
					}
				}
				else if (settings['effect']['type'] == 'fade') {
					current.css('display', 'none');
					//current.css('z-index', 2);
					current.css('left', 0);
					current.css('top', 0);
					//prev.css('z-index', 1);
					var duration = settings['duration'];
					if (typeof fast != 'undefined') duration = 0;

					prev.fadeOut(duration, function () {
						prev.css('display', 'none');
						current.fadeIn(duration, function () {
							finish_animate();
						});
					});
				}
				else if (settings['effect']['type'] == 'carousel') {
					$('> *', thisObj).each(function (i) {
						liel = $(this);
						var ci = carouselGetFramePos(i, settings['current']);
						if (settings['direction'] == 'f')
							var pi = carouselGetFramePos(i, settings['current'] - 1);
						else var pi = carouselGetFramePos(i, settings['current'] + 1);

						if ((settings['direction'] == 'f') && (ci == 0)) {
							liel.css('left', (-1 * settings['fwidth']));
							liel.animate({ 'left': ci * settings['fwidth'] }, settings['duration']);
						}
						else if ((settings['direction'] == 'f') && (pi + 1 == settings['effect']['showCount'])) {
							liel.animate({ 'left': (settings['effect']['showCount']) * settings['fwidth'] }, settings['duration']);
						}
						else if ((settings['direction'] == 'b') && (pi == 0)) {
							liel.animate({ 'left': -1 * settings['fwidth'] }, settings['duration']);
						}
						else if ((settings['direction'] == 'b') && (ci + 1 == settings['effect']['showCount'])) {
							liel.css('left', (ci + 1) * settings['fwidth']);
							liel.animate({ 'left': ci * settings['fwidth'] }, settings['duration']);
						}
						else {
							if ((ci < settings['effect']['showCount']) && (ci >= 0)) {
								liel.animate({ 'left': ci * settings['fwidth'] }, settings['duration']);
							}
							else {
								liel.css('left', (ci * settings['fwidth']));
							}
						}

						setTimeout(function () {
							finish_animate();
						}, settings['duration'] + 100);
					});
				}
			}

			if (settings['ajax']) {
				settings['onAjaxStart'](settings, thisEl); // notification
				var statusbar_loaded = thisEl.getSlide(settings['current'])[0].usl_ajax_loaded;

				thisEl.uslAjaxLoadSlide(settings['current'], function () {
					settings['onAjaxStop'](settings, thisEl); // notification
					doRefresh();
				})
			}
			else {
				if (settings['lazyload']) {
					var $imgToLoad = $('img', current[0]);

					$imgToLoad.each(function (i) {
						var img = $(this);
						img.attr('src', img.attr('rel'));
					});

					settings['z_img_count'] = $imgToLoad.length;
					settings['z_img_loaded'] = 0;
					$imgToLoad.each(function () {
						if (this.complete) {
							settings['z_img_loaded']++;
						}
						else {
							$(this).load(function () {
								settings['z_img_loaded']++;
								if (settings['z_img_loaded'] == settings['z_img_count']) {
									doRefresh();
								}
							});
						}
					});

					if (settings['z_img_loaded'] == settings['z_img_count']) {
						doRefresh();
					}
					return;
				}

				doRefresh();
			}
		};

		thisEl.uslAjaxLoadSlide = function (slide_num, callback) {
			var current = thisEl.getSlide(slide_num);

			if (current[0].usl_ajax_loaded) {
				callback();
			}
			else {
				var url = $(settings['pager']).eq(slide_num).attr('href');
				current[0].usl_ajax_loaded = true;
				current.load(url + '?ajax=1', false, callback);
			}
		};

		thisEl.uslRefreshClasses = function () {
			if (settings['count'] > 1) {
				if (settings['nextButton']) $(settings['nextButton']).addClass('active');
				if (settings['prevButton']) $(settings['prevButton']).addClass('active');
			}
			if (settings['pager']) {
				$(settings['pager']).removeClass('usl-current');
				$(settings['pager'] + '.usl-pager-' + thisEl.uslCurrent()).addClass('usl-current');
				$(settings['pager']).parent().removeClass('usl-current-parent');
				$(settings['pager'] + '.usl-pager-' + thisEl.uslCurrent()).parent().addClass('usl-current-parent');
			}
		};

		if (settings['nextButton']) {
			$(settings['nextButton']).click(function () {
				next();
				return false;
			});
		}

		if (settings['prevButton']) {
			$(settings['prevButton']).click(function () {
				prev();
				return false;
			});
		}

		var paused = false;
		var autoslide = settings['autoslide'];

		if (settings['pausePlayButton']) {
			$(settings['pausePlayButton']).click(function () {
				if (paused)
					thisEl.playAutoslide();
				else
					thisEl.pauseAutoslide();
			});
		}

		thisEl.pauseAutoslide = function () {
			$(settings['pausePlayButton']).addClass('paused');
			settings['autoslide'] = false;
			paused = true;
		};

		thisEl.playAutoslide = function () {
			$(settings['pausePlayButton']).removeClass('paused');
			settings['autoslide'] = autoslide;
			thisEl.initAutoslide();
			paused = false;
		};

		function setNavigator(s_navigator) {
			var pager = $(s_navigator);
			pager.each(function (index) {
				this.usl_navigator_index = index;
				$(this).addClass('usl-pager-' + index);
			});

			pager.click(function () {
				var c = this.usl_navigator_index;
				if ((c < settings['count']) && (c != thisEl.uslCurrent())) {
					//thisEl.uslCurrent(c);
					if (c > thisEl.uslCurrent()) settings['direction'] = 'f';
					else settings['direction'] = 'b';
					thisEl.uslRefresh(c);

					thisEl.pauseAutoslide();
				}
				return false;
			});
		}

		if (settings['pager']) {
			setNavigator(settings['pager']);
		}
		if (settings['navigator2']) {
			setNavigator(settings['navigator2']);
		}

		function loadingStatus(loading) {
			if (loading) {
				thisObj.addClass('usl-loading');
			}
			else {
				thisObj.removeClass('usl-loading');
			}
		}

		thisEl.uslStatusbar = function () {

			if (settings['lazyload']) {
				var $imgToLoad = $('>li:eq(' + settings['current'] + ') img', thisEl);
			}
			else {
				var $imgToLoad = $('img', thisEl);
			}

			settings['img_count'] = $imgToLoad.length;
			if (settings['img_count']) {
				loadingStatus(true);
			}

			settings['img_loaded'] = 0;
			$imgToLoad.each(function () {
				if (this.complete) {
					settings['img_loaded']++;
				}
				else {
					$(this).load(function () {
						settings['img_loaded']++;
						//alert(settings['img_loaded'] + ' of ' + settings['img_count']);
						if (settings['img_loaded'] == settings['img_count']) {
							loadingStatus(false);
							thisEl.ready = true;
							thisEl.uslRefresh();
						}
					});
				}
			});

			if (settings['img_loaded'] == settings['img_count']) {
				loadingStatus(false);
				thisEl.ready = true;
				thisEl.uslRefresh();
			}
		};

		// statusbar
		if (settings['statusbar'] && !settings['ajax']) {
			thisEl.uslStatusbar();
		}

		/*
		* If the mousewheel plugin has been included on the page then
		* the slider will also respond to the mouse wheel.
		*/
		if (settings['mousewheel']) {
			thisObj.bind(
                'mousewheel',
                function (event, delta) {
                	if (thisEl.ready) {
                		if (delta < 0) {
                			next();
                		}
                		else {
                			prev();
                		}
                	}
                	return false;
                });
		}

		if (!settings['statusbar'] || settings['ajax']) {
			thisEl.ready = true;
			thisEl.uslRefresh();
		}
	};
})(jQuery); 
