// récupéré du site

/* Transformations mathématiques de base */

function line(x, coef, yo, xo) {
	return coef * (x - xo) + yo;
}

function bline(x, coef, yo, xo) {
	return x <= xo ? line(x, coef, yo, xo) : line(x, -coef, yo, xo);
}

function parabol(x, coef, yo, xo) {
	return coef * Math.pow((x - xo), 2) + yo;
}

function circle(x, coef, yo, xo, amp) {
	x = (x - xo) > amp ? x = amp + xo : x;
	return - coef * Math.sqrt(Math.pow(amp, 2) - Math.pow((x - xo), 2)) + yo;
}

function arctan(x, coef, yo, xo, amp) {
	return amp * Math.atan(coef * (x - xo)) + yo;
}

function gauss(x, coef, yo, xo, amp) {
	return amp * Math.exp(- Math.pow((x - xo), 2) / (2 * Math.pow(coef, 2))) + yo;
}

function agnesi(x, coef, yo, xo, amp) {
	return amp * Math.pow(amp, 3) / (Math.pow((x - xo) / coef, 2) + Math.pow(amp, 2)) + yo;
}

function clearDim(dim)
{
	dim = "" + dim;
	if (dim.indexOf('px') != -1 || dim.indexOf('em') != -1 || dim.indexOf('pt') != -1) return dim.substring(0, dim.length - 2);
	if (dim.indexOf('%') != -1 ) return dim.substring(0, dim.length - 1);
	return dim * 1;
}

var SlideFlow = Class.create(
{
	initialize:function(element)
	{
		this.element = $(element);

		this.options = Object.extend(
		{
			// Effets
			depth:			3,
			reflects:		false,
			blur:			true,
			layer_mode:		false,
			
			// Animation
			closure:		5 / 1000,
			period:			65,
			dichotomie	:	5,
			
			// Slider
			slider:			true,
			handle:			'handle',
			track:			'track',
			scrollArea:		'scroll-area',

			// Params
			x_function:		'arctan', 	// arctan | line
			x_max	:		180 / 100,
			x_coef	:		1,
			y_function: 	'parabol', 	// parabol | circle
			y_coef	:		0.5,
			r_function:		'agnesi', 	// flat | gauss | agnesi | bline
			r_coef:			1,
			a_function:		'agnesi', 	// flat | gauss | agnesi | bline
			a_coef:			0.8,
			
			// Messages
			current_img_title: "No title",
			other_img_title: "No title",
			title_array: null,
			start_img_id: 0
	
		}, arguments[1] || {});
		
		if (SWFAddress.getValue() != "/")
		{
			id = SWFAddress.getValue().replace(/\/photo(\d*)\/{0,1}/,'$1');
			id = isNaN(id) ? 0 : id - 1;
			this.current_id = (1 * id);
		}
		else 
		{
			this.current_id = 0;
		}
		this.target_id = this.current_id;
//		document.observe('resize', this.refresh.bindAsEventListener(this));
	},
	initImages:function()
	{
		this.image_max_width = 0;
		this.image_max_height = 0;

		this.div_loading 	= this.element.down('.loading');
		this.div_images 	= this.element.down('.images');
		this.div_caption	= this.element.down('.captions');
		
		this.images = this.div_images.select('a');

		this.max_id = this.images.length;
		
		this.images.each(function(obj, id)
		{
			w = obj.style.width; // alert(id + ".style.width: " + w)
			if (!w) {
				w = obj.width; // alert(id + ".width: " + w)
			}
			if (!w) {
				w = obj.getWidth(); // alert(id + ".getWidth(): " + w)
			}

			h = obj.style.height; if (!h) h = obj.height; if (!h) h = obj.getHeight();
			
			obj.w = clearDim(w);
			obj.h = clearDim(h);
			
			this.image_max_width = Math.max(this.image_max_width, obj.w);
			this.image_max_height = Math.max(this.image_max_height, obj.h);

			if (this.options.reflects)
			{
				Reflection.add(obj.down(), { opacity: 0.5 });
			}
			obj.observe('click', function(e)
			{	
				if (this.current_id == id) { return; }
				if (this.options.slider)
				{
					this.slider.setValue(id);
					this.glideTo(id);
				}
				Event.stop(e);
			}.bindAsEventListener(this));
		}.bind(this));
		
		// Init du div conteneur
		//this.div_images.absolutize();
		this.images_height = Math.round(this.image_max_height);
		this.div_images.setStyle(
		{
			left:	'0px',
			top:	'0px',
			height:	this.images_height+'px'
		});
		
		// Création d'un slider
		if (this.options.slider)
		{
			$(this.options.scrollArea).show();
			this.slider = new Control.Slider(this.options.handle, this.options.track, 
			{
				axis: 'horizontal',
				range: $R(0,this.max_id-1),
				values: $R(0,this.max_id-1),
				onSlide: this.onSlide.bind(this)
//				onChange: this.onSlide.bind(this)
			});

			// Capture du scroll de la souris
			this.delta = 0;
			Event.observe(this.element, "mousewheel", this.onRoll.bindAsEventListener(this));
			Event.observe(this.element, "DOMMouseScroll", this.onRoll.bindAsEventListener(this)); // Firefox*/
			
			// On observe le clavier
			Event.observe(document, 'keydown', function(e)
			{
				if (e.keyCode == Event.KEY_LEFT) 
				{	
					id = Math.max(this.current_id - 1, 0);
				}	
				else if (e.keyCode == Event.KEY_RIGHT) 
				{
					id = Math.min(this.current_id + 1, this.max_id - 1);
				}
				else { return; }
				if (this.current_id == id) return; 
				this.slider.setValue(id);
				this.glideTo(id);
			}.bindAsEventListener(this));
		};
		
		
		this.running = false;
		this.div_loading.hide();
		this.slider.setValue(this.current_id);
		this.refresh();
	},
	onSlide:function(step)
	{
		this.glideTo(step);
		this.element.fire("slideflow:onSlide");
	},
	onRoll:function(e) 
	{
		this.delta = Event.wheel(e);
		id = (this.delta > 0) ? Math.max(this.current_id - this.delta, 0) : Math.min(this.current_id - this.delta, this.max_id - 1);
		this.slider.setValue(id);
		this.glideTo(id);
	},
	nextStep:function(current, target) 
	{
		return current + (target - current) / this.options.dichotomie;
	},
	play:function(step) 
	{
		step = 1 * step;
		this.timer = new PeriodicalExecuter(function()
		{
			if (step == this.target_id) 
			{
				this.running = false;
				this.timer.stop();
				return;
			}		
			step = this.nextStep(step, this.target_id);
			if (Math.abs(this.target_id - step) <= this.options.closure) 
			{ 
				step = this.target_id;
			}
			this.draw(step);
		}.bind(this), this.options.period / 1000);
		
	},
	glideTo:function(id)
	{	
		id = 1 * id; 
		SWFAddress.setValue('photo' + (id + 1));		
		this.target_id = id;
		this.div_caption.update(this.images[this.target_id].down('img').alt);
		if (!this.running) 
		{
			this.running = true;
			this.play(this.current_id);
		}
		this.current_id = this.target_id;
		if ($('cur_img')) { $('cur_img').update(this.current_id + this.options.start_img_id); }
	},
	draw:function(step) 
	{	
		if (false) this.div_caption.update('cid: ' + this.current_id + '; tid: ' + this.target_id + '; step: ' + step); // debug purpose
//		this.images.each(function(obj,id)
		for (id = 0; id < this.max_id; id++)
		{
			obj = this.images[id];
			
			if (this.target_id == id) {
//				obj.down('img').title = this.options.current_img_title;
				this.options.title_array[id] = this.options.current_img_title;
			} else {
//				obj.down('img').title = this.options.other_img_title;
				this.options.title_array[id] = this.options.other_img_title;
			}
			
			if (Math.abs(id - this.target_id) < this.options.depth)
			{
				
				var x = this.fx(id, step);
				var y = this.fy(x);
				var z = this.fz(id, Math.round(step));
				var r = this.fr(id, step);
				var w = Math.round(r * obj.w);
				var h = Math.round(r * obj.h);
				var a = (z == this.max_id ? 1 : this.fa(id, step));
				
			    var a_image = (this.options.layer_mode ? 1 : a);
				var a_layer = 1 - a;
				
				if (!this.options.reflects) 
				{
					calque = obj;
					image = obj.down('img');
					
					// Propriétés du lien
					calque.setStyle({
						left: this.x2left(x - w / 2) + 'px',
						top: this.y2top(y + h) + 'px',
						zIndex: z,
						display: 'block'
					});
					// Propriétés de l'image
					image.setStyle({
						width: w + 'px',
						height: h + 'px',
						opacity: (this.options.blur) ? a_image : 1
					});
				}
				else 
				{
					calque = obj;
					image = obj.down('img');
					reflect_container = (Prototype.Browser.IE) ? obj.down('a') : obj.down('div');
					reflect = (Prototype.Browser.IE) ? obj.select('img')[1] : obj.down('canvas');
					
					// Propriétés du lien
					calque.setStyle({
						left: this.x2left(x - w / 2) + 'px',
						top: this.y2top(y + h) - 20 + 'px',
						zIndex: z,
						display: 'block'
					});
					// Propriétés de l'image
					image.setStyle({
						width: w + 'px',
						height: h + 'px',
						opacity: (this.options.blur) ? a_image : 1
					});
					// Div conteneur du reflet
					reflect_container.setStyle({
						width: w + 'px',
						height: h*1.5 + 'px'
					});
					// Propriétés du reflet
					reflect.setStyle({
						width: w + 'px',
						height: h*.5 + 'px',
						opacity: (Prototype.Browser.IE) ? 1 : a_image,
						filter: (Prototype.Browser.IE) ? 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+a_image*50+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=100)' : false
					});									
				}
			}
			else 
			{
				obj.hide();
			}
//		}.bind(this));
		}
	},
	refresh:function() 
	{
		this.images_width 	= this.div_images.offsetWidth;
		this.images_height 	= this.div_images.offsetHeight;
		this.draw(this.current_id);
		this.glideTo(this.current_id);
	},
	x2left:function(x) 
	{
		return Math.round(x + this.images_width / 2);
	},
	y2top:function(y)
	{
		return Math.round(this.images_height - y);
	},
	fx:function(i, offset) 
	{
		if (this.options.x_function == 'arctan') 
		{
			return arctan(i, this.options.x_coef, 0, offset, this.options.x_max * this.image_max_width / Math.PI);
		}
		return line(i, this.options.x_coef * this.image_max_width, 0, offset);
	},
	fy:function(x) {
		if (this.options.y_function == 'parabol') 
		{
			return parabol(x, this.options.y_coef / 1000, 0, 0);
		}
		var r = this.options.x_max * this.image_max_width / 2;
		return circle(x, this.options.y_coef, this.options.y_coef * r, 0, r);
	},
	fz:function(i, offset) 
	{
		return bline(i, 2, this.max_id, offset);
	},
	fr:function(i, offset) 
	{
		if (this.options.r_function == 'flat') 
		{
			return this.options.r_coef;
		}
		if (this.options.r_function == 'gauss') 
		{
			return gauss(i, this.options.r_coef, 0, offset, 1);
		}
		if (this.options.r_function == 'agnesi') 
		{
			return agnesi(i, this.options.r_coef, 0, offset, 1);
		}
		var r = bline(i, this.options.r_coef, 1, offset); 
		return (r < 0 ? 0 : r);
	},
	fa:function(i, offset) 
	{
		if (this.options.a_function == 'flat') 
		{
			return this.options.a_coef;
		}
		if (this.options.a_function == 'gauss') 
		{
			return gauss(i, this.options.a_coef, 0, offset, 1);
		}
		if (this.options.a_function == 'agnesi') 
		{
			return agnesi(i, this.options.a_coef, 0, offset, 1);
		}
		var a = bline(i, this.options.a_coef, 1, offset); 
		return (a < 0 ? 0 : a);
	}
});
