/* 
 *	@copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * 	@autor: Vasily Mamaevsky (polochka@design.ru)
 * 	@update: Dmitry Kharchenko (dims@design.ru)
 *
 *	Requires:
 *	- jquery
 *	- speedometer
 *	- draggable
 */		
function AlsScroll() {
	var tmp = 0;
	
	var s_timer = {};
	var s_mouse = new MouseVelocityMeter('.card-extra-navigation__suggestions');
	
	var s_width = 0;
	var s_item_w = 0;
	var s_items_q = 0;
	var s_items_on_screen = 0;
	
	// константы анимации
	var STD_MAX_X = 0;
	var STD_FPS = 63;
	var STD_ANIMATION_T = Math.round(1000 / STD_FPS); // 16 для 63 фпс 
	var STD_DURATION = 608;
	
	var STD_ACC_X = 0.95;
	var STD_PENETRATION_DEC_X = 0.996;
	var STD_PENETRATION_ACC_X = 0.92;
	var STD_MIN_VEL = 50;
	var STD_SM_PENETRATION_MIN_VEL = 100;
	var STD_VEL_X = 200;
	var STD_MAX_VEL = 1500;
	
	// начальные параметры анимации
	var anim_state = {
		i: 0,
		pos_x: 0,
		vel_x: 0,
		start_vel_x: 0,
		acc_x: 0,
		duration: 0
	}
	
	var s_teaser;
	var s_teasers;
	var s_dom_teasers;
	var s_viewport;
	var s_scroll;
	var resize_proc_running	= false;
	var s_viewport_w = 0;
	
	var s_end_pos = 0;
	
	var s_items_q_tmp = 0;
	
	var xDraggableAPI = null;
	
	// Флаги
	var s_mouse_button = false;
	var s_drag_mode = false;
	var s_animation_stop = false;
	var s_penetration_started = false;
	var s_penetration_ended = false;
	var s_arrow_is_pushwed = false;
	var s_animation_is_running = false;
	var s_animation_was_stopped_by_click = false;
	
	function _init() {		
		// initialize scroll
		
		s_body = $('body');
		s_scroll = $('.card-extra-navigation__scroll-container');
		s_viewport = $('.card-extra-navigation__viewport', s_body);
		s_teasers = $('.card-extra-navigation__suggestions', s_viewport);
		s_dom_teasers = s_teasers.get(0);
		s_teaser = $('.card-extra-navigation__card-suggestion', s_teasers);
		
		s_larr = $('.scroll-larr');
		s_rarr = $('.scroll-rarr');
		
		s_teasers.xdraggable();
		xDraggableAPI = s_teasers.data('xdraggable');
		
		s_items_q = s_teaser.length;
		s_item_w = s_teaser.outerWidth(true); //include element padding/margin
		
		s_display_w = s_scroll.width();
		s_items_on_screen = Math.floor(s_display_w / s_item_w);
		
		s_viewport_w = s_items_on_screen * s_item_w;
		
		s_viewport.width(s_viewport_w);
		s_teasers.width( (s_item_w) * (s_items_q + 1));
		s_end_pos = Math.round((-1) * s_item_w * (s_items_q - s_items_on_screen));

		// Set initial position to show selected item
		var s_currentTeaser = s_teaser.filter('.card-extra-navigation__card-suggestion_current'); 
		if(s_currentTeaser.length > 0){
			var s_current_rpos = -s_currentTeaser.position().left;
			s_teasers.css('left', (s_current_rpos > s_end_pos ) ? s_current_rpos : s_end_pos );
		}
		
		// Events ///////////////////////////////
		$(window).resize(function(){
			s_display_w = s_scroll.width();
			
			var s_items_on_screen_tmp = Math.floor(s_display_w / s_item_w);
			
			if (s_items_on_screen_tmp != s_items_on_screen) {
				s_items_on_screen = s_items_on_screen_tmp;
				
				s_viewport_w = s_items_on_screen * s_item_w;
				s_viewport.width(s_viewport_w);
				
				s_end_pos = Math.round((-1) * s_item_w * (s_items_q - s_items_on_screen));
				if (GetPos() < s_end_pos) s_teasers.css('left', s_end_pos);
				
				UpdateButtons();
			}			
		});
		
		//prevent IE selection and image/link dragging
		s_dom_teasers.ondragstart = function () { return false; };
		s_dom_teasers.onselectstart = function () { return false; };
		
		$(document).mouseup(function(e) {
			e.preventDefault();
			
			if (s_mouse_button) {
				s_animation_stop = false;
				
				// получаем скорость и позицию
				var vel = s_mouse.getV() * 1000 // пикселей в секунду
				vel = (Math.abs(vel) > STD_MAX_VEL) ? ( Math.abs(vel) / vel ) * STD_MAX_VEL : vel;
				var cur_pos = GetPos();
				
				if (vel != 0) {
					SetSteveMobbsAnimation(vel, cur_pos);
				} else if (cur_pos > STD_MAX_X) {
					UpdateButtons(STD_MAX_X);
					s_teasers.animate({
						left: STD_MAX_X
					}, STD_DURATION/2);
				} else if (cur_pos < s_end_pos) {
					UpdateButtons(s_end_pos);
					s_teasers.animate({
						left: s_end_pos
					}, STD_DURATION/2);
				}
			} 
			
			s_mouse_button = false;
			s_body.removeClass('grabbing');
			xDraggableAPI.setSensitivity(1.0);			
		}).click(function(){
			s_drag_mode = false;
			s_animation_was_stopped_by_click = false;
		});
			
		s_teasers.mousedown(function(e){
			e.preventDefault();				
			s_mouse_button = true;
			s_body.addClass('grabbing'); 
			StopAnimation();
		});
		
		s_teasers.mousemove(function(e){
			var cur_pos = GetPos();
			
			if (s_mouse_button) {				
				if 	(cur_pos > 0 || cur_pos < s_end_pos) { 
					// сопротивляемся, КАК НА МАКЕ
					xDraggableAPI.setSensitivity(0.5); 
				}
				else { 
					xDraggableAPI.setSensitivity(1.0); 
				}
				
				if (!s_drag_mode) s_drag_mode = true;
			}
		});
		
		$("a", s_viewport).click(function(e){
			if (s_drag_mode || s_animation_was_stopped_by_click) e.preventDefault();
		});
		
		// стрелочки по краям экрана
		s_larr.add(s_rarr).mouseup(function(e){
			s_arrow_is_pushed = false;
		}).click(function(){ return false; });
		
		s_larr.mousedown(function(e){
			s_arrow_is_pushed = true;
			if (!$(this).hasClass('.scroll_disabled'))
				MoveLeft();
			return false;
		});
		
		s_rarr.mousedown(function(e){
			s_arrow_is_pushed = true;
			if (!$(this).hasClass('.scroll_disabled'))
				MoveRight();
			return false;
		});
	}
	
	
	function GetPos() {	return s_teasers.position().left; }
	function GetItemsCountOnPage(canvas_w, item_w) { return Math.floor(canvas_w / item_w); }
	function StopAnimation() { 
		s_animation_stop = true;		
		if (s_animation_is_running) s_animation_was_stopped_by_click = true;
		s_teasers.stop();
	}
	
	
	/*
	 *	Функции анимации
	 */
	
	function MoveLeft() {
		StopAnimation();
		
		var s_pos_x = GetPos();
		
		if (!s_arrow_is_pushed) {
			var index = Math.ceil(Math.abs(s_pos_x / s_item_w));
			var new_x = (-1) * s_item_w * (index - 1);
			
			if (new_x > STD_MAX_X) new_x = 0;		
			UpdateButtons(new_x);
			
			s_teasers.animate({
				left: new_x
			}, 2*STD_DURATION, 'easeOutExpo');
			
		} else if (s_pos_x < STD_MAX_X) {
			if (Math.abs(s_pos_x - STD_MAX_X) > s_item_w) {
				var step = 30;
				s_dom_teasers.style.left = s_pos_x + step + 'px';
				setTimeout(MoveLeft, STD_ANIMATION_T);
			}
			else 
				s_teasers.animate({
					left: STD_MAX_X
				}, {
					duration: 2*STD_DURATION, 
					easing: 'easeOutExpo',
					complete: UpdateButtons
				});
			
		} else {
			UpdateButtons();
		}
	}
	
	function MoveRight() {
		StopAnimation();
		
		var s_pos_x = GetPos();
		
		if (!s_arrow_is_pushed) {
			var index = Math.floor(Math.abs(s_pos_x / s_item_w));
			var new_x = (-1) * s_item_w * (index + 1);
			
			if (new_x < s_end_pos) new_x = s_end_pos;
			UpdateButtons(new_x);
			
			s_teasers.animate({
				left: new_x
			}, 2*STD_DURATION, 'easeOutExpo');
		} else if (s_pos_x > s_end_pos) {
			if (Math.abs(s_pos_x - s_end_pos) > 400) {
				var step = 30;
				s_dom_teasers.style.left = s_pos_x - step + 'px';
				setTimeout(MoveRight, STD_ANIMATION_T);
			}
			else 
				s_teasers.animate({
					left: s_end_pos
				}, {
					duration: 2*STD_DURATION, 
					easing: 'easeOutExpo',
					complete: UpdateButtons
				});
		} else {
			UpdateButtons();
		}
	}
	
	// Функция устанавливает параметры анимации 
	// и запускает таймер
	function SetSteveMobbsAnimation(vel_x, pos_x) {			
		anim_state = {
			pos_x: pos_x,
			vel_x: vel_x,
			acc_x: STD_ACC_X,
			i: 0
		};
		
		s_animation_is_running = true;
		s_teasers.addClass('animated');
		
		s_timer.t = 0;
		s_timer.obj = setTimeout(SteveMobbsAnimation, STD_ANIMATION_T);
	}
	
	// Итерация анимации
	function SteveMobbsAnimation() {		
		/*
		// Сначала необходимо проверить не доехала ли лента до края	
		if ((anim_state.pos_x > STD_MAX_X || anim_state.pos_x < s_end_pos) && !s_penetration_started) {
			
			// Начало вылезания за край — как бы новая анимация.
			// Необходимо сбросить счетчик, чтобы сччитать скорость по более мудреному закону
			s_penetration_started = true;
			anim_state.acc_x = STD_PENETRATION_DEC_X;
			anim_state.i = 2;
		} else if ((Math.abs(anim_state.vel_x) <= STD_SM_PENETRATION_MIN_VEL) && s_penetration_started && !s_penetration_ended) {
			// Середина, движение обратно
			s_penetration_ended = true; 
			anim_state.acc_x = STD_PENETRATION_ACC_X;
			
			// Возвращаем в крайнее положение
			if (anim_state.pos_x > STD_MAX_X) {
				anim_state.vel_x = GetImpulseVelocity(anim_state.pos_x, STD_MAX_X, STD_PENETRATION_ACC_X);
			}
			else if (anim_state.pos_x < s_end_pos) {
				anim_state.vel_x = GetImpulseVelocity(anim_state.pos_x, s_end_pos, STD_PENETRATION_ACC_X);
			}
		}
		
		// И только после этого проверить, достигли ли мы конца анимации
		// Условие: если анимация остановлена внешним воздействием или скорость 
		// упала ниже определенной минимальной, при этом не происходит вылезания за край
		if (s_animation_stop || (Math.abs(anim_state.vel_x) <= STD_MIN_VEL && !s_penetration_started)) {			
			ClearAnimation();
			return;
		} else {
			// Считаем скорость
			if (!s_penetration_started || (s_penetration_started && s_penetration_ended)) {
				// Для простого движения и для возвращения на край
				// Сначала всегда проверка: не пора ли закончить все это?
				if (Math.abs(anim_state.vel_x) <= STD_MIN_VEL) {
					ClearAnimation();
					return;
				}
				
				anim_state.vel_x *= anim_state.acc_x;
			} else if (s_penetration_started && !s_penetration_ended) {
				// Для вылезания за край, но до остановки
				anim_state.start_vel_x = anim_state.vel_x;
				anim_state.vel_x = PenetrationVelocityEase (anim_state.start_vel_x, anim_state.acc_x, anim_state.i);
			}
			
			anim_state.pos_x += anim_state.vel_x * STD_ANIMATION_T / 1000;
			s_dom_teasers.style.left = Math.round(anim_state.pos_x);
			
			anim_state.i++;
			s_timer.obj = setTimeout(SteveMobbsAnimation, STD_ANIMATION_T);
		}
		*/
		
		// Сначала необходимо проверить не доехала ли лента до края	
		if (anim_state.pos_x > STD_MAX_X || anim_state.pos_x < s_end_pos) {
			var vel = Math.round(anim_state.vel_x);
			var vel_abs = Math.abs(vel);
			
			var t1 = (anim_state.i == 0 ? 0 : 100 + Math.round(Math.sqrt(vel_abs/2)));						
			var x1 = Math.round(anim_state.i == 0 ? anim_state.pos_x : anim_state.pos_x + Math.round(vel/20));
			var t2 = 500 + Math.round(Math.sqrt(vel_abs)) * 10;
		}
		if (anim_state.pos_x > STD_MAX_X) {						
			s_teasers.animate({
				left: x1
			}, {
				duration: t1,
				easing: 'easeOutQuad',
				complete: function(){
					s_teasers.animate({
						left: STD_MAX_X
					}, {
						duration: t2,
						easing: 'easeOutExpo',
						complete: function(){
							ClearAnimation();
						}
					});
				}
			});
			return;	
		} else if (anim_state.pos_x < s_end_pos) {			
			s_teasers.animate({
				left: x1
			}, {
				duration: t1,
				easing: 'easeOutQuad',
				complete: function(){
					s_teasers.animate({
						left: s_end_pos
					}, {
						duration: t2,
						easing: 'easeOutExpo',
						complete: function(){
							ClearAnimation();
						}
					});
				}
			});
			return;	
		}
		
		
		if (s_animation_stop) {
			ClearAnimation();
			return;
		} else if (Math.abs(anim_state.vel_x) <= STD_MIN_VEL){
			SnapAnimation();
			return;
		} else {
			anim_state.vel_x *= anim_state.acc_x;
			anim_state.pos_x += anim_state.vel_x * STD_ANIMATION_T / 1000;
			s_dom_teasers.style.left = Math.round(anim_state.pos_x) + 'px'; 
			
			anim_state.i++;
			
			s_timer.obj = setTimeout(SteveMobbsAnimation, STD_ANIMATION_T);
		}
	}
	
	function SnapAnimation() {
		var closest_pos_delta = Math.abs(anim_state.pos_x) % s_item_w;
		
		// Pull to closest
		closest_pos_delta = (closest_pos_delta > s_item_w / 2) 
		? s_item_w - closest_pos_delta 
		: -closest_pos_delta;
		
		// Pull back anyway
//		closest_pos_delta = (anim_state.vel_x > 0)
//		? Math.abs(closest_pos_delta)
//		: -closest_pos_delta;
		
		s_teasers.animate({
			left: Math.round(anim_state.pos_x) - closest_pos_delta + 'px'
		}, STD_DURATION * 2, 'easeOutExpo');
		
		ClearAnimation();
	}
	
	/*
	// Передаются параметры для начала движения и итерацию i от начала движения
	function PenetrationVelocityEase(start_vel, acc, i) { 
		return start_vel * Math.pow(acc, i * i * i); 
	}
		
	function GetImpulseVelocity(pos_x, end_pos_x, dec) {
		var vel_x = STD_MIN_VEL;
		var tmp_x = 0;
		var d_x = 0;
		
		d_x = Math.abs(end_pos_x - pos_x);
		
		while (tmp_x <= d_x) {
			vel_x /= dec;
			tmp_x += vel_x / STD_FPS;
		}
		
		vel_x *= (pos_x > end_pos_x ? -1 : 1);
		
		return vel_x;
	}
	*/
	function ClearAnimation() {
		//FIXME: was clearInterval here
		clearTimeout(s_timer.obj);
		s_timer.obj = null;
		s_timer.t = 0;
		
		s_penetration_started = false;
		s_penetration_ended = false;
		s_animation_stop = false;
		s_animation_is_running = false;
		s_teasers.removeClass('animated');
		
		anim_state.vel_x = 0;
		anim_state.acc_x = STD_ACC_X;
		
		UpdateButtons();
	}

	
	function UpdateButtons(cur_pos) {
		if (typeof(cur_pos) == 'undefined') cur_pos = GetPos();
		
		if ((Math.abs(cur_pos - STD_MAX_X) <= 10) || (cur_pos > STD_MAX_X))
			s_larr.addClass('scroll_disabled');
		else
			s_larr.removeClass('scroll_disabled');
		
		if ((Math.abs(cur_pos - s_end_pos) <= 10) || (cur_pos < s_end_pos))
			s_rarr.addClass('scroll_disabled');
		else
			s_rarr.removeClass('scroll_disabled');
	}

	return {
		init: _init
	}
}

$(document).ready(function(){
	if($('.card-extra-navigation__suggestions').length > 0){
		var alsScroll = new AlsScroll();
		alsScroll.init();
	}
});
