(function ($) {
    $.fn.miniscroller = function (options) {
        var defaults = {
            next: ".next",
            prev: ".prev",
            type: "horizontal",
            pause: 5000,
            speed: 500,
            itemsInGroup: 1,
			mousestop: 0,
			tipClass: 'tooltip',
			layout: '<div/>',
			position: ['top', 'center'], 
			offset: [4, 0],
			relative: false,
			tpause: 300
        };
        var mask = null;
        var items = null;
        var delta = 0;
        var index = 0;
        var _locked = false;
        var _intvl = 0;
		var _stop = 0;
		var _astop = 0;
        var options = $.extend(defaults, options);
        var _type = options.type;
        var _next_selector = options.next;
        var _prev_selector = options.prev;
        var _cssProperty = options.type == "vertical" ? "top" : "left";        
		var _tipintvl = false;
		var tip = false;
		var tipcount = 0;

	    function _reset() {
			if (_stop > 0)
				return;
			if (tip) {
				// _down(tip);
			}
            _locked = true;
            var anim = {};
            anim[_cssProperty] = 0;
            mask.children().eq(0).animate(anim, options.speed, function () {
                _locked = false;
                index = 0;
                if (index < items - 1)
                    $(_next_selector).css("visibility", "visible");
                if (index == 0)
                    $(_prev_selector).css("visibility", "hidden");
            });
        }
        function _prev() {
            if (_locked || index == 0 || _stop > 0)
                return;
			if (tip) {
				// _down(tip);
			}
            _locked = true;
            var anim = {};
            anim[_cssProperty] = ("+=" + delta);
            mask.children().eq(0).animate(anim, options.speed, function () {
                _locked = false;
                index--;
                if (index < items - 1)
	                $(_next_selector).css("visibility", "visible");
                if (index == 0)
                    $(_prev_selector).css("visibility", "hidden");
            });
        }
        function _next() {
            if (_locked || index == items || _stop > 0)
                return;
			if (tip) {
				// _down(tip);
			}
            _locked = true;
            var anim = {};
            anim[_cssProperty] = ("-=" + delta);
            mask.children().eq(0).animate(anim, options.speed, function () {
                _locked = false;
                index++;
                if (index == items - 1) 
                    $(_next_selector).css("visibility", "hidden");
                if (index > 0) 
                    $(_prev_selector).css("visibility", "visible");
            });
        }

		function _up(tip) {
			if (_astop > 0) return;
			_astop = 1;
			tip.height(0);
			tip.css({display: 'block'});
			pos = options.position[0];
			var anim = {};
			if (pos == 'top') {
				anim['height'] = ("+=" + tip.th);
			}
			else {
				anim['top'] = ("-=" + tip.th);
				anim['height'] = ("+=" + tip.th);
			}
			$(tip).animate(
				anim
			, options.tpause, function() {
				_astop = 0;
				tip.height(tip.th);
			});
		}

		function _down(tip) {
			if (_astop > 0) return;
			_astop = 1;
			pos = options.position[0];
			var anim = {};
			if (pos == 'top') {
				anim['height'] = ("-=" + tip.th);
			}
			else {
				anim['top'] = ("+=" + tip.th);
				anim['height'] = ("-=" + tip.th);
			}
			$(tip).animate(
				anim
			  , options.tpause / 2, function() {
					tip.css({display:'none'});
					tip.css({top: tip.to});
					tip.height(tip.th);
					_astop = 0;
					_stop = 0;
					clearInterval(_tipintvl);
					_tipintvl = false;
			});
		}
	
		function getPosition(trigger, tip) {	
			var top = options.relative ? trigger.position().top : trigger.offset().top, 
			 	left = options.relative ? trigger.position().left : trigger.offset().left,
				pos = options.position[0];

			top  -= tip.outerHeight() - options.offset[0];
			left += trigger.outerWidth() + options.offset[1];

			// iPad position fix
			if (/iPad/i.test(navigator.userAgent)) {
				top -= $(window).scrollTop();
			}

			// adjust Y		
			var height = trigger.outerHeight();
			if (pos == 'center') 	{ top += height / 2; }
			if (pos == 'bottom') 	{ top += height; }


			// adjust X
			pos = options.position[1]; 	
			var width = tip.outerWidth() + trigger.outerWidth();
			if (pos == 'center') 	{ left -= width / 2; }
			if (pos == 'left')   	{ left -= width; }	 
	
			return {top: top, left: left};
		}

        return this.each(function () {
            mask = $(this);
			mask.css("position", "relative")
				.css("overflow", "hidden");
			mask.children().eq(0).css("position", "absolute")								
								.css("width", "100000px")
								.css("left", "0")
								.css("top", "0");
            delta = options.type == "vertical" ? mask.height() : mask.width();
            $(_prev_selector).css("visibility", "hidden").click(_prev);
            $(_next_selector).css("visibility", "hidden").click(_next);

			if (typeof options.position == 'string') {
				options.position = options.position.split(/,?\s/);	
			}
	
			var items_w_class = mask.find(".item").size();
			if(items_w_class == 0)
				items = Math.ceil(mask.children().eq(0).children().size() / options.itemsInGroup);					
			else
				items = Math.ceil(mask.find(".item").size() / options.itemsInGroup);
				
			if (options.mousestop > 0) {
				$(this).mousemove(function(event) {
					if (_locked || _astop > 0) return;
					var trigger = $(event.target);
					if ($(trigger).attr("title")) $(trigger).data("title", $(trigger).attr("title")).removeAttr("title");
					clearInterval(_tipintvl);
					_tipintvl = false;
					_stop = 1;
					if ($(trigger).data("title")) {
						var title = $(trigger).data("title");
						if (!tip) {
							tip = $(options.layout).addClass(options.tipClass).appendTo(document.body).hide().append(title);
							tip.attr("id", "tooltip");
							tip.mousemove(function(event) {
								_stop = 1;	
								clearInterval(_tipintvl);
								_tipintvl = false;
							});
							tip.mouseout(function(event) {
								if (!_tipintvl) _tipintvl = setInterval(function () {
								_down(tip);
								}, options.tpause);
							});
							tip.mouseup(function(event) {
								if (tip.h != "") {
									document.location.href = tip.h;
								}
							});	
						}
						if (!trigger.attr("id")) trigger.attr("id", ++tipcount);
						if (tip.tid == trigger.attr("id") && tip.css("display") == "block") return;
						tip.tid = trigger.attr("id");
						tip.ob = trigger;
						tip.h = trigger.parent().attr("href");
						if (tip.h != "") {
							tip.css("cursor", "pointer");
						}
						else {
							tip.css("cursor", "none");
						}
						var pos = getPosition($(trigger), tip);
						if (!tip.th) tip.th = tip.height();
						if (!tip.to) {
							var posi = options.position[0];
							tip.to = pos.top;
							if (posi == 'top') tip.to += 22;
						}
						tip.css({position:'absolute', top: tip.to + tip.th, left: pos.left});
						tip.html(title);					
						_up(tip);
					}
				});
				$(this).mouseout(function(event) {
					if (tip) {
						if (!_tipintvl) _tipintvl = setInterval(function () {
							_down(tip);
						}, options.tpause);
					}
					else _stop = 0;
				});
			}
            if (items > 1)
				if(options.type == "horizontal")
				{
					mask.children().eq(0).children().each(function () {
						$(this).css("float", "left");
					});					
				}
           	    $(_next_selector).css("visibility", "visible");
            	_intvl = setInterval(function () {
                if (index == items - 1)
                    _reset();                
                else
					_next();
            }, options.pause);
        });
    };
})(jQuery);
