(function($){
	
 	$.fn.extend({
 		
		//pass the options variable to the function
 		yCarousel: function(options) {
			var defaults = {
				direction	: 'right',
				way			: 'h'
			};
			var o =  $.extend(defaults, options);
			var publicObj = [];
			
			var collection = false;
			collection = this.length > 1 ? true : false;
			
			if(collection) {
				this.each(function() {
					var elmt = $(this);
					var self = this;
					publicObj.push(new $.carousel(elmt, o, self));
				});
			} else {
				var elmt = $(this);
				var self = this;
				publicObj = new $.carousel(elmt, o, self);
			}
			return publicObj;
    	}
	});
	
	$.carousel = function(elmt, o, self) {
		var publicObj;
		
		var wrapper = $(elmt);
		var list = wrapper.find('> *');
		var lis = list.find('> li');
		
		var init = function() {
			elmt.addClass('carouselWrapper');
			
			// make the mobile wrap
			var className = 'innerWrapper';
			className += o.way == 'h' ? ' hWrapper' : ' vWrapper';
			list.wrap('<div class="'+className+'"></div>');
			
			// set width or height of list wrapper
			update();
			
			// put the last element in first place to make the illusion !
			pv.lastInFirst();
			
			// bind touch events
			// set touch start values
			elmt.context.addEventListener("touchstart", function(e) {
				if(e.targetTouches.length == 1) {
					e.preventDefault();
					pv.touchStart(e);
				}
			}, false);
			
			elmt.context.addEventListener("touchmove", function(e) {
				if(e.targetTouches.length == 1) {
					e.preventDefault();
					pv.touchMove(e);
				}
			}, false);
			
			elmt.context.addEventListener("touchend", function(e) {
				pv.touchEnd(e);
			}, false);
		};
		
		// private functions & vars
		var pv = {
			decal : 0,
			durationBack: 500,
			durationMove: 100,
			easingBack: 'easeOutCubic',
			easingMove: 'linear',
			touch: {
				start: {
					x: 0,
					y: 0,
					t: 0
				},
				delta: {
					x: 0,
					y: 0,
					t: 0,
					direction : 'prev'
				}
			},
			touchStart: function(e) {
				pv.touch.start.x = e.targetTouches[0].pageX;
				pv.touch.start.y = e.targetTouches[0].pageY;
				pv.touch.start.t = (new Date).getTime();
				
				pv.touch.delta.x = 0;
				pv.touch.delta.y = 0;
				pv.touch.delta.t = 0;
			},
			touchMove:	function(e) {
				var cur = {};
				cur.touchX = e.targetTouches[0].pageX;
				cur.touchY = e.targetTouches[0].pageY;
				cur.touchT = (new Date).getTime();
				
				// set touch delta values
				pv.touch.delta.x = pv.touch.start.x - cur.touchX;
				pv.touch.delta.y = pv.touch.start.y - cur.touchY;
				pv.touch.delta.t = pv.touch.start.t - cur.touchT;
				
				// drag item
				var currentPos = -pv.decal;
				var targetPos = currentPos - pv.touch.delta.x;
				list.css('left', targetPos+'px');
			},
			touchEnd: function(e) {
				var decal = pv.decal;
				var currentDecal = parseInt(pv.touch.delta.x);
				pv.direction = currentDecal < 0 ? 'prev' : 'next';
				currentDecal = currentDecal < 0 ? currentDecal * -1 : currentDecal;
				var percentMove = currentDecal / decal * 100;
				if(percentMove > 50) {
					pv.move();
				} else {
					pv.goBack();
				}
			},
			move: function() {
				var pos = pv.direction == 'prev' ? 0 : -(pv.decal * 2);
				list.stop().animate({
					left: pos+'px'
				}, pv.durationMove, pv.easingMove, function() {
					pv.direction == 'prev' ? pv.lastInFirst() : pv.firstInLast();
				});
			},
			goBack: function() {
				list.stop().animate({
					left: -pv.decal+'px'
				}, pv.durationBack, pv.easingBack, function() {
					
				});
			},
			lastInFirst: function() {
				var last = list.find('> li:last');
				var temp = last;
				last.remove();
				list.prepend(temp);
				pv.decal = pv.itemWidth(temp);
				list.css('left', -pv.decal+'px');
			},
			firstInLast: function() {
				var first = list.find('> li:first');
				var temp = first;
				first.remove();
				list.append(temp);
				pv.decal = pv.itemWidth(list.find('> li:first'));
				list.css('left', -pv.decal+'px');
			},
			itemWidth : function(item) {
				return $(item).width();
			},
			listWidth : function(lis) {
				var tot = 0;
				lis.each(function() {
					var e = $(this);
					var eWidth = e.width();
					tot = tot + eWidth;
				});
				return tot;
			},
			listHeight : function(lis) {
				var tot = 0;
				lis.each(function() {
					var e = $(this);
					var eWidth = e.height();
					tot = tot + eWidth;
				});
				return tot;
			}
		};
		
		// public functions
		function update() {
			var cWidth = elmt.width();
			if(o.way == 'h') {
				lis.css('width', cWidth+'px');
			}
			// set width or height of list wrapper
			var value = o.way == 'h' ? pv.listWidth(lis) : pv.listHeight(lis);
			list.css('width', value+'px');
		}
		
		function getDirection () {
			return o.direction;
		}
		
		function setClass() {
			elmt.removeClass('test').addClass('test');
		}
		
		function me() {
			return $(elmt);
		}
		
		publicObj = {
			update: update,
			getDirection: getDirection,
			me: me,
			setClass: setClass
		};
		
		init();
		return publicObj;
	};
	
})(jQuery);
