/**
 * @author Rasmus F. Rasmussen
 * (C) 2009
 * dependencies: collision.js, get_scrollbar_width.js, resize_image.js
 * 
 * Added may 5th 2010:
 * 	arguments: canvasColor, callBack
 * 	methods: selectable_image.set_dimensions()
 * 	dependency: resize_image.js
 * 
 * Changes may 5th 2010:
 * 	approx. line 89 - set_dimensions
 *  approx. lile 513 & 525  - subtract the parent elements value from mouseCooords
 */


function Image_Sequencer(name, selectMode, canvasWidth, canvasHeight, canvasLeft, canvasTop, canvasColor, imageWidth, imageHeight, imageBorderWidth, borderSelectColor, borderHighlightColor, imageArray_str, imageDirectory )
{
	this.name = name; // Name of the workspace. Also the ID of the DIV screen object.
	this.canvasWidth = canvasWidth; // Width of the workspace.
	this.canvasHeight = canvasHeight;
	this.canvasLeft = canvasLeft;
	this.canvasTop = canvasTop;
	this.canvasColor = canvasColor;
		
	this.imageWidth 		= imageWidth;
	this.imageHeight 		= imageHeight;
	this.imageBorderWidth 	= imageBorderWidth;
	
	// The canvas needs to be wide enough for at least 1 image, borders,
	// and an indentation, which is eqal to the border width, plus a scrollbar.
	this.canvasMinWidth = this.imageWidth + (this.imageBorderWidth * 3) + get_scrollbar_width();
	
	//colors
	this.selectColor = borderSelectColor;
	this.highlightColor = borderHighlightColor;
	
	this.totalImageWidth  = this.imageWidth + (this.imageBorderWidth * 2);
	this.totalImageHeight = this.imageHeight + (this.imageBorderWidth * 2);
	
	this.imageDirectory = imageDirectory;
	this.imagePath_arr = new Array(); // Holds the path of the images relative to the image folder
	if( imageArray_str != "" )
		this.imagePath_arr = imageArray_str.split("|");
	
	this.screenImageArray = new Array(); // Holds the on-screen image objects
	this.canvas; // Holds the on-screen canvas div object
	
	
	// single_select callback function pointer
	this.single_select_callback = null;
	
	// var to store wheter the preloading is done
	this.loadingComplete = false;
	
	this.collisionManager;
	
	// variables used by the draw fuctionality, which should really be moved to a separate function...
	this.selectionRangeBegin = -1;
	this.selectionRangeEnd 	= -1;
	
	this.dragDetector = new circularCollidable(0,0,0);
	this.mouseIsDown = false;
	
	// var to distinguish between modes "drag_select, select, drag" default is select
	this.mode = selectMode;
	
	this.mouseCoordX;
	this.mouseCoordY;
	
	this.append = function( parent )
	{
		parent.appendChild( this.canvas );
	};
	
	this.remove = function()
	{
		this.canvas.parentNode.removeChild( this.canvas );
	};
	this.currentlyLoadingImg = 0;
	this.preload = function()
	{
		if( !this.currentlyLoadingImg == 0 )
		{
			if( !this.screenImageArray[this.currentlyLoadingImg - 1 ].imageElement.complete )
				return;
			//do;
			this.screenImageArray[ this.currentlyLoadingImg - 1 ].set_border(this.imageBorderWidth, 'solid', 'transparent');
			this.screenImageArray[ this.currentlyLoadingImg - 1 ].set_dimensions( this.imageWidth, this.imageHeight );
			this.canvas.appendChild(this.screenImageArray[ this.currentlyLoadingImg - 1 ].divElement );
			this.position_screen_images();
			this.draw();
		}
		
		if( this.currentlyLoadingImg != this.imagePath_arr.length )
		{
			// load;
			++this.currentlyLoadingImg;
			// set image src and border
			this.screenImageArray[ this.currentlyLoadingImg - 1 ].imageElement.src = this.imageDirectory + this.imagePath_arr[ this.currentlyLoadingImg - 1 ];
		}
		
		else
		{
			//complete;
			this.loadingComplete = true;
		}
	};
	
	this.set_single_select_callback_function = function(pointer)
	{
		this.single_select_callback = pointer;
	};
	
	this.position_screen_images = function()
	{
		// create collision_manager
		this.collisionManager = new collisionManager();
		
		var imageSurfaceWidth = this.canvasWidth;
		// will a scroolbar be nedded?
		var totalHeightOfAllImages = Math.ceil( this.screenImageArray.length / Math.floor( this.canvasWidth/this.totalImageWidth ) ) * this.totalImageHeight;
		if( totalHeightOfAllImages > this.canvasHeight )
		{
			// Making room for a scrollbar.
			imageSurfaceWidth -= get_scrollbar_width();
		}
		
		// Variables to store the position of the curent image
		var x = 0;
		var y = 0;
		
		for( i = 0; i < this.screenImageArray.length; ++i )
		{
			if( !this.screenImageArray[i].complete() )
				break;
			
			if (x + this.totalImageWidth > imageSurfaceWidth)
			{
				// Check if no images were positioned in the current row.
				// This is to preven an endless loop if there isn't room for a single image.
				if(x == this.imageBorderWidth)
				{
					alert("ERROR: There is no room for even a single image!");
					break;
				}
				y += this.totalImageHeight;
				x = 0;
				
				
			}
			
			this.screenImageArray[i].set_position( x, y );
						
			// create collidable for the image
			this.collisionManager.createSquareCollidable(this.screenImageArray[i].get_positionX() + this.imageBorderWidth,
														 this.screenImageArray[i].get_positionX()+ this.imageWidth + this.imageBorderWidth,
														 this.screenImageArray[i].get_positionY() + this.imageBorderWidth,
														 this.screenImageArray[i].get_positionY()+ this.imageHeight + this.imageBorderWidth);
			x += this.totalImageWidth;
			
		}
		
		//this.canvas.style.height = y + this.totalImageHeight + "px";
	};
	
	this.set_canvas_size = function( width, height )
	{
		if( width < this.canvasMinWidth )
			width = this.canvasMinWidth;
		
		this.canvasWidth = width;
		this.canvasHeight = height;
		
		this.canvas.style.width = width + "px";
		this.canvas.style.height = height + "px";
		this.position_screen_images();
	};
	
	this.set_canvas_position = function( x, y )
	{
		this.canvas.style.left = x + "px";
		this.canvas.style.top = y + "px";
		this.position_screen_images();
	};
	
	// Removes ONLY the first selected image from the sequence
	this.remove_selected_image_from_image_array = function()
	{
		if( this.loadingComplete == false )
		{
			alert('Please allow the images to load before deleting.');
			return;
		}
		
		for (i = 0; i < this.screenImageArray.length; ++i)
		{
			if (this.screenImageArray[i].selected)
			{
				this.canvas.removeChild(this.screenImageArray[i].divElement);
				
				//Remove entry from this.screenImageArray
				this.screenImageArray.splice(i, 1);
				
				//Remove entry from this.imagePath_arr
				this.imagePath_arr.splice(i, 1);
				
				//Break out of the loop
				break;
			}
		}
		this.deselect_all();
		this.position_screen_images();
		this.draw();
	};
	
	this.rearrange_image_array = function(source, destination, numOfImgs)
	{
		source 		= parseInt(source);
		destination = parseInt(destination);
		numOfImgs 	= parseInt(numOfImgs);
		
		if (source < destination) 
		{
			var destIndex = destination -1;
			
			var evalStr = "this.imagePath_arr.splice(" + destination + ", 0";
			for (i = 0; i < numOfImgs; i++) 
			{
				var currentIndex = parseInt(source) + i;
				evalStr += ", this.imagePath_arr[" + currentIndex + "]";
			}
			evalStr += ")";
			
			eval(evalStr);
			
			this.imagePath_arr.splice(source, numOfImgs);
		}
		else if (source > destination) 
		{
			var destIndex = destination;
			var evalStr = "this.imagePath_arr.splice(" + destIndex + ", 0";
			for (i = 0; i < numOfImgs; i++) 
			{
				var currentIndex = source + i;
				evalStr += ", this.imagePath_arr[" + currentIndex + "]";
			}
			evalStr += ")";
			//alert (tempArrStr);
			eval(evalStr);
			
			this.imagePath_arr.splice(source + numOfImgs, numOfImgs);
		}
		this.update_image_paths();
		
		//make sure the dragged pictures are now selected
		this.deselect_all();
		for( i = destination; i < destination + numOfImgs; ++i)
		{
			if(destination < source)
			{
				this.screenImageArray[i].select();
			}
			else
			{
				this.screenImageArray[i-numOfImgs].select();
			}
		}
	};
	
	this.update_image_paths = function ()
	{
		for (i in this.imagePath_arr)
		{
			this.screenImageArray[i].imageElement.src = this.imageDirectory + this.imagePath_arr[i];
			this.screenImageArray[i].set_dimensions( this.imageWidth, this.imageHeight );
		}
	};
	
	this.list_all_images = function()
	{
		var newImageArray_str = "";
		for (i = 0; i < this.imagePath_arr.length; ++i) 
		{
			if (newImageArray_str != "") 
				newImageArray_str += "|";
			newImageArray_str += this.imagePath_arr[i];
		}
		return newImageArray_str;
	};
	
	this.list_selected_images = function ()
	{
		var selectedImages = "";
		
		for (i = 0; i < this.screenImageArray.length; ++i)
		{
			if (this.screenImageArray[i].selected)
			{
				if (selectedImages.length != 0)
					selectedImages += "|";
				
				selectedImages += this.imagePath_arr[i];
			}
		}
		return selectedImages;
	};
	
	this.list_unselected_images = function ()
	{
		var unselectedImages = "";
		
		for (i = 0; i < this.screenImageArray.length; ++i)
		{
			if (!this.screenImageArray[i].selected)
			{
				if (unselectedImages.length != 0)
					unselectedImages += "|";
				
				unselectedImages += this.imagePath_arr[i];
			}
		}
		return unselectedImages;
	};
	
	this.event_handler_drag_select = function( event )
	{
		switch (event.type)
		{
			case 'mousemove':
			
			if(event.shiftKey)
			{
				var selectedIndex = -1;
				for(i in this.screenImageArray)
				{
					if(this.screenImageArray[i].selected)
					{
						selectedIndex = i;
						break;
					}
				}

				if(selectedIndex != -1)
				{
					var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
					if (collided != -1)
					{
						this.selectionRangeBegin = selectedIndex < collided ? selectedIndex : collided;
						this.selectionRangeEnd = selectedIndex > collided ? selectedIndex : collided;
					}
				}
			}
				
			else
			{
				this.selectionRangeBegin = -1;
				this.selectionRangeEnd = -1;
			}
				
			if( this.dragDetector.radius !=0 &&	
				this.dragDetector.checkCollision(this.mouseCoordX, this.mouseCoordY) == false &&
				this.mouseIsDown)
				{
					var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
					if (collided != -1)
					{
						if (!this.screenImageArray[collided].selected) 
							this.screenImageArray[collided].select();
					}
	
					this.mode = 'drag';
				}
					
			break;
			
			case 'mousedown':
			
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
				
				if (collided != -1)
				{
					//alert(collided);
					this.dragDetector.centerX = this.mouseCoordX;
					this.dragDetector.centerY = this.mouseCoordY;
					this.dragDetector.radius = 10;
						
					if (event.shiftKey) 
					{
						var selectedIndex = -1;
						for(i in this.screenImageArray)
						{
							if(this.screenImageArray[i].selected)
							{
								selectedIndex = i;
								break;
							}
						}
		
						if(selectedIndex != -1)
						{
							this.selectionRangeBegin = selectedIndex < collided ? selectedIndex : collided;
							this.selectionRangeEnd = selectedIndex > collided ? selectedIndex : collided;
						}
						
						this.select_range(this.selectionRangeBegin, this.selectionRangeEnd);
					}
					
					else if(this.screenImageArray[collided].selected == false)
					{
						this.deselect_all();
						this.screenImageArray[collided].select();
					}
				}
			break;
			
			case 'mouseup':
				this.dragDetector.radius = 0;
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
				if (collided != -1 && this.screenImageArray[collided].selected)
				{
					if (!event.shiftKey)
					{
						this.deselect_all();
						this.screenImageArray[collided].select();
					}
				}
				
			break;
			
		}
	};
	
	this.event_handler_drag = function( event )
	{
		switch (event.type)
		{
			case 'mousemove':
				// display move representation
				
				this.canvas.style.cursor = "url('../grafik/icon_drag.png'), default";
				
				// display destination graphics if collided
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
				if (collided != -1)
				{
					if (!this.screenImageArray[collided].selected)
					{
						// Find the index of the first selected image, if there are any
						var firstSelectedIndex = -1;
						for (i in this.screenImageArray) 
						{
							if (this.screenImageArray[i].selected) 
							{
								firstSelectedIndex = i;
								break;
							}
						}
						
						if (collided < firstSelectedIndex )
						{
							this.insertIcon.style.left = this.screenImageArray[collided].get_positionX() - 2 + "px";
							this.insertIcon.style.top = this.screenImageArray[collided].get_positionY() - 2 + "px";
							this.insertIcon.style.visibility = "visible";
						}
						else
						{
							this.insertIcon.style.left = this.screenImageArray[collided].get_positionX() + this.totalImageWidth - 2 + "px";
							this.insertIcon.style.top = this.screenImageArray[collided].get_positionY() - 2 + "px";
							this.insertIcon.style.visibility = "visible";
						}
					}
				}
				else
				{
					this.insertIcon.style.visibility = "hidden";
					this.insertIcon.style.left = "0px";
					this.insertIcon.style.top = "0px";
				}
				
			break;
			
			case 'mousedown':
			break;
			
			case 'mouseup':
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
				
				if (collided != -1 && !this.screenImageArray[collided].selected) 
				{
					// Find the index of the first selected image, if there are any
					var firstSelectedIndex = -1;
					for (i in this.screenImageArray) 
					{
						if (this.screenImageArray[i].selected) 
						{
							firstSelectedIndex = i;
							break;
						}
					}
					
					// If at least 1 image was selected
					if (firstSelectedIndex != -1) 
					{
						// Find out how many images were selected
						numberOfSelectedImages = 0;
						for( i = firstSelectedIndex; i < this.screenImageArray.length && this.screenImageArray[i].selected; ++i)
							++numberOfSelectedImages;
						
						if (collided < firstSelectedIndex )
							this.rearrange_image_array(firstSelectedIndex, collided, numberOfSelectedImages);
						else
							this.rearrange_image_array(firstSelectedIndex, collided+1, numberOfSelectedImages);
					}
				}
				
				this.canvas.style.cursor = "auto";
				this.insertIcon.style.visibility = "hidden";
				this.mode = 'drag_select';
			break;
			
		}
	};
	
	this.event_handler_select = function( event )
	{
		switch (event.type)
		{
			case 'mousemove':
			break;
			
			case 'mousedown':
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
					if (collided != -1)
					{
						this.screenImageArray[collided].toggle_selected();
						this.selectionRangeBegin = collided;
					}
					
			break;
			
			case 'mouseup':
			break;
			
		}
	};
	
	this.event_handler_single_select = function( event )
	{
		switch (event.type)
		{
			case 'mousemove':
			break;
			
			case 'mousedown':
				var collided = this.collisionManager.checkCollision(this.mouseCoordX, this.mouseCoordY);
					if (collided != -1)
					{
						this.deselect_all();
						this.screenImageArray[collided].select();
						this.selectionRangeBegin = collided;
						if( this.single_select_callback )
							this.single_select_callback( collided, this.imagePath_arr[collided] );
					}
					
			break;
			
			case 'mouseup':
			break;
			
		}
	};
	
	this.event_handler = function ( event )
	{
		if (!event)
		var event = window.event;
		
		switch (event.type)
		{
			case 'mousemove':
				if (event.pageX)
					this.mouseCoordX = event.pageX;
				else
					this.mouseCoordX = event.clientX;
				
				if(this.canvas.style.left)
					this.mouseCoordX = this.mouseCoordX - parseInt(this.canvas.style.left);
				
				// subtract the parent elements left value
				if(this.canvas.parentNode)
					this.mouseCoordX = this.mouseCoordX - this.canvas.parentNode.offsetLeft;
				
				if (event.pageY)
					this.mouseCoordY = event.pageY + this.canvas.scrollTop;
				else
					this.mouseCoordY = event.clientY + this.canvas.scrollTop;
			
				if(this.canvas.style.top)
					this.mouseCoordY = this.mouseCoordY - parseInt(this.canvas.style.top);
				
				// subtract the parent elements top value
				if(this.canvas.parentNode)
					this.mouseCoordY = this.mouseCoordY - this.canvas.parentNode.offsetTop;
			break;
			
			case 'mouseup':
				this.mouseIsDown = false;				
			break;
			
			case 'mousedown':
				if( event.preventDefault )
					event.preventDefault();
				this.mouseIsDown = true;
			break;
		}
		
		switch (this.mode)
		{
			case 'drag_select':
			this.event_handler_drag_select(event);
			break;
			
			case 'drag':
			this.event_handler_drag(event);
			break;
			
			case 'select':
			this.event_handler_select(event);
			break;
			
			case 'single_select':
			this.event_handler_single_select(event);
			break;
			
			default:
			alert(this.mode + " does not exist.");
			break;
		}
		
		//document.getElementById('debugger1').innerHTML = this.mode;
		
		this.draw();
	};
	
	this.draw = function ()
	{
		// draw it		
		for(i = 0; i < this.screenImageArray.length; ++i)
		{
			if (this.screenImageArray[i].selected) 
				this.screenImageArray[i].set_border_color( this.selectColor );
			else
			{
				this.screenImageArray[i].set_border_color( "transparent" );
				
				if (i >= this.selectionRangeBegin && i <= this.selectionRangeEnd) 
					this.screenImageArray[i].set_border_color( this.highlightColor );
			}
		}
	};
	
	this.change_select_color = function(color)
	{
		this.selectColor = color;
		this.draw();
	};
	
	this.change_highlight_color = function(color)
	{
		this.highlightColor = color;
		this.draw();
	};
	
	this.select_all = function()
	{
		for(i = 0; i < this.screenImageArray.length; ++i)
		{
			this.screenImageArray[i].select();
		}
		this.selectionRangeBegin = -1;
		this.selectionRangeEnd = -1;
	};
	
	this.deselect_all = function()
	{
		for(i = 0; i < this.screenImageArray.length; ++i)
		{
			this.screenImageArray[i].deselect();
		}
		this.selectionRangeBegin = -1;
		this.selectionRangeEnd = -1;
	};
	
	this.select = function( index )
	{
		if( index < this.screenImageArray.length )
			this.screenImageArray[index].select();
	};
	
	this.select_range = function(begin, end)
	{
		for(i = begin; i <= end; ++i)
			this.screenImageArray[i].select();
	};

	// Draw objects on screen and fill screenImageArray with selectable images
	
	this.canvas = document.createElement( "div" );
	this.canvas.setAttribute( "id", this.name );
	this.canvas.style.position = "absolute";
	this.canvas.style.overflow = "auto";
	this.canvas.style.top = this.canvasTop + 'px';
	this.canvas.style.left = this.canvasLeft + 'px';
	this.canvas.style.backgroundColor = this.canvasColor;
	
	this.insertIcon = document.createElement( "div" );
	this.insertIcon.setAttribute( "id", this.name + "_insertIcon" );
	this.insertIcon.style.position = "absolute";
	this.insertIcon.style.visibility = "hidden";
		
	var insertIcon_line = document.createElement( "div" );
	insertIcon_line.setAttribute( "id", this.name + "_insertIcon_line" );
	insertIcon_line.style.position = "absolute";
	insertIcon_line.style.backgroundColor = this.selectColor;
	insertIcon_line.style.width = "2px";
	insertIcon_line.style.left = "1px";
	insertIcon_line.style.height = this.totalImageHeight + "px";
	
	var insertIcon_dot = document.createElement( "div" );
	insertIcon_dot.setAttribute( "id", this.name + "_insertIcon_dot" );
	insertIcon_dot.style.position = "absolute";
	insertIcon_dot.style.backgroundColor = this.selectColor;
	insertIcon_dot.style.width = "4px";
	insertIcon_dot.style.height = "4px";
	insertIcon_dot.style.top = this.totalImageHeight/2 - 2 + 'px';
	
	this.canvas.appendChild(this.insertIcon);
	this.insertIcon.appendChild(insertIcon_line);
	this.insertIcon.appendChild(insertIcon_dot);
	
	for( var i = 0; i < this.imagePath_arr.length; ++i )
		this.screenImageArray.push( new Selectable_Image() );
	
	this.set_canvas_size( this.canvasWidth, this.canvasHeight );
}

function Selectable_Image()
{
	this.divElement = document.createElement( 'div' );
	this.imageElement = document.createElement( 'img' );
	this.divElement.appendChild( this.imageElement );
	
	this.selected = false;
	this.divElement.style.position = 'absolute';
	this.imageElement.style.position = 'absolute';
	var positionX = 0;
	var positionY = 0;
	var width = 0;
	var height = 0;
	
	this.complete = function()
	{
		return this.imageElement.complete;
	};
	
	this.set_position = function( x, y )
	{
		this.positionX = x;
		this.positionY = y;
		this.divElement.style.left 	= x + "px";
		this.divElement.style.top 	= y + "px";
	};
	
	this.set_dimensions = function ( width, height )
	{
		this.divElement.style.width = width + 'px';
		this.divElement.style.height = height + 'px';
		resize_image( this.imageElement, width, height );
		
		var imageWidth = parseInt( this.imageElement.style.width );
		var imageHeight = parseInt( this.imageElement.style.height );
		this.imageElement.style.left = ( width - imageWidth ) / 2 + 'px';
		this.imageElement.style.top = ( height - imageHeight ) / 2 + 'px';
		
	};
	
	this.set_border_color = function( color )
	{
		this.divElement.style.borderColor = color;
	};
	
	this.set_border = function( width, style, color )
	{
		this.divElement.style.border = width + 'px ' + style + ' ' + color;
	};
	
	this.get_positionX = function()
	{
		return this.positionX;
	};
	
	this.get_positionY = function()
	{
		return this.positionY;
	};
	
	this.select = function()
	{
		this.selected = true;
	};
	
	this.deselect = function()
	{
		this.selected = false;
	};
	
	this.toggle_selected = function()
	{
		this.selected = !this.selected;
	};
}
