(function($)
{	
	$.fn.em_carousel = function(options)
	{
		var defaults = {
			shift: 126,
			activeItems: 8,
			visibleItems: 4,
			speed: 1000,
			direction: 'horizontal',
			initCallback: null,
			itemLoadCallback: null
		};
	
		var opts = $.extend({}, defaults, options);

		return this.each(function()
		{
			this.add = addItem;
			this.show = showCarousel;
			this.last_ten = showLastTenItems;
			var isBusy = false;
			var currentDirection = null; // null, next, prev
			var obj = $(this); // jquery item
			var self = this; // html item
			this.items = new Array();
			this.item_ptr = 0; // указывает на 1-й из activeItems элемент в массиве items
			this.length = 0;
			
			// настройка callback-ов
			if ((opts.itemLoadCallback != null) && (typeof opts.itemLoadCallback != 'function'))
			{
				opts.itemLoadCallback = null;
				alert('Не установлена функция загрузки.');
				return;
			} else if (opts.itemLoadCallback == null)
			{
				alert('Не установлена функция загрузки.');
				return;
			}
			if ((opts.initCallback != null) && (typeof opts.initCallback != 'function'))
			{
				opts.initCallback = null;
				alert('Не установлена функция инициализации, первоначальной загрузки.');
				return;
			} else if (opts.initCallback == null)
			{
				alert('Не установлена функция инициализации, первоначальной загрузки.');
				return;
			}
			
			// рисуем
			this.show();
			
			if (opts.direction == 'horizontal')
			{
				// выставляем ширину
				$(".em_carousel", obj).css("width", (opts.visibleItems * opts.shift + $(".em_carousel_prev").width() + $(".em_carousel_next").width()) + "px");
				$(".em_carousel_clip", obj).css("width", opts.visibleItems * opts.shift + "px");
				this.length = opts.activeItems * opts.shift;
				$(".em_carousel_list", obj).css("width", this.length + "px");
				
				// отрисовываем стрелки
				$(".em_carousel_prev", obj).css("left", "0px");
				$(".em_carousel_next", obj).css("left", (opts.visibleItems * opts.shift + $(".em_carousel_prev").width()) + "px");
			} else
			{
				// выставляем высоту
				$(".em_carousel", obj).css("height", (opts.visibleItems * opts.shift + $(".em_carousel_prev").height()) + 5 + "px");
				$(".em_carousel_clip", obj).css("height", opts.visibleItems * opts.shift + "px");
				this.length = opts.activeItems * opts.shift;
				$(".em_carousel_list", obj).css("height", this.length + "px");
				
				// отрисовываем стрелки
				$(".em_carousel_prev", obj).css("top", (opts.visibleItems * opts.shift) + "px");
				$(".em_carousel_next", obj).css("top", (opts.visibleItems * opts.shift) + "px");
			}
			
			// запускаем инициалиацию
			opts.initCallback(self, currentDirection);
					
			// настраиваем ивенты для кнопок вправо-влево
			$(".em_carousel_right", obj).mouseenter(function()
			{
				currentDirection = 'next';
				Move(1);
			}).mouseleave(function()
			{
				currentDirection = null;
			});
			$(".em_carousel_left", obj).mouseenter(function()
			{
				currentDirection = 'prev';
				Move(-1);
			}).mouseleave(function()
			{
				currentDirection = null;
			});
			
			// собственно движение
			function Move(direction)
			{
				if (isBusy) return;
				isBusy = true;
				
				if (direction == 1)
				{
					if (opts.direction == 'horizontal')
					{
						if ($(".em_carousel_list", obj).position().left == ($(".em_carousel_clip", obj).width() - $(".em_carousel_list", obj).width()))
						{
							isBusy = false;
							return;
						}
						var newPos = $(".em_carousel_list", obj).position().left - opts.shift;
						if ($(".em_carousel_list", obj).width() + newPos < $(".em_carousel_clip", obj).width())
						{
							newPos = $(".em_carousel_clip", obj).width() - $(".em_carousel_list", obj).width();
						}
					} else
					{
						if ($(".em_carousel_list", obj).position().top == ($(".em_carousel_clip", obj).height() - $(".em_carousel_list", obj).height()))
						{
							isBusy = false;
							return;
						}
						var newPos = $(".em_carousel_list", obj).position().top - opts.shift;
						if ($(".em_carousel_list", obj).height() + newPos < $(".em_carousel_clip", obj).height())
						{
							newPos = $(".em_carousel_clip", obj).height() - $(".em_carousel_list", obj).height();
						}
					}
					$(".em_carousel_left", obj).removeClass("em_carousel_left_disabled");
				} else
				{
					if (self.item_ptr < 1)
					{
						isBusy = false;	
						return;
					}
					if (opts.direction == 'horizontal')
					{
						var newPos = $(".em_carousel_list", obj).position().left + opts.shift;
					} else
					{
						var newPos = $(".em_carousel_list", obj).position().top + opts.shift;
					}
					if (newPos > 0) newPos = 0;
				}
				
				// если новый элемент, то грузим из клиентской функции, в противном случае из нашего кеша
				if (direction == 1)
				{
					var newIndx = self.item_ptr + opts.activeItems;
					if (newIndx >= self.items.length) opts.itemLoadCallback(self, currentDirection);
																			 else itemLoadFromCache(newIndx, direction);
				} else
				{
					var newIndx = self.item_ptr - (opts.activeItems - opts.visibleItems) - 1;
					if (newIndx > -1)
					{
						itemLoadFromCache(newIndx, direction);
						if (opts.direction == 'horizontal')
						{
							newPos = $(".em_carousel_list", obj).position().left + opts.shift;
						} else
						{
							newPos = $(".em_carousel_list", obj).position().top + opts.shift;
						}
					}
				}
				
				if (opts.direction == 'horizontal')
				{
					$(".em_carousel_list", obj).animate(
						{left:newPos+"px"},
						opts.speed,
						'linear',
						function(){animate_callback();}
					)
				} else
				{
					$(".em_carousel_list", obj).animate(
						{top:newPos+"px"},
						opts.speed,
						'linear',
						function(){animate_callback();}
					)
				}
				
				function animate_callback()
				{
					isBusy = false;
					self.item_ptr += direction;
					if (self.item_ptr == 0) $(".em_carousel_left", obj).addClass("em_carousel_left_disabled");
					if (direction == 1)
					{
						var del_element = self.item_ptr - (opts.activeItems - opts.visibleItems) - 1;
						if (del_element > -1)
						{
							$(".em_carousel_item_" + del_element, obj).remove();
							if (opts.direction == 'horizontal')
							{
								$('.em_carousel_list', obj).css('left', ($(".em_carousel_list", obj).position().left + opts.shift) + 'px');
								self.length -= opts.shift;
								$('.em_carousel_list', obj).css('width', self.length + 'px');
							} else
							{
								$('.em_carousel_list', obj).css('top', ($(".em_carousel_list", obj).position().top + opts.shift) + 'px');
								self.length -= opts.shift;
								$('.em_carousel_list', obj).css('height', self.length + 'px');
							}
						}
					} else
					{
						var del_element = self.item_ptr + opts.activeItems;
						$(".em_carousel_item_" + del_element, obj).remove();
						self.length -= opts.shift;
						if (opts.direction == 'horizontal')
						{
							$('.em_carousel_list', obj).css('width', self.length + 'px');
						} else
						{
							$('.em_carousel_list', obj).css('height', self.length + 'px');
						}
					}
					if (currentDirection != null)
					{
						if (currentDirection == 'prev')
						{
							Move(-1);
						} else
						{
							Move(1);
						}
					}
					return;
				} // function animate_callback()
			} // function Move ()
			
			// загружаем элемент из кеша
			function itemLoadFromCache(indx, direction)
			{
				self.length += opts.shift;
				if (opts.direction == 'horizontal')
				{
					$('.em_carousel_list', obj).css('width', self.length + 'px');
				} else
				{
					$('.em_carousel_list', obj).css('height', self.length + 'px');
				}
				if (direction == 1)
				{
					$('.em_carousel_list', obj).append('<li class="em_carousel_item_' + indx + '">' + self.items[indx][1] + '</li>');
				} else
				{
					$('.em_carousel_list', obj).prepend('<li class="em_carousel_item_' + indx + '">' + self.items[indx][1] + '</li>');
					if (opts.direction == 'horizontal')
					{
						$('.em_carousel_list', obj).css('left', ($(".em_carousel_list", obj).position().left - opts.shift) + 'px');
					} else
					{
						$('.em_carousel_list', obj).css('top', ($(".em_carousel_list", obj).position().top - opts.shift) + 'px');
					}
				}
			}
		});
		
		// загружаем темплейт
		function showCarousel()
		{
			if (opts.direction == 'vertical')
			{
				var tmpl = $.fn.em_carousel.html_structure_vertical();
			} else
			{
				var tmpl = $.fn.em_carousel.html_structure_horizontal();
			}
			$(this).html(tmpl);
		}
		
		// добавить элемент в карусель
		function addItem(id, code)
		{
			var obj = $(this);
			this.items.push(new Array(id, code));
			this.length += opts.shift;
			if (opts.direction == 'horizontal')
			{
				$('.em_carousel_list', obj).css('width', this.length + 'px');
			} else
			{
				$('.em_carousel_list', obj).css('height', this.length + 'px');
			}
			$('.em_carousel_list', obj).append('<li class="em_carousel_item_' + (this.items.length - 1) + '">' + code + '</li>');
		};
		
		// показываем последние 10 id-шек
		function showLastTenItems()
		{
			var mas = new Array();
			var n = this.items.length;
			var start = n - 10;
			if (start < 0) start = 0;
			for (var i = start; i<n; i++) mas.push(this.items[i][0]);
			return mas;
		}
	};
	
	$.fn.em_carousel.html_structure_vertical = function()
	{
		var tmpl = '\
<div class="em_carousel">\
	<div class="em_carousel_clip">\
		<ul class="em_carousel_list"></ul>\
	</div>\
	<div class="em_carousel_prev"><span class="em_carousel_left em_carousel_left_disabled"></span></div>\
	<div class="em_carousel_next"><span class="em_carousel_right"></span></div>\
</div>';
	
		return tmpl;
	}
	$.fn.em_carousel.html_structure_horizontal = function()
	{
		var tmpl = '\
<div class="em_carousel">\
	<div class="em_carousel_prev"><span class="em_carousel_left em_carousel_left_disabled"></span></div>\
	<div class="em_carousel_next"><span class="em_carousel_right"></span></div>\
	<div class="em_carousel_clip">\
		<ul class="em_carousel_list"></ul>\
	</div>\
</div>';
	
		return tmpl;
	}
})(jQuery);