/**
 * Fade Slider
 *
 * @author Tobias Schibler <tobias@tujo.no>
 * @package JavaScript
 * @copyright 2011 tujo ANS
 */



function FadeSlider(){}
FadeSlider.prototype.init = function(rootEl, opts){
	this.rootEl = rootEl;
	this.totalWidth = 0;

	/**
	 * List of FX names like easeInOut...
	 * http://gsgd.co.uk/sandbox/jquery/easing/
	 *
	 * Quad
	 * Cubic
	 * Quart
	 * Quint
	 * Sine
	 * Expo
	 * Circ
	 * Elastic
	 * Back
	 * Bounce
	 */
	this.def = {
		easing: 'easeInOutQuint',
		duration: 1600
	};
	this.opts = $.extend(this.def, opts);

	if($.browser.SafariMobile)
		this._setDragSwipeTouch();
	else
		this._setDragSwipe();

};
FadeSlider.prototype._setDragSwipe = function(){
	var target = this;

	this.mouseEnter = function(e){
		this.over = true;
		$(this.rootEl).addClass('over');
//		if(!this.wasEntered){
//			fire('mouseEnter');
//		}
	};
	this.mouseLeave = function(e){
		if(this.wasEntered && !this.down){
			$(this.rootEl).removeClass('over');
//			fire('mouseLeave');
		}
	};
	this.mouseDown = function(e){
		this.down = this.over = true;
		this.renderPosition(e, true);
		$(this.rootEl).removeClass('over');
		$(this.rootEl).addClass('dragging');
//		fire('mouseDown');
		if($(e.target).parents('li:first').is('li'))
			this.lastTarget = e.target;
	};
	this.mouseUp = function(e, focus){
//		fire('mouseUp');
		this.renderPosition(e, false);

		this.down = false;
		$(this.rootEl).removeClass('dragging');

		/** go back to last pisition */
		this.draggedPos = (this.getLeftPos(this.lastTarget) + parseFloat($('ul', target.rootEl).position().left));
//		fire(Math.abs(this.draggedPos)+' > '+(this.screen.w/4));
		if(Math.abs(this.draggedPos) > (this.screen.w/4)){
			var liEl = $(this.lastTarget).parents('li:first');
			var elem = this.draggedPos<0?$(liEl).next('li'):$(liEl).prev('li');
			if(!$(elem).is('li'))
				elem = liEl;
		}
		else
			var elem = this.lastTarget;

		this.toElem(elem, {
			easing: 'easeOutCubic',
			duration: 600,
			complete: function(){
			}
		});


	};
	this.renderPosition = function(e, u){
		e = (e || window.event);

		if(u){
			$('ul', target.rootEl).stop();
			this.startPos = this.mouseCoords(e).x;
			this.leftOffset = parseFloat($('ul', target.rootEl).position().left)||0;
//			alert(this.leftOffset);
		}

		this.pos = this.mouseCoords(e).x + this.leftOffset;//this.leftOffset
		this.left = this.pos - this.startPos;

//		if($.browser.SafariMobile)
//			alert(this.left);

		this.setPosition(-this.left);
//		$('ul', target.rootEl).css({'left': ((this.left/this.totalWidth*100)+'%')});

		this.wasEntered = true;
	};
	this.mouseCoords = function(e){
		if(e.pageX)// || e.pageY
			return {
				x: e.pageX
//				y: e.pageY
			};
		return {
			x: (e.clientX + document.body.scrollLeft - document.body.clientLeft)
//			y: e.clientY + document.body.scrollTop  - document.body.clientTop
		};
	};


	$(document).bind('mouseup', function(e){
		if(target.down)
			target.mouseUp(e);
	}).bind('mousemove', function(e){
		if(target.down)//target.over ||
			target.renderPosition(e);
		if(target.down)
			return false;
	}).bind('mousedown', function(e){
		if(target.down)
			return false;
	});

	$('ul', this.rootEl).bind('mousemove', function(e){
		if(!target.over)
			target.mouseEnter(e);
	}).bind('mouseleave', function(e){
		if(target.over)
			target.mouseLeave(e);
		target.over = target.wasEntered = false;
	}).bind('mousedown', function(e){
		target.mouseDown(e);
	}).bind('mouseup', function(e){
		target.mouseUp(e);
	});


};
FadeSlider.prototype._setDragSwipeTouch = function(){
	var target = this;

	if($.fn.swipe)
	$(document).swipe({
		swipeStatus: function(event, phase, direction, distance){

			if(phase === 'start'){
				$('ul', target.rootEl).stop();
				target.leftOffset = -parseFloat($('ul', target.rootEl).position().left)||0;
				target.startTime = event.timeStamp;
			}

			/** If we are moving before swipe, and we are going Lor R in X mode, or U or D in Y mode then drag. */
			if(phase === 'move' && (direction === 'left' || direction === 'right')){
				switch(direction){
					case 'left':
						target.setPosition((target.leftOffset + distance), null, false);
						break;
					case 'right':
						target.setPosition((target.leftOffset - distance), null, false);
						break;
				}
			}
			else if(phase === 'cancel'){
				target.toElem(target.currentElem, {
					easing: 'easeOutCubic',
					duration: 600
				});
			}
			else if(phase === 'end'){
				if((event.timeStamp-target.startTime) > 500 && Math.abs((target.leftOffset + (parseFloat($('ul', target.rootEl).position().left)||0))) < (target.screen.w/2))
					target.toElem(target.currentElem, {
						easing: 'easeOutCubic',
						duration: 800
					});
				else
					switch(direction){
						case 'left':
							target.next({
								easing: 'easeOutCubic',
								duration: 500
							});
							break;
						case 'right':
							target.prev({
								easing: 'easeOutCubic',
								duration: 500
							});
							break;
					}
			}

		},
		allowPageScroll: 'vertical',
		triggerOnTouchEnd: true,
		fingers: 1,
		threshold: 75
	});

};
FadeSlider.prototype.prev = function(cb){
	if(!this.currentElem)
		this.currentElem = $('ul li:first', this.rootEl);
	this.toElem($(this.currentElem).prev('li'), cb);
};
FadeSlider.prototype.next = function(cb){
	if(!this.currentElem)
		this.currentElem = $('ul li:first', this.rootEl);
	this.toElem($(this.currentElem).next('li'), cb);
};
FadeSlider.prototype.onNavigate = function(fn){
	this.navigateFn = fn;
};
FadeSlider.prototype.callOnNavigate = function(){
	this.navigateFn.apply(this, [{
		isFirst: !$(this.currentElem).prev('li').is('li'),
		isLast: !$(this.currentElem).next('li').is('li')
	}]);
};
FadeSlider.prototype._setTotalWidth = function(){
	var target = this;
	this.totalWidth = 0;
	$('ul li', this.rootEl).each(function(i){
		target.totalWidth += $(this).width();
	});

	$(this.rootEl).css({'width': this.totalWidth});

	this.screen = $.screen();
	$(this.rootEl).parents('div:first').css({'width': this.screen.w, 'height': this.screen.h, 'overflow': 'hidden'});
};
FadeSlider.prototype.getLeftPos = function(elem, cb){
	var left = 0;
	if(!$(elem).is('li'))
		var elem = $(elem).closest('li');
	$(elem).prevAll().each(function(i){
		left += $(this).width();
	});
	return left;
};
FadeSlider.prototype.setLiWidth = function(fn){
	var target = this;
	if(!typeof fn === 'function')
		return warn('No setLiWidth Callback!');
	$('ul li', this.rootEl).each(function(){
		$(this).css({'width': fn.apply(target, [this])});
	});
};
FadeSlider.prototype.refresh = function(){
	var target = this;
	this._setTotalWidth();
};
FadeSlider.prototype.onSlide = function(fn){
		this._onSlide = fn;
};
FadeSlider.prototype.setPosition = function(left, cb, animate){
//	fire(cb);
	var target = this;
	var args = this.opts

	if(typeof cb === 'object')
		args = cb;

	var _cb = function(){
//		fire(cb);
//		if(typeof cb === 'function')
//			cb.apply(target, []);
		if(typeof target._onSlide === 'function')
			target._onSlide.apply(target, [target.left]);
	};

	var data = {'left':(-(left/this.totalWidth*100)+'%')};

//	imgs.css("-webkit-transition-duration", (duration/1000).toFixed(1) + "s");
//
//	//inverse the number we set in the css
//	var value = (distance<0 ? "" : "-") + Math.abs(distance).toString();
//
//	imgs.css("-webkit-transform", "translate3d("+value +"px,0px,0px)");

	if(animate){
		if($.easing){
			/** if we have this code, the callback will call each time a new one, so we call a cb twice,... */
//			if(typeof args.complete=== 'function')
//				cb = args.complete;
			args.complete = _cb;
			$('ul', this.rootEl).stop().animate(data, args);
		}
		else
			$('ul', this.rootEl).stop().animate(data, this.opts.duration, null, _cb);
	}
	else
		$('ul', this.rootEl).css(data);
};
FadeSlider.prototype.toElem = function(elem, cb){
//	this.refresh();
	if($(elem).closest('li').is('li'))
		this.currentElem = $(elem).closest('li');
	this.left = this.getLeftPos(this.currentElem);
	this.setPosition(this.left, cb, true);
	this.callOnNavigate();
};



jQuery.extend(jQuery.browser, {
    SafariMobile: navigator.userAgent.toLowerCase().match(/iP(hone|ad)/i)
});


