PhotoViewer = function( photoViewerId )
	{
		if( PhotoViewer.Instances[ photoViewerId ] != null )
		{
			delete PhotoViewer.Instances[ photoViewerId ];
		}

		this.Id = photoViewerId;
		this.Images = [];
		this.ImagesLoaded = 0;
		this.SelectedImage = null;
		this.SelectedImageElem = null;
		this.SelectedNotLoaded = false;
		this.ImageOver = false;
		
		// Events
		this.OnSelected = null;
		this.OnDeleted = null;
		this.OnMoved = null;

		this.Init();
		PhotoViewer.Instances[ photoViewerId ] = this;
	}

PhotoViewer.ScrollSpeed = 100; //Pixels per second
PhotoViewer.ShowLink = false;
PhotoViewer.ToolbarVisible = false;
PhotoViewer.DeleteEnabled = true;
PhotoViewer.SortingEnabled = true;
PhotoViewer.DeleteText = "Delete";
PhotoViewer.MoveLeftText = "Move left";
PhotoViewer.MoveRightText = "Move right";
PhotoViewer.DeleteConfirmText = "Do you really want to delete this picture?";
PhotoViewer.ThumbOpacity = 0.6;
PhotoViewer.DescOpacity = 0.7;
PhotoViewer.LayerOpacity = 0.3;
PhotoViewer.LayerHoverOpacity = 0.9;

PhotoViewer.prototype = 
	{
		Init : function()
			{
				// Get data
				this.DataElem = jQuery( '#' + this.Id ).get(0);
				if( !this.DataElem )
					return PhotoViewerError( 'Error: No data element!' );
				
				this.DrawControl();
				
				var pv = this;
				jQuery( 'li', this.DataElem ).each( function( index, elem ){
													pv.AddImage(
																	jQuery('h3', elem).html(),
																	jQuery('p', elem).html(),
																	jQuery('img', elem).get(0).src,
																	jQuery('a', elem).get(0).href,
																	elem.value
																);
												} );
				jQuery( this.DataElem ).remove();
			},
		DrawControl : function()
			{
				var pv = this;
				this.Control = jQuery('<div class="PhotoViewer"></div>').get(0);
				jQuery( this.Control ).insertBefore( this.DataElem );
				
				this.ImageContainer = jQuery('<div class="LargeImage"></div>').get(0);
				jQuery( this.Control ).append( this.ImageContainer );
				
				this.Prev = jQuery('<div class="Prev"></div>').get(0);
				jQuery( this.ImageContainer ).append( this.Prev );
				jQuery( this.Prev ).css( 'opacity', PhotoViewer.LayerOpacity );
				
				this.Next = jQuery('<div class="Next"></div>').get(0);
				jQuery( this.ImageContainer ).append( this.Next );
				jQuery( this.Next ).css( 'opacity', PhotoViewer.LayerOpacity );
				
				var arrLayers = [ this.Prev, this.Next ];
				if( PhotoViewer.ShowLink )
				{
					this.Link = jQuery('<div class="Link"></div>').get(0);
					jQuery( this.ImageContainer ).append( this.Link );
					jQuery( this.Link ).css( 'opacity', PhotoViewer.LayerOpacity );
					arrLayers.push( this.Link ); 
				}

				this.TextElem = jQuery('<div class="Description"></div>').get(0);
				jQuery( this.ImageContainer ).append( this.TextElem );
				jQuery( this.TextElem ).css( 'opacity', PhotoViewer.DescOpacity );
				jQuery( this.TextElem ).css( 'display', 'none' );
				
				this.Title = jQuery('<h3></h3>');
				jQuery( this.TextElem ).append( this.Title );

				this.Desc = jQuery('<p></p>');
				jQuery( this.TextElem ).append( this.Desc );
				
				if( PhotoViewer.ToolbarVisible )
				{
					this.ShowToolbar();
				}
				
				var thumbContainer = jQuery('<div class="Thumbs"></div>').get(0);
				jQuery( this.Control ).append( thumbContainer );
				
				this.ScrollLeft = jQuery('<div class="ScrollLeft"></div>').get(0);
				jQuery( thumbContainer ).append( this.ScrollLeft );

				this.ThumbsArea = jQuery('<div class="ThumbsArea"></div>').get(0);
				jQuery( thumbContainer ).append( this.ThumbsArea );

				this.Thumbs = jQuery('<div class="ThumbsScroll"></div>').get(0);
				jQuery( this.ThumbsArea ).append( this.Thumbs );

				this.ScrollRight = jQuery('<div class="ScrollRight"></div>').get(0);
				jQuery( thumbContainer ).append( this.ScrollRight );

				jQuery( arrLayers ).hover( 
						function(){
								jQuery(this).stop( true, true );
								jQuery(this).animate( { opacity: PhotoViewer.LayerHoverOpacity } );
							},
						function(){
								jQuery(this).stop( true, true );
								jQuery(this).animate( { opacity: PhotoViewer.LayerOpacity } );
							});

				jQuery( this.ScrollLeft ).hover( 
						function(){ pv.ScrollLeftOver(); },
						function(){ pv.ScrollLeftOut(); });
						
				jQuery( this.ScrollRight ).hover( 
						function(){ pv.ScrollRightOver(); },
						function(){ pv.ScrollRightOut(); });
						
				jQuery( this.TextElem ).hover( 
						function(){ jQuery(this).animate( { opacity: PhotoViewer.DescOpacity <= 0.8 ? PhotoViewer.DescOpacity+0.2 : 1 }, 600 ); },
						function(){ jQuery(this).animate( { opacity: PhotoViewer.DescOpacity }, 600 ); });
						
				jQuery( this.ImageContainer ).hover( 
						function()
							{
								jQuery( pv.TextElem ).stop(true,true);
								if( pv.Title.html() != "" || pv.Desc.html() != "" )
									jQuery( pv.TextElem ).slideDown(); 
								pv.ImageOver = true;
							},
						function()
							{
								jQuery( pv.TextElem ).stop(true,true);
								if( pv.Title.html() != "" || pv.Desc.html() != "" )
									jQuery( pv.TextElem ).slideUp(); 
								pv.ImageOver = false;
							});
						
				jQuery( this.Next ).click( function(){ pv.SelectNext(); } );
				jQuery( this.Prev ).click( function(){ pv.SelectPrev(); } );
			},
		AddImage : function( title, desc, imgThumbPath, imgPath, id )
			{
				var pv = this;
				var image = {
					'Title' : title,
					'Description' : desc,
					'ThumbPath' : imgThumbPath,
					'Path' : imgPath,
					'Id' : id
				};
				
				var thumbHolder = jQuery('<div class="ThumbHolder"></div>').get(0);
				jQuery( this.Thumbs ).append( thumbHolder );
				
				var img = jQuery( '<img src="' + image.ThumbPath + '" />' );
				jQuery( thumbHolder ).append( img );
				jQuery( img ).css( 'opacity', PhotoViewer.ThumbOpacity );
				
				image.Div = thumbHolder;
				image.Img = img.get(0);
				
				this.Images.push( image );
				
				//events
				jQuery(image.Img).load( function(){ CenterImage(image.Img); jQuery(image.Div).fadeIn( 1000, function(){ pv.ImageLoaded( image ); } ); } );
				jQuery(image.Div).click( function(){ pv.SelectImage( image ); } );

				jQuery(image.Img).hover( 
						function(){
								if( pv.SelectedImage != null && pv.SelectedImage.Img == this )
									return;
									 
								jQuery(this).stop( true, true );
								jQuery(this).animate( { opacity: 1 } );
							},
						function(){
								if( pv.SelectedImage != null && pv.SelectedImage.Img == this )
									return;

								jQuery(this).stop( true, true );
								jQuery(this).animate( { opacity: PhotoViewer.ThumbOpacity } );
							});

				
				if( this.SelectedImage == null )
					 this.SelectImage( image );
				
				return image;
			},
		ImageLoaded : function()
			{
				this.ImagesLoaded++;
				if( this.ImagesLoaded == this.Images.length )
				{
					this.RefreshThumbsHolder();
				}
			},
		RefreshThumbsHolder : function()
			{
				var width = 0;
				for( var i=0; i<this.Images.length; i++ )
				{
					width += jQuery( this.Images[i].Div ).outerWidth(true);
				}
				jQuery( this.Thumbs ).width( width );
				
				jQuery( this.Thumbs ).css( 'marginLeft', 0 );
				this.BringIntoView();
			},
		SelectNext : function()
			{
				if( this.Images.length <= 1 || this.SelectedNotLoaded )
					return;
				
				var selectedIndex = this.SelectedIndex();

				if( this.SelectedImage == null || selectedIndex == this.Images.length-1 )
					this.SelectImage( this.Images[0] );
				else
					this.SelectImage( this.Images[selectedIndex + 1] );
			},
		SelectPrev : function()
			{
				if( this.Images.length <= 1 || this.SelectedNotLoaded )
					return;
				
				var selectedIndex = this.SelectedIndex();

				if( this.SelectedImage == null )
				{
					this.SelectImage( this.Images[0] );
					return;
				}
				if( selectedIndex == 0 )
					this.SelectImage( this.Images[this.Images.length-1] );
				else
					this.SelectImage( this.Images[selectedIndex-1] );
			},
		SelectedIndex : function()
			{
				var selectedIndex = -1;
				if( this.SelectedImage == null || this.Images.length == 0 )
					return selectedIndex;
					
				for( var i=0; i<this.Images.length; i++ )
				{
					if( this.Images[i] == this.SelectedImage )
						return i;
				}
				return selectedIndex;
			},
		SelectImage : function( image )
			{
				if( this.SelectedNotLoaded || this.SelectedImage == image )
					return;

				var pv = this;
				var imageElem = jQuery( '<img src="' + image.Path + '" />' );
				jQuery( this.ImageContainer ).children().first().before( imageElem );

				this.SelectedNotLoaded = true;
				imageElem.css( 'display', 'none' );
				imageElem.load( function(){
										// Hide and delete previous image
										if( pv.SelectedImageElem != null )
											jQuery( pv.SelectedImageElem ).fadeOut( 600, function(){ jQuery(this).remove(); } );
										// Show the current image
										CenterImage( this ); 
										jQuery( this ).fadeIn( 600, function(){ 
																				jQuery( pv.TextElem ).stop(true,true);

																				if( pv.ImageOver )
																					jQuery( pv.TextElem ).slideDown(); 

																				pv.Title.html( image.Title );
																				pv.Desc.html( image.Description ); 
																				pv.SelectedNotLoaded = false; 
																				
																				if( pv.OnSelected != null && typeof( pv.OnSelected ) == 'function' )
																					pv.OnSelected( pv, image );
																			});
										pv.SelectedImageElem = this;
									});
				if( this.SelectedImage != null )
				{
					jQuery(this.SelectedImage.Img).stop( true, true );
					jQuery(this.SelectedImage.Img).css( 'opacity', PhotoViewer.ThumbOpacity );
					jQuery(this.SelectedImage.Div).removeClass( 'ThumbHolderHover' );
					
					jQuery( this.TextElem ).stop(true,true);
					jQuery( this.TextElem ).slideUp( 600, function(){ 
																pv.Title.html( "" );
																pv.Desc.html( "" ); 
															});
				}
				
				this.SelectedImage = image;
				jQuery(this.SelectedImage.Img).stop( true, true );
				jQuery(this.SelectedImage.Img).css( 'opacity', 1 );
				jQuery(this.SelectedImage.Div).addClass( 'ThumbHolderHover' );
				
				this.BringIntoView();
			},
		ScrollLeftOver : function()
			{
				jQuery(this.ScrollLeft).addClass( 'ScrollLeftHover' );
				
				var jThumbs = jQuery( this.Thumbs );
				jThumbs.stop( true );
				var thumbsAreaWidth = jQuery( this.ThumbsArea ).width();
				var thumbsWidth = jThumbs.width();
				var thumbsLeft = this.Thumbs.offsetLeft;
				var maxLeft = 0;
				if( thumbsLeft >= maxLeft )
					return;
				
				// calculate duration
				var distance = thumbsLeft*(-1);
				var duration = distance/PhotoViewer.ScrollSpeed*1000;
				
				jThumbs.animate( { 'marginLeft' : maxLeft+'px' }, duration );
			},
		ScrollLeftOut : function()
			{
				jQuery( this.Thumbs ).stop( true );
				jQuery(this.ScrollLeft).removeClass( 'ScrollLeftHover' );
				
			},
		ScrollRightOver : function()
			{
				jQuery(this.ScrollRight).addClass( 'ScrollRightHover' );
				
				var jThumbs = jQuery( this.Thumbs );
				jThumbs.stop( true );
				
				var thumbsAreaWidth = jQuery( this.ThumbsArea ).width();
				var thumbsWidth = jThumbs.width();
				var thumbsLeft = this.Thumbs.offsetLeft;

				var minLeft = (thumbsWidth-thumbsAreaWidth)*(-1);
				if( minLeft >= 0 || thumbsLeft <= minLeft )
					return;
				
				// calculate duration
				var distance = thumbsWidth + thumbsLeft - thumbsAreaWidth;
				var duration = distance/PhotoViewer.ScrollSpeed*1000;
				jThumbs.animate( { 'marginLeft' : minLeft+'px' }, duration );
			},
		ScrollRightOut : function()
			{
				jQuery( this.Thumbs ).stop( true );
				jQuery(this.ScrollRight).removeClass( 'ScrollRightHover' );
				
			},
		BringIntoView : function()
			{
				if( this.SelectedImage == null )
					return;
					
				var jThumbs = jQuery( this.Thumbs );
				var imageWidth = jQuery( this.SelectedImage.Div ).outerWidth(true);
				var imageLeft = this.SelectedImage.Div.offsetLeft;
				var thumbsLeft = this.Thumbs.offsetLeft;
				
				// Image is in left
				if( thumbsLeft*(-1) > imageLeft )
				{
					jThumbs.animate( { 'marginLeft' : ((-1)*(imageLeft-2))+'px' }, 600 );
					return;
				}

				var thumbsAreaWidth = jQuery( this.ThumbsArea ).width();
				if( imageLeft+imageWidth > thumbsAreaWidth-thumbsLeft )
				{
					jThumbs.animate( { 'marginLeft' : ((-1)*(imageLeft+imageWidth-thumbsAreaWidth))+'px' }, 600 );
					return;
				}
			},
		DeleteSelected : function()
			{
				if( this.SelectedImage == null || ( PhotoViewer.DeleteConfirmText && !confirm( PhotoViewer.DeleteConfirmText ) ) )
					return;
				
				var pv = this;
				var imageToDelete = this.SelectedImage;
				if( this.Images.length > 1 )
				{
					var oldOnSelected = this.OnSelected;
					this.OnSelected = function(){
											pv.OnSelected = oldOnSelected;
											
											var newImages = [];
											for( var i=0; i<pv.Images.length; i++ )
											{
												if( pv.Images[i] != imageToDelete )
													newImages.push( pv.Images[i] );
											}
											pv.Images = newImages;
											jQuery( imageToDelete.Div ).remove();
											pv.RefreshThumbsHolder();
											
											if( pv.OnDeleted != null && typeof( pv.OnDeleted ) == 'function' )
												pv.OnDeleted( pv, imageToDelete );
											
											delete imageToDelete;
										 };
					this.SelectPrev();
				}
				else
				{
					if( this.SelectedImageElem != null )
						jQuery( this.SelectedImageElem ).fadeOut( 600, function(){ jQuery(this).remove(); } );

					jQuery( this.TextElem ).slideUp( 600, function(){ 
																pv.Title.html( "" );
																pv.Desc.html( "" ); 
															});
					this.Images = [];
					jQuery( imageToDelete.Div ).remove();
					this.SelectedImageElem = null;
					this.SelectedImage = null;
					this.RefreshThumbsHolder();

					if( this.OnDeleted != null && typeof( this.OnDeleted ) == 'function' )
						this.OnDeleted( this, imageToDelete );

					delete imageToDelete;
				}
			},
		EnableDelete : function()
			{
				PhotoViewer.DeleteEnabled = true;
				this.ShowToolbar();
			},
		ShowToolbar : function() 
			{
				var pv = this;

				if( this.Toolbar == null )
				{
					this.Toolbar = jQuery('<div class="Toolbar"></div>');
					jQuery( this.ImageContainer ).append( this.Toolbar );
				}
				
				if( PhotoViewer.SortingEnabled && this.MoveLeftBtn == null && this.MoveRightBtn == null )
				{
					this.MoveLeftBtn = jQuery('<div class="MoveLeft"></div>');
					jQuery( this.Toolbar ).append( this.MoveLeftBtn );
					this.MoveLeftBtn.html( PhotoViewer.MoveLeftText );
					this.MoveLeftBtn.click( function(){ pv.MoveLeft(); } );
					this.MoveLeftBtn.hover( function(){ jQuery(this).addClass('MoveLeftHover'); }, function(){ jQuery(this).removeClass('MoveLeftHover'); } );

					this.MoveRightBtn = jQuery('<div class="MoveRight"></div>');
					jQuery( this.Toolbar ).append( this.MoveRightBtn );
					this.MoveRightBtn.html( PhotoViewer.MoveRightText );
					this.MoveRightBtn.click( function(){ pv.MoveRight(); } );
					this.MoveRightBtn.hover( function(){ jQuery(this).addClass('MoveRightHover'); }, function(){ jQuery(this).removeClass('MoveRightHover'); } );
				}
				
				if( PhotoViewer.DeleteEnabled && this.DeleteBtn == null )
				{
					this.DeleteBtn = jQuery('<div class="Delete"></div>');
					jQuery( this.Toolbar ).append( this.DeleteBtn );
					this.DeleteBtn.html( PhotoViewer.DeleteText );
					this.DeleteBtn.click( function(){ pv.DeleteSelected(); } );
					this.DeleteBtn.hover( function(){ jQuery(this).addClass('DeleteHover'); }, function(){ jQuery(this).removeClass('DeleteHover'); } );
				}
			},
		HideToolbar : function() 
			{
				this.Toolbar.remove();
				this.Toolbar = null;
				this.DeleteBtn = null;
				this.MoveLeftBtn = null;
				this.MoveRightBtn = null;
			},
			
		// SORTING
		MoveLeft : function()
			{
				if( this.SelectedImage == null )
					return;
				
				var selDiv = jQuery( this.SelectedImage.Div );
				
				if( selDiv.prev().get(0) )
				{
					selDiv.insertBefore( selDiv.prev() );
				
					if( this.OnMoved != null && typeof( this.OnMoved ) == 'function' )
						this.OnMoved( this, this.SelectedImage, "left" );
				}
				
				this.BringIntoView();
			},		
		MoveRight : function()
			{
				if( this.SelectedImage == null )
					return;
				
				var selDiv = jQuery( this.SelectedImage.Div );
				
				if( selDiv.next().get(0) )
				{
					selDiv.insertAfter( selDiv.next() );
				
					if( this.OnMoved != null && typeof( this.OnMoved ) == 'function' )
						this.OnMoved( this, this.SelectedImage, "right" );
				}

				this.BringIntoView();
			},		
	
		SetTitle : function( title )
			{
				if( this.SelectedImage == null )
					return;
				this.SelectedImage.Title = title;
				this.Title.html( title );
			},
		SetDescription : function( desc )
			{
				if( this.SelectedImage == null )
					return;
				this.SelectedImage.Description = desc;
				this.Desc.html( desc );
			}
	}
	
CenterImage = function( image )
	{
		if( image == null )
			return;
		
		var parentElem = jQuery( image ).parent();
		var imageElem = jQuery( image );
		
		var displayedElem = null;
		if( imageElem.height() == 0 )
		{
			displayedElem = parentElem.css( 'display' ) == "none" ? parentElem : null;
			
			if( displayedElem == null && imageElem.css( 'display' ) == "none" )
				displayedElem = imageElem;
			
			if( displayedElem == null )
				return;
				
			displayedElem.css( 'display', 'block' );
		}
		
		// Get sizes
		var imageWidth = imageElem.width()
		var imageHeight = imageElem.height()
		
		var parentWidth = parentElem.width()
		var parentHeight = parentElem.height()
		
		if( displayedElem != null )
			displayedElem.css( 'display', 'none' );

		if( parentWidth != imageWidth )
			imageElem.css( 'marginLeft', Math.round((parentWidth - imageWidth)/2) + 'px' );
		if( parentHeight != imageHeight )
			imageElem.css( 'marginTop', Math.round((parentHeight - imageHeight)/2) + 'px' );
	}
PhotoViewerError = function( error )
	{
		alert( error );
		return null;
	}

// Instances
PhotoViewer.Instances = [];

