﻿/*
 * @include "/jTweener/src/jTweener.js"
 * @include "/kv/js/EventDispatcher.js"
 */

$(function(){
	var titles = ['Жара', 'Еще глоточек', 'Еще бутылочку'];
	
	
	/**
	 * Возвращает случайно сгенерированную кривую Безье,
	 * описывающую движение «горящего» элемента
	 */
	function createHeatPath(spread){
		 var p1 = spread || 20;
		 var p2 = (spread || 20) * 2;
		 var p3 = (spread || 20) * 2.5;
		
		
		return {
			x1: 0,
			x2: Math.random() * p1 - p1/2,
			cx1: Math.random() * p2 - p2/2,
			cx2: Math.random() * p3 - p3/2
		};
	}
	
	var temperature = function(){
		var conatiner = $('#temperature');
		
		var offset = 2;
		
		function getValue(){
			return parseInt(conatiner.find('.value').text());
		}
		
		function setValue(value){
			conatiner.find('.value').text(value);
		}
		
		function updateValue(change){
			var sign = (change > 0) ? 1 : -1;
			var cur_value = getValue();
			var delay = Math.abs(change) > 3 ? 150 : 700;
			for (var i = 0; i < Math.abs(change); i++) {
				(function(i){
					setTimeout(function(){
						setValue(cur_value + sign * (i + 1));
					}, i * delay);
				})(i);
			}
		}
		
		return {
			increase: function(){
				updateValue(offset);
			},
			decrease: function(){
				updateValue(-offset);
			},
			
			getValue: getValue,
			resetValue: function(){
				updateValue(30 - getValue());
			}
		}
	}();
	
	/**
	 * Эффект «жара»: создает ощущение, что элементы с классом heat искускают жар. 
	 */
	var heat = function(){
		/** Контейнер «жары» */
		var heat_container = $('<div id="heat"></div>').prependTo($('#content'));
		
		/** Элементы, которые должны пускать «жар» */
		var heat_items = $('#content .heat');
		
		/**
		 * Идентификатор таймера, создающего частицы жара
		 */
		var timer = null;
		
		/** Цвет максимально раскаленного элемента */
		var heat_color = '#eca44b';
		
		/** Конечный цвет раскаленной частицы */
		var end_color = '#efece5';
		
		
		/**
		 * Клонирует элементы, пускающие жар, в контейнер <code>heat_container</code>.
		 * Именно клонированные создают эффект жары
		 * @return {jQuery} Набор клонированных элементов
		 */
		function cloneItems(){
			var clones = [];
			heat_items.each(function(){
				var pos = {
					left: this.offsetLeft,
					top: this.offsetTop,
					width: $(this).width(),
					height: $(this).height()
				};
				
				var clone = $(this).clone().css(pos);
				clones.push(clone.get(0));
				heat_container.append(clone);
			});
			return $(clones);
		}
	
		// for debug
		var max_emits = 30;
		var emits = 0;
		
		
		
		function emitParticle(){
			var particles = cloneItems();
			var anim_time = 3;
			
			emits++;
			if (emits >= max_emits) {
				heat.stop();
				emits = 0;
				return;
			}
				
			jTweener.addTween(particles, {
				top: '-=60',
				time: anim_time,
				transition: 'easeinquad',
				onComplete: function(){
					particles.remove();
				}
			});
			
			jTweener.addTween(particles, {
				color: heat_color,
				time: anim_time / 2,
				transition: 'linear'
			});
			
			jTweener.addTween(particles, {
				color: end_color,
				delay: anim_time / 2,
				time: anim_time / 2,
				transition: 'linear'
			});
			
			/** Путь (кривая Безье), вдоль которого движутся частицы жары */
			var emit_path = createHeatPath();
			
			// записываю начальное положение каждой частицы
			particles.each(function(ix){
				particles.eq(ix).data('original_x', this.offsetLeft);
			});
			
			// эта анимация прижимает частицы у кривой emit_path
			jTweener.addTween({value: function(val){
				if (!arguments.length) {
					return 0;
				} else {
					var dx = jTweener.Utils.bezier3(val, emit_path.x1, emit_path.cx1, emit_path.cx2, emit_path.x2);
					particles.each(function(ix){
						var p = particles.eq(ix);
						p.css('left', p.data('original_x') + dx || 0);
					});
				}
			}}, {
				value: 1,
				time: anim_time,
				transition: 'linear'
			});
		}
		
		return {
			start: function(){
				heat.stop();
				startIdle();
				timer = setInterval(emitParticle, 130);
			},
			
			stop: function(){
				stopIdle();
				clearInterval(timer);
			}
		};
	}();
	
	/**
	 * Бутылка кваса
	 */
	var bottle = function(){
		var container = $('#bottle');
		/**
		 * Список фраз (выбираются именно контейнеры, а не сами фразы)
		 */
		var phrases = container.find('ul.phrases');
		
		/** Конечный цвет фразы, вылетающей из бутылки  */
		var end_color = '#b84939';
		// начальный цвет указывается в CSS
		var start_color = phrases.find('li:first').css('color');
		
		
		var dispatcher = new EventDispatcher();
		
		var EVENT = {
			START: 'onStart',
			STOP: 'onStop'
		};
		
		/** Изображения бутылки */
		var images = [];
		
		/** Количество загруженных на данный момент картинок */
		var loaded_images = 0;
		
		var is_loaded = false;
		
		var is_busy = false;
		var ns = 'phrases';
		
		jTweener.addNSAction({onComplete: function(){
			is_busy = false;
		}}, ns);
		
		
		
		
		/** Текущее состояние бутылки */
		var cur_state = 1;
		
		/**
		 * Загрузка всех картинок
		 */
		function loadImages(){
			for (var i = 1; i <= 10; i++) {
				var img = new Image();
				images.push(img);
				img.onload = function(){
					loaded_images++;
					if (loaded_images == images.length) {
						is_loaded = true;
					}
				}
				img.src = './i/bottle2/' + i + '.jpg';
			}
		}
		
		function animatePhrase(ix){
			var time = 5;
			var delay_delta = 0.4;
			
			if (ix < 0) {
				dispatcher.dispatchEvent(EVENT.STOP);
				return;
			}
			
			var cur_items = phrases.eq(ix).find('li').each(function(i){
				var delay = i * delay_delta;
				var obj = $(this).css({color: start_color, top: 0, fontSize: 0});
				is_busy = true;
				
				var emit_path = createHeatPath(130);
				
				jTweener.addTween(this, {
					color: end_color,
					namespace: ns,
					fontSize: 30,
					time: time * 0.7,
					delay: delay,
					transition: 'easeoutcubic'
				});
				
				jTweener.addTween(this, {
					top: -260,
					time: time,
					namespace: ns,
					delay: delay,
					onStart: function(){
						obj.show();
					},
					onComplete: function(){
						obj.hide();
					},
					transition: 'easeoutquad'
				});
				
				jTweener.addTween({value: function(val){
					if (!arguments.length) {
						return 0;
					} else {
						var dx = jTweener.Utils.bezier3(val, emit_path.x1, emit_path.cx1, emit_path.cx2, emit_path.x2);
						obj.css('left', dx);
					}
				}}, {
					value: 1,
					namespace: ns,
					time: time,
					delay: delay,
					transition: 'easeinoutcubic'
				});
			});
			
			setTimeout(function(){
				dispatcher.dispatchEvent(EVENT.STOP);
			}, (delay_delta * cur_items.length + time) * 1000);
			
		}
		
		function changeBottle(){
			is_busy = true;
			dispatcher.dispatchEvent(EVENT.START);
			var img = container.find('img');
			temperature.resetValue();
			img.fadeOut(500, function(){
				img.css('top', -1000).attr('src', images[0].src).show();
				jTweener.addTween(img, {
					top: 0,
					time: 1,
					delay: 0.2,
					transition: 'easeoutbounce',
					onComplete: function(){
						is_busy = false;
						cur_state = 1;
						dispatcher.dispatchEvent(EVENT.STOP);
					}
				});
			})
		}
		
		function nextSlide(){
			if (is_busy)
				return false;
			else if (cur_state >= images.length) {
				cur_state = 0;
				changeBottle();
				return false;
			}
			
			dispatcher.dispatchEvent(EVENT.START);
			var old_img = container.find('img');
			var new_img = old_img.clone()
				.attr('src', images[cur_state].src)
				.hide()
				.appendTo(container)
				.fadeIn(500, function(){
					old_img.remove();
				});
			
			animatePhrase(cur_state - 2);
			cur_state++;
			if (cur_state <= images.length) {
				new_img.click(nextSlide);
			} else {
				new_img.addClass('last');
			}
		}
		
		$(window).load(loadImages);
		
		return {
			nextSlide: nextSlide,
			EVENT: EVENT,
			addEventListener: function(type, listener){
				dispatcher.addEventListener(type, listener);
			},
			
			removeEventListener: function(type, listener){
				dispatcher.removeEventListener(type, listener);
			},
			
			getTotalImages:function(){
				return images.length;
			},
			
			getCurrentImage: function(){
				return cur_state;
			}
		};
	}();
	
	// контроллер
	var wait_timer;
	
	function startIdle(){
		if (temperature.getValue() < 100) {
			wait_timer = setTimeout(function(){
				temperature.increase();
				heat.start();
			}, 10000);
		}
	}
	
	function stopIdle(){
		clearTimeout(wait_timer);
	}
	
	var weather_title = $('#weather .pseudo-href');
	var original_title_color = weather_title.css('color');
	var bg_color = $(document.body).css('background-color');
	
	function hideTitle(){
		jTweener.addTween(weather_title, {
			color: bg_color,
			borderBottomColor: bg_color,
			time: 0.5
		});
	}
	
	function showTitle(new_title){
		if (new_title) {
			weather_title.text(new_title);
		}
		
		jTweener.addTween(weather_title, {
			color: original_title_color,
			borderBottomColor: original_title_color,
			time: 0.5
		});
		
	}
	
	var is_started = false;
	bottle.addEventListener(bottle.EVENT.START, function(){
		stopIdle();
		if (is_started) {
			hideTitle();
		}
		temperature.decrease();
	});
	
	bottle.addEventListener(bottle.EVENT.STOP, function(){
		startIdle();
		var new_title = '';
		if (!is_started) {
			is_started = true;
			return;
		}
		
		switch(bottle.getCurrentImage()) {
			case 0:
			case 1:
				new_title = titles[0];
				break;
			case bottle.getTotalImages():
				new_title = titles[2];
				break;
			default:
				new_title = titles[1];
		}
		
		showTitle(new_title);
	});
	
	$('#weather .pseudo-href, #weather img, #bottle img').click(function(){
		bottle.nextSlide();
	});
	
	
	startIdle();
});








