(function($){

	var t3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix,

		trl = t3d ? 'translate3d(' : 'translate(',

		trr = t3d ? ',0)' : ')';

	$.fn.carousel = function(opt){

		opt = $.extend({

			interval: 3000,

			scroll: true,

			loop: true

		}, opt);

		var me = this,

			body = $(document.body),

			items, width = opt.width || me.children()[0].scrollWidth,

			trans = opt.loop ? opt.initPos - width : opt.initPos,

			startPos, startTime, curPos, lastPos, gap = opt.gap,

			last = 0, movecount = 0, startY, isX, am;

		function init(){

			var item = me.children()[0];

			opt.loop && me.append(item.cloneNode(true)).append(item.cloneNode(true));

			items = me.children().addClass("carousel-items");

			translate();

			setTimeout(function(){

				items.addClass("carousel-3d");

			}, 100);

			me.on("touchstart", ontouchstart).on("touchmove", ontouchmove).on("touchend", ontouchend);

			automove();

			me[0].isInit = true;

		}

		function translate(){

			items.css("-webkit-transform", trl + trans + "px,0" + trr);

		}

		function onchange(){

			if(opt.onchange){

				cur = parseInt((trans - opt.initPos) / gap);

				if(cur !== last){

					opt.onchange.call(me, -cur);

					last = cur;

				}

			}

		}

		function ontouchstart(e){

			items.removeClass('carousel-trans');

			movecount = 0;

			startPos = lastPos = e.touches[0].clientX;

			startY = e.touches[0].clientY;

			startTime = e.timeStamp;

			clearInterval(am);

		}

		function moveHandler(e){

			e.preventDefault();

			movecount += 1;

			var oriTrans = trans;

			trans = trans + curPos - lastPos;

			lastPos = curPos;

			if(opt.loop){

				if(-trans < width){

					trans -= width;

				}

				if(-trans > width * 2){

					trans += width;

				}

			} else {

				if(-trans < -opt.initPos || -trans > opt.endPos){

					trans = oriTrans;

				}

			}

			translate();

			onchange();

		}

		function ontouchmove(e){

			curPos = e.touches[0].clientX;

			var deltaX = curPos - lastPos;

			if(movecount == 0){

				isX = (Math.abs(deltaX) > Math.abs(e.touches[0].clientY - startY));

				isX && moveHandler(e);

			} else if(isX){

				moveHandler(e);

			}

			movecount++;

		}

		function ontouchend(e){

			var ot = Math.abs((trans - opt.initPos) % gap),

				flag = trans > 0 ? 1 : -1,

				delta = lastPos - startPos,

				oriTrans = trans;

			if((Math.abs(delta) / (e.timeStamp - startTime)) > 0.1){

				trans = delta < 0 ? (trans + flag * (gap - ot)) : (trans - flag * ot);

			} else {

				trans = ot >= gap / 2 ? (trans + flag * (gap - ot)) : (trans - flag * ot);

			}

			items.addClass('carousel-trans');

			if(-trans < -opt.initPos || -trans > opt.endPos){

				trans = oriTrans;

			}

			translate();

			items.one('webkitTransitionEnd', function(){

				items.removeClass('carousel-trans');

				onchange();

			});

			clearInterval(am);

			automove();

		}

		function move(dir){

			trans += dir * gap;

			items.addClass('carousel-trans');

			translate();

			items.one('webkitTransitionEnd', function(){

				items.removeClass('carousel-trans');

				if(-trans < width){

					trans -= width;

				}

				if(-trans > width * 2){

					trans += width;

				}

				translate();

				onchange();

			});

		}

		function automove(){

			if(opt.automove){

				am = setInterval(function(){

					move(-1);

				}, opt.interval)

			}

		}

		init();

		return me;

	}

})(Zepto)

function _(el, opt, n){

	var dv = "div";

	if(!el || $.isPlainObject(el)){

		return _(dv, el, opt);

	}

	if(n){

		for(var a = [], i = 0; i < n; i++){

			a.push(_(el, opt));

		}

		return a;

	}

	var m = el.match(/^(\w*)(?:#([\w-]+))?(?:\.(.+?))?$/),

		e = document.createElement(m[1] || dv), c, E = $(e);

	if(m[2]) e.id = m[2];

	if(m[3]) e.className = m[3];

	for(var i in opt || {}){

		c = opt[i];

		switch(i){

			case "c":

				E.append(c);

				break;

			case "p":

				E.appendTo(c);

				break;

			case "s":

				e.style.cssText = c;

				break;

			case "t":

				E.text(c);

				break;

			default:

				i[0] == "_" ? E.data(i.slice(1), c) : e[i] = c;

				break;

		}

	}

	return e;

}

Class = function(){

	var _construct = function(init, members, statics){

			$.extend(init.prototype, members);

			$.extend(init, _statics, statics);

			return init;

		}, _statics = {

			extend: function(init, members){

				if(!$.isFunction(init))

					return this.extend(function(){

						arguments.callee._super.apply(this, arguments);

					}, init, members);

				init._super = this;

				$.extend(init.prototype, this.prototype);

				return _construct.apply(this, arguments);

			}

		};

	return _construct;

}();

Carousel = Class(function(opt){

	this.opt = $.extend({}, this._opt, opt);

	this.el = _.apply(0, this.opt.el);

	this.setStyle(this.opt.style);

	this.apply(this.opt);

}, {

	_opt: {

		_style: "carousel",

		start: 0,

		gap: 0,

		items: [],

		df: 0,

		dm: [[320, 120]]

	},

	apply: function(opt){

		var v = opt.items, pg = v.length,

			e1 = _({p: this.el}, 2),

			e2 = _({p: e1[0]}),

			e3 = _({p: e1[1]}, 2),

			e4 = _({p: e3[1]}, pg), s,

			dm = opt.dm

			w = Math.min(innerWidth, innerHeight);

		v.forEach(function(item){

			e2.appendChild(item.el);

			$(item.el).width(w).height(w * dm[1] / dm[0]);

		});

		$(e4[s = opt.start]).addClass("sel");

		$(e3[0]).text(v[0].text);

		opt.gap += w;

		opt.initPos = -w / 2;

		this.onrender = function(){

			$(e1[0]).carousel($.extend({

				onchange: function(c){

					$(e4[s]).removeClass("sel");

					s = (c + opt.start) % pg;

					$(e4[s]).addClass("sel");

					$(e3[0]).text(v[s].text);

				}

			}, opt));

		};

	},

	render: function(d){

		$(this.el).appendTo(d || document.body);

		this.onrender();

	},

	setStyle: function(style){

		var _s = this._opt._style || "", s = style || "";

		if(_s || s) this.el.className = $.trim([_s, s].join(" "));

	}

});