/**
 *	ImageFlow 0.9
 *
 *	This code is based on Michael L. Perrys Cover flow in Javascript.
 *	For he wrote that "You can take this code and use it as your own" [1]
 *	this is my attempt to improve some things. Feel free to use it! If
 *	you have any questions on it leave me a message in my shoutbox [2].
 *
 *	The reflection is generated server-sided by a slightly hacked  
 *	version of Richard Daveys easyreflections [3] written in PHP.
 *	
 *	The mouse wheel support is an implementation of Adomas Paltanavicius
 *	JavaScript mouse wheel code [4].
 *
 *	Thanks to Stephan Droste ImageFlow is now compatible with Safari 1.x.
 *
 *
 *	[1] http://www.adventuresinsoftware.com/blog/?p=104#comment-1981
 *	[2] http://shoutbox.finnrudolph.de/
 *	[3] http://reflection.corephp.co.uk/v2.php
 *	[4] http://adomas.org/javascript-mouse-wheel/
 */

function iflow_lightbox()
{
		/* Configuration variables */
	var conf_reflection_p = 0.5;         // Sets the height of the reflection in % of the source image 
	var conf_focus = 4;                  // Sets the numbers of images on each side of the focussed one
	var lightbox_conf_slider_width = 11;          // Sets the px width of the slider div
	var lightbox_images_cursor = 'pointer';  // Sets the cursor type for all images default is 'default'
	var lightbox_slider_cursor = 'pointer';  // Sets the slider cursor type: try "e-relightbox_size" default is 'default'

	/* Id names used in the HTML */
	var lightbox_conf_imageflow = 'lightbox_iflow';    // Default is 'imageflow'
	var lightbox_conf_loading = 'lightbox_loading';        // Default is 'loading'
	var lightbox_conf_images = 'lightbox_images';          // Default is 'images'
	var lightbox_conf_captions = 'lightbox_captions';      // Default is 'captions'
	var lightbox_conf_scrollbar = 'lightbox_scrollbar';    // Default is 'scrollbar'
	var lightbox_conf_slider = 'lightbox_slider';          // Default is 'slider'

	/* Define global variables */
	var lightbox_caption_id = 0;
	var new_lightbox_caption_id = 0;
	var lightbox_current = 0;
	var lightbox_target = 0;
	var mem_lightbox_target = 0;
	var lightbox_timer = 0;
	var lightbox_array_images = new Array();
	var lightbox_new_slider_pos = 0;
	var lightbox_dragging = false;
	var lightbox_dragobject = null;
	var lightbox_dragx = 0;
	var lightbox_posx = 0;
	var new_lightbox_posx = 0;
	var lightbox_xstep = 150;

	this.onload = function(name)
	{
		if(document.getElementById(lightbox_conf_imageflow))
		{
			iflow_lightbox.hide(lightbox_conf_loading);
			iflow_lightbox.refresh(true);
			iflow_lightbox.show(lightbox_conf_images);
			iflow_lightbox.show(lightbox_conf_scrollbar);
			iflow_lightbox.initMouseWheel();
			iflow_lightbox.initMouseDrag();
			iflow_lightbox.show('lightbox_iflow_buttons');

			this.glideTo((Math.ceil(lightbox_array_images.length/2) - 1) * -lightbox_xstep, Math.ceil(lightbox_array_images.length/2) - 1);
		}
	}

	this.step = function()
	{
		switch (lightbox_target < lightbox_current-1 || lightbox_target > lightbox_current+1) 
		{
			case true:
				iflow_lightbox.moveTo(lightbox_current + (lightbox_target-lightbox_current)/3);
				window.setTimeout(iflow_lightbox.step, 50);
				lightbox_timer = 1;
				break;

			default:
				lightbox_timer = 0;
				break;
		}
	}

	this.glideTo = function(x, new_lightbox_caption_id)
	{	
		/* Animate gliding to new x position */
		lightbox_target = x;
		mem_lightbox_target = x;
		if (lightbox_timer == 0)
		{
			window.setTimeout(this.step, 50);
			lightbox_timer = 1;
		}
		
		/* Display new caption */
		lightbox_caption_id = new_lightbox_caption_id;
		caption = lightbox_img_div.childNodes.item(lightbox_array_images[lightbox_caption_id]).getAttribute('alt');
		if (caption == '') caption = '&nbsp;';
		lightbox_caption_div.innerHTML = caption;

		/* Set scrollbar slider to new position */
		if (lightbox_dragging == false)
		{
			lightbox_new_slider_pos = (lightbox_scrollbar_width * (-(x*100/((lightbox_max-1)*lightbox_xstep))) / 100) - new_lightbox_posx;
			lightbox_slider_div.style.marginLeft = (lightbox_new_slider_pos - lightbox_conf_slider_width) + 'px';
		}
	}

	this.moveTo = function(x)
	{
		lightbox_current = x;
		var zIndex = lightbox_max;
		
		/* Main loop */
		for (var index = 0; index < lightbox_max; index++)
		{
			var image = lightbox_img_div.childNodes.item(lightbox_array_images[index]);
			var lightbox_current_image = index * -lightbox_xstep;

			/* Don't display images that are not conf_focussed */
			if ((lightbox_current_image+lightbox_lightbox_max_conf_focus) < mem_lightbox_target || (lightbox_current_image-lightbox_lightbox_max_conf_focus) > mem_lightbox_target)
			{
				image.style.visibility = 'hidden';
				image.style.display = 'none';
			}
			else 
			{
				var z = Math.sqrt(10000 + x * x) + 100;
				var xs = x / z * lightbox_size + lightbox_size;

				/* Still hide images until they are processed, but set display style to block */
				image.style.display = 'block';
			
				/* Process new image height and image width */
				var new_img_h = (image.h / image.w * image.pc) / z * lightbox_size;
				switch ( new_img_h > lightbox_lightbox_max_height )
				{
					case false:
						var new_img_w = image.pc / z * lightbox_size;
						break;

					default:
						new_img_h = lightbox_lightbox_max_height;
						var new_img_w = image.w * new_img_h / image.h;
						break;
				}
				var new_img_top = (lightbox_images_width * 0.18 - new_img_h) + lightbox_images_top + ((new_img_h / (conf_reflection_p + 1)) * conf_reflection_p);

				/* Set new image properties */
				image.style.left = xs - (image.pc / 2) / z * lightbox_size + lightbox_images_left + 'px';
				if(new_img_w && new_img_h)
				{ 
					image.style.height = new_img_h + 'px'; 
					image.style.width = new_img_w + 'px'; 
					image.style.top = new_img_top + 'px';
				}
				image.style.visibility = 'visible';

				/* Set image layer through zIndex */
				switch ( x < 0 )
				{
					case true:
						zIndex++;
						break;

					default:
						zIndex = zIndex - 1;
						break;
				}
				
				/* Change zIndex and onclick function of the focussed image */
				switch ( image.i == lightbox_caption_id )
				{
					case false:
						image.onclick = function() { iflow_lightbox.glideTo(this.x_pos, this.i); }
						break;

					default:
						zIndex = zIndex + 1;
						image.onclick = function() { if (this.url) { document.location = this.url } }
						break;
				}
				image.style.zIndex = zIndex;
			}
			x += lightbox_xstep;
		}
	}

	/* Main function */
	this.refresh = function(onload)
	{
		/* Cache document objects in global variables */
		lightbox_imageflow_div = document.getElementById(lightbox_conf_imageflow);
		lightbox_img_div = document.getElementById(lightbox_conf_images);
		lightbox_scrollbar_div = document.getElementById(lightbox_conf_scrollbar);
		lightbox_slider_div = document.getElementById(lightbox_conf_slider);
		lightbox_caption_div = document.getElementById(lightbox_conf_captions);

		/* Cache global variables, that only change on refresh */
		lightbox_images_width = lightbox_img_div.offsetWidth;
		lightbox_images_top = lightbox_imageflow_div.offsetTop;
		lightbox_images_left = lightbox_imageflow_div.offsetLeft;
		lightbox_lightbox_max_conf_focus = conf_focus * lightbox_xstep;
		lightbox_size = lightbox_images_width * 0.5;
		lightbox_scrollbar_width = lightbox_images_width * 0.4;
		lightbox_conf_slider_width = lightbox_conf_slider_width * 0.5;
		lightbox_lightbox_max_height = lightbox_images_width * 0.51;

		/* Change images div properties */
		lightbox_img_div.style.height = '240px';

		/* Change captions div properties */
		lightbox_caption_div.style.width = lightbox_images_width + 'px';

		/* Change scrollbar div properties */
		lightbox_scrollbar_div.style.marginTop = lightbox_images_width * 0.01 + 'px';
		lightbox_scrollbar_div.style.marginLeft = lightbox_images_width * 0.3 + 'px';
		lightbox_scrollbar_div.style.width = lightbox_scrollbar_width + 'px';

		if (document.getElementById('lightbox_iflow_buttons'))
		{
			document.getElementById('lightbox_iflow_buttons').style.marginTop = -lightbox_images_width * 0.0058 + 'px';
			document.getElementById('lightbox_iflow_buttons').style.left = (lightbox_images_width * 0.3) - 20 + 'px';
			document.getElementById('lightbox_iflow_buttons').style.width = (lightbox_scrollbar_width) + 45 + 'px';
		}

		/* Set slider attributes */
		lightbox_slider_div.onmousedown = function () { iflow_lightbox.dragstart(this); };
		lightbox_slider_div.style.cursor = lightbox_slider_cursor;

		/* Cache EVERYTHING! */
		lightbox_max = lightbox_img_div.childNodes.length;
		var i = 0;
		for (var index = 0; index < lightbox_max; index++)
		{ 
			var image = lightbox_img_div.childNodes.item(index);
			if (image.nodeType == 1)
			{
				lightbox_array_images[i] = index;
				
				/* Set image onclick by adding i and x_pos as attributes! */
				image.onclick = function() { iflow_lightbox.glideTo(this.x_pos, this.i); }
				image.x_pos = (-i * lightbox_xstep);
				image.i = i;
				
				/* Add width and height as attributes ONLY once onload */
				if(onload == true)
				{
					image.w = image.width;
					image.h = image.height;
				}

				/* Check source image format. Get image height minus reflection height! */
				switch ((image.w + 1) > (image.h / (conf_reflection_p + 1))) 
				{
					/* Landscape format */
					case true:
						image.pc = 118;
						break;

					/* Portrait and square format */
					default:
						image.pc = 100;
						break;
				}

				/* Set ondblclick event */
				image.url = image.getAttribute('longdesc');
				image.ondblclick = function() { if (this.url) { document.location = this.url } }

				/* Set image cursor type */
				image.style.cursor = lightbox_images_cursor;

				i++;
			}
		}
		lightbox_max = lightbox_array_images.length;

		/* Display images in lightbox_current order */
		this.moveTo(lightbox_current);
		this.glideTo(lightbox_current, lightbox_caption_id);
	}

	/* Show/hide element functions */
	this.show = function(id)
	{
		var element = document.getElementById(id);
		element.style.visibility = 'visible';
	}
	this.hide = function(id)
	{
		var element = document.getElementById(id);
		element.style.visibility = 'hidden';
		element.style.display = 'none';
	}

	/* Handle the wheel angle change (delta) of the mouse wheel */
	this.handle = function(delta)
	{
		var change = false;
		switch (delta > 0)
		{
			case true:
				if(lightbox_caption_id >= 1)
				{
					lightbox_target = lightbox_target + lightbox_xstep;
					new_lightbox_caption_id = lightbox_caption_id - 1;
					change = true;
				}
				break;

			default:
				if(lightbox_caption_id < (lightbox_max-1))
				{
					lightbox_target = lightbox_target - lightbox_xstep;
					new_lightbox_caption_id = lightbox_caption_id + 1;
					change = true;
				}
				break;
		}

		/* Glide to next (mouse wheel down) / previous (mouse wheel up) image */
		if (change == true)
		{
			this.glideTo(lightbox_target, new_lightbox_caption_id);
		}
	}

	/* Event handler for mouse wheel event */
	this.wheel = function(event)
	{
		var delta = 0;
		if (!event) event = window.event;
		if (event.wheelDelta)
		{
			delta = event.wheelDelta / 120;
		}
		else if (event.detail)
		{
			delta = -event.detail / 3;
		}
		if (delta) iflow_lightbox.handle(delta);
		if (event.preventDefault) event.preventDefault();
		event.returnValue = false;
	}

	/* Initialize mouse wheel event listener */
	this.initMouseWheel = function()
	{
		if(window.addEventListener) lightbox_imageflow_div.addEventListener('DOMMouseScroll', this.wheel, false);
		lightbox_imageflow_div.onmousewheel = this.wheel;
	}

	/* This function is called to drag an object (= slider div) */
	this.dragstart = function(element)
	{
		lightbox_dragobject = element;
		lightbox_dragx = lightbox_posx - lightbox_dragobject.offsetLeft + lightbox_new_slider_pos;
	}

	/* This function is called to stop lightbox_dragging an object */
	this.dragstop = function()
	{
		lightbox_dragobject = null;
		lightbox_dragging = false;
	}

	/* This function is called on mouse movement and moves an object (= slider div) on user action */
	this.drag = function(e)
	{
		lightbox_posx = document.all ? window.event.clientX : e.pageX;
		if(lightbox_dragobject != null)
		{
			lightbox_dragging = true;
			new_lightbox_posx = (lightbox_posx - lightbox_dragx) + lightbox_conf_slider_width;

			/* Make sure, that the slider is moved in proper relation to previous movements by the glideTo function */
			if(new_lightbox_posx < ( - lightbox_new_slider_pos)) new_lightbox_posx = - lightbox_new_slider_pos;
			if(new_lightbox_posx > (lightbox_scrollbar_width - lightbox_new_slider_pos)) new_lightbox_posx = lightbox_scrollbar_width - lightbox_new_slider_pos;
			
			var slider_pos = (new_lightbox_posx + lightbox_new_slider_pos);
			var step_width = slider_pos / ((lightbox_scrollbar_width) / (lightbox_max-1));
			var image_number = Math.round(step_width);
			var new_lightbox_target = (image_number) * -lightbox_xstep;
			var new_lightbox_caption_id = image_number;

			lightbox_dragobject.style.left = new_lightbox_posx + 'px';
			iflow_lightbox.glideTo(new_lightbox_target, new_lightbox_caption_id);
		}
	}

	/* Initialize mouse event listener */
	this.initMouseDrag = function()
	{
		obj = document.getElementById(lightbox_conf_imageflow);
		obj.onmousemove = this.drag;
		obj.onmouseup = this.dragstop;

		/* Avoid text and image selection while lightbox_dragging  */
		obj.onselectstart = function () 
		{
			if (lightbox_dragging == true)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
	}

	this.getKeyCode = function(event)
	{
		event = event || window.event;
		return event.keyCode;
	}
}