(function($, undefined){
	
	$.mSlider = {
		defaults: {
			type: 'slide',
			speed: 300,
			timeout: 3000,
			easing: 'swing',
			paseOnHover: false,
			onClick: false,
			nextButton: false,
			prevButton: false
		},
		timer: false,
		animating: false,
		temp: {},
		
		init: function($this, options, fn){
			
			this.$el = $this;
			this.settings = $.extend(this.defaults, options);
			this.$children = this.$el.children();
			this.width = this.settings.width ? this.settings.width : this.$children.width();
			this.height = this.settings.height ? this.settings.height : this.$children.height();
			
			this.html();
			this.css();
			
			if(this.$children.size() > 1)
			{
				this.events();
				this.start();
			}
			
			this.save();
			
			if($.isFunction(fn))
			{
				fn.call(this);	
			}
		},
		
		html: function(){
			this.$el.wrap('<div id="slider-container" />');	
			this.$container = this.$el.parent();
		},
		
		css: function(){
			this.$container.css({
				position: 'relative',
				width: this.width,
				height: this.height,
				overflow: 'hidden'
			});	
			
			this.$el.css({
				position: this.settings.type == 'slide' ? 'absolute' : 'relative',
				margin: 0,
				padding: 0,
				width: this.settings.type == 'slide' ? this.width * this.$children.size() : this.width,
				height: this.height
			});
			
			this.$children.css({
				float: 'left',
				listStyle: 'none',
				position: this.settings.type == 'slide' ? '' : 'absolute',
				left: 0,
				top: 0
			});
			
			if(this.settings.type == 'fade')
			{
				this.$children.filter(':first').css({
					zIndex: 4444									
				});
				this.$children.filter(':not(:first)').fadeOut(200);
			}
		},
		
		events: function(){
			var base = this;
			if(this.settings.pauseOnHover)
			{
				this.$el.hover(function(){
					clearTimeout(base.timer);
					base.temp.timeout = base.settings.timeout;				
				}, function(){
					base.settings.timeout = base.temp.timeout;	
					base.start();
				});
			}
			
			if(this.settings.onClick)
			{
				this.$container.click(function(){
					base.next();	
					return false;
				});
			}
			
			if(this.settings.nextButton)
			{
				$(this.settings.nextButton).click(function(){
					base.next();	
					return false;
				});
			}
			
			if(this.settings.prevButton)
			{
				$(this.settings.prevButton).click(function(){
					base.prev();	
					return false;
				});
			}
		},
		
		start: function(){
			var base = this;
			if(this.settings.timeout)
			{
				this.timer = setTimeout(function(){
					base.next();
				}, this.settings.timeout);
			}
		},
		
		next: function(){
			if(!this.animating)
			{
				this.dir = 'next';
				this.pos = -this.width;
				this.animate();
			}
		},
		
		prev: function(){
			if(!this.animating)
			{
				this.dir = 'prev';
				this.pos = 0;
				this.animate();
			}
		},
		
		animate: function(){
			if(!this.animating)
			{
				clearTimeout(this.timer);
				this.animating = true;
				var base = this,
					type = this.settings.easing,
					easing = jQuery.easing[type] !== undefined ? type : 'swing';
				base.fixPrev();
				if(base.settings.type == 'fade')
				{
					base.$el.children(':first').fadeOut(base.settings.speed);
					base.$el.children(':eq(1)').fadeIn(base.settings.speed, function(){
						base.fixNext();
						base.animating = false;
						base.start();															 
					});
				}
				else
				{
					this.$el.animate({left: this.pos}, this.settings.speed, easing, function(){
						base.fixNext();
						base.animating = false;
						base.start();
					});
				}
			}
		},
		
		fixNext: function(){
			this.$el.children(':first').remove().appendTo(this.$el).css({
				zIndex: 0
			});
			
			if(this.settings.type == 'slide')
			{
				this.$el.css({
					left: 0
				});
			}
		},
		
		fixPrev: function(){
			if(this.dir == 'prev')
			{
				if(this.settings.type == 'slide')
				{
					this.$el.css({
						left: -this.width
					});
					
					this.$el.children(':last').remove().prependTo(this.$el);
				}
				
				if(this.settings.type == 'fade')
				{
					this.$el.children(':last').remove().insertAfter(this.$el.children(':first')).css({
						zIndex: 8888
					}).hide();
				}
			}
		},
		
		save: function(){
			this.$el.data('mSlider', this);
		},
		
		action: function(action, option){
			switch(action)
			{
				default:
					return false;
					break;
				
				case 'next':
					this.next();
					break;
				
				case 'prev':
					this.prev();
					break;
			}
		}
	};
	
	$.fn.mSlider = function(options, fn){
		
		if(typeof options !== 'string')
		{
			return this.each(function(){
				$.mSlider.init($(this), options, fn);						  
			});
		}
		else
		{
			return this.each(function(){
				var slider = $(this).data('mSlider');
				slider.action(options, fn);						  
			});
		}
		
	};
	
})(jQuery);
