//
//  Configuration
//
modalPhotoOptions = Object.extend({
    fileLoadingImage: '/images/image-loader.gif',     
    fileCloseX: 	  '/images/closex.png',

    overlayOpacity: 0.8,   // controls transparency of shadow overlay
    resizeSpeed: 7,        // controls the speed of the image resizing animations (1=slowest and 10=fastest)
    preloadImages: true,

	// When grouping images this is used to write: Image # of #.
	// Change it for non-english localization
	labelImage: "Image",
	labelOf: "of"
}, window.modalPhotoOptions || {});

function dbalert( msg )
{
    if (1)
    {
        alert(msg);
    }
}

//
//	Additional methods for Element added by SU, Couloir
//	- further additions by Lokesh Dhakar (huddletogether.com)
//
Object.extend(Element, {
	getWidth: function(element) {
	   	element = $(element);
	   	return element.offsetWidth; 
	},
	setWidth: function(element,w) {
	   	element = $(element);
    	element.style.width = w +"px";
	},
	setHeight: function(element,h) {
   		element = $(element);
    	element.style.height = h +"px";
	},
	setTop: function(element,t) {
	   	element = $(element);
    	element.style.top = t +"px";
	},
	setLeft: function(element,l) {
	   	element = $(element);
    	element.style.left = l +"px";
	},
	setSrc: function(element,src) {
    	element = $(element);
    	element.src = src; 
	},
	setHref: function(element,href) {
    	element = $(element);
    	element.href = href; 
	},
	setInnerHTML: function(element,content) {
		element = $(element);
		element.innerHTML = content;
	}
});


// -----------------------------------------------------------------------------------
var modalPhoto = Class.create();

modalPhoto.prototype = {

	parentSet:  undefined,
	domElement: undefined,
	width:      0,
	height:     0,
	isLoaded:   false,
	hasError:   false,
	src:        '',
	options:    undefined,
    imageToShow: undefined,
    
    // Constructor
    initialize: function( domElement, imageToShow, parentSet, options ) {
    
        this.imageToShow = $(new Image());
        
    	this.options = Object.extend({
    	
    		caption: '',
    		title:   ''
    	
    	}, options || {} );
    
    	// Scoping trick to maintain access to 'this'
    	var that = this;
    	
    	this.parentSet = parentSet;
    
    	// Make dom element clickable
    	this.domElement = $(domElement);
    	this.domElement.observe( 'click', function(e)
    	{
    		that.parentSet.show( that, e );
    	});
    	
    	// Load in the image to show
    	// Define onload and onerror events
    	this.imageToShow.setStyle( { opacity: 0 } );
    	
    	this.imageToShow.observe( 'error', function()
    	{
    		alert( 'Image ' + that.imageToShow.src + ' failed to load.' );
    		that.hasError = true;
    		that.width    = 500;
    		that.height   = 500;
    	});
    	
    	this.imageToShow.onload = function(e)//observe( 'load', function()
    	{
    		that.isLoaded = true;
    		that.width    = this.width;
    		that.height   = this.height;
		};
		
		// Load the image
		this.src = imageToShow;
		
		if (modalPhotoOptions.preloadImages)
		{
			this.imageToShow.src = imageToShow;
		}
        
    }
    
}

var modalPhotoSet = Class.create();

modalPhotoSet.prototype = {

	modalPhotos: [],
	left:        0,
	top:         0,
	startLeft:   0,
	startTop:    0,
	isActive:    false,
	isOpen:      false,
	curPhoto:    undefined,
	outerDiv:    $(document.createElement( 'div' )),
	loadingImg:  $(new Image()),
	closeImg:    $(new Image()),
	photoImg:    $(new Image()),
	overlay:     $(document.createElement( 'div' )),
	leftArrow:   $(new Image()),
	rightArrow:  $(new Image()),
	leftDiv:     $(document.createElement( 'div' )),
	rightDiv:    $(document.createElement( 'div' )),
	captionDiv:  $(document.createElement( 'div' )),
	photoIdx:    -1,

	initialize: function() {

		var that = this;
		
		this.outerDiv.setStyle({
			opacity:    0,
			display:    'none',
			position:   'absolute',
			border:     '1px solid black',
			background: '#ffffff'
		});

		this.loadingImg.setStyle({
			opacity:  0,
			position: 'absolute',
			display:  'none'
		});
		this.loadingImg.src = modalPhotoOptions.fileLoadingImage;
    
		this.closeImg.setStyle({
			opacity:  0,
			position: 'absolute',
			display:  'none',
			right:    '-15px',
			top:      '-15px'
		});
		this.closeImg.src = modalPhotoOptions.fileCloseX;
        
		this.closeImg.observe( 'click', function(e)
		{
			that.hide();
		});
        
		this.photoImg.setStyle({
			width: '100%',
			height: '100%',
			border: 0
		});

		this.overlay.setStyle({
			display: 'none',
			opacity: 0,
			background: 'black',
			position: 'absolute',
			left: '0px',
			top: '0px'
		});
		this.overlay.observe( 'click', function(e)
		{
			that.hide();
		});
        
		var body = $(document.getElementsByTagName('body')[0]);
		body.appendChild( this.overlay );
		body.appendChild( this.outerDiv );
		body.appendChild( this.loadingImg );
		this.outerDiv.appendChild( this.photoImg );
        
		this.leftDiv.setStyle({
			width: '40%',
			height: '100%',
			position: 'absolute',
			left: '0px',
			top: '0px',
            background: '#000',
            opacity: 0,
			cursor: 'pointer'
		});

		this.leftDiv.observe( 'mouseover', function(e) { that.mouseOver ( -1 ) });
		this.leftDiv.observe( 'mouseout', function(e)  { that.mouseOut  ( -1 ) });
		this.leftDiv.observe( 'click', function(e)  { that.mouseClick( -1 ) });

		this.rightDiv.setStyle({
			width: '40%',
			height: '100%',
			position: 'absolute',
			right: '0px',
			top: '0px',
            background: '#000',
            opacity: 0,
			cursor: 'pointer'
		});
		this.rightDiv.observe( 'mouseover', function(e) { that.mouseOver ( 1 ) });
		this.rightDiv.observe( 'mouseout', function(e)  { that.mouseOut  ( 1 ) });
		this.rightDiv.observe( 'click', function(e)  { that.mouseClick( 1 ) });
		
		this.leftArrow.setStyle({
			opacity: 0,
			position: 'absolute',
			left: '5px',
			bottom: '5px'
		});
		this.leftArrow.src = '/images/leftArrow.gif';

		this.rightArrow.setStyle({
			opacity: 0,
			position: 'absolute',
			right: '5px',
			bottom: '5px'
		});
		this.rightArrow.src = '/images/rightArrow.gif';


		this.captionDiv.setStyle({
			opacity: .2,
			background: '#000000',
			color: '#ffffff',
			position: 'absolute',
			width: '100%',
			lineHeight: '1.8em',
			textAlign: 'center',
			fontFamily: 'Arial',
			fontSize: '8pt',
			left: '0px',
			bottom: '0px'
		});
		
		
		this.outerDiv.appendChild( this.captionDiv );
		this.outerDiv.appendChild( this.leftArrow );
		this.outerDiv.appendChild( this.rightArrow );
		this.outerDiv.appendChild( this.leftDiv );
		this.outerDiv.appendChild( this.rightDiv );
		this.outerDiv.appendChild( this.closeImg );
		
		// ESC key closes
		Event.observe( window, 'keyup', function(e)
		{
			if ( that.isOpen && !that.isActive && e.which == 27 )
			{
				that.hide();
			}
		});
		
		// Move the box on window resize
		Event.observe( window, 'resize', function()
		{
			if ( that.isOpen && !that.isActive )
			{
				that.isActive = true;
				var placement = that.getDivPlacement( that.left, that.top, that.curPhoto.width, that.curPhoto.height );
				new Effect.Move( that.outerDiv, { x: placement.x, y: placement.y,
					afterFinish: function()
					{
						that.isActive = false;
					}
				});
			}
		});
		
	},
	
	mouseOver: function( whichSide )
	{
//		if ( this.isActive || !this.isOpen )
//		{
//			return;
//		}
		if ( whichSide < 0 )
		{
			if ( this.photoIdx > 0 )
			{
				appear( this.leftArrow,  { to: 0.8, duration: 0.3 } );
			}
		}
		else
		{
			if ( this.photoIdx < this.modalPhotos.length - 1 )
			{
				appear( this.rightArrow, { to: 0.8, duration: 0.3 } );
			}
		}
	},
	
	mouseOut: function( whichSide )
	{	
//		if ( this.isActive || !this.isOpen )
//		{
//			return;
//		}

		if ( whichSide < 0 )
		{
			disappear( this.leftArrow );
		}
		else
		{
			disappear( this.rightArrow );
		}
	},
	
	mouseClick: function( whichSide )
	{
		if ( this.isActive || !this.isOpen )
		{
			return;
		}

		if ( whichSide < 0 )
		{
			if ( this.photoIdx > 0 )
			{
				this.show( this.modalPhotos[this.photoIdx-1] );
			}
		}
		else
		{
			if ( this.photoIdx < this.modalPhotos.length - 1 )
			{
				this.show( this.modalPhotos[this.photoIdx+1] );
			}
		}
	
	},
	
	findPhoto: function( photo )
	{
		// find the photo
		for( var i = 0; i < this.modalPhotos.length; ++i )
		{
			if ( this.modalPhotos[i] == photo )
			{
				return i;
			}
		}
	
		return -1;
	},
	
	windowSize: function() {
	
	     var xScroll, yScroll;
		
		if (window.innerHeight && window.scrollMaxY) {	
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		
		var windowWidth, windowHeight;
		
		if (self.innerHeight) {	// all except Explorer
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth; 
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	
		
		// for small pages with total height less then height of the viewport
		pageHeight = Math.max( yScroll, windowHeight );
	
		// for small pages with total width less then width of the viewport
		pageWidth = Math.max( xScroll, windowWidth );
	
 	 	// returns correct dimensions for window, had issues with prototype's sometimes. this was ganked from apple.
		var viewWidth  = window.innerWidth  || (window.document.documentElement.clientWidth  || window.document.body.clientWidth);
		var viewHeight = window.innerHeight || (window.document.documentElement.clientHeight || window.document.body.clientHeight);
		var x          = window.pageXOffset || (window.document.documentElement.scrollLeft   || window.document.body.scrollLeft);
		var y          = window.pageYOffset || (window.document.documentElement.scrollTop    || window.document.body.scrollTop);
		
		return {
				 'viewWidth':  viewWidth,
				 'viewHeight': viewHeight,
				 'pageWidth':  pageWidth,
				 'pageHeight': pageHeight,
				 'x':      x,
				 'y':      y
			   }
		
	},
	
	getDivPlacement: function( startX, startY, width, height ) {
	
		// where to plac the div?
		
		// Get some info first
		var dims               = this.windowSize();
		var yOffset            = document.viewport.getScrollOffsets()[1];
		var xOffset            = document.viewport.getScrollOffsets()[0];
		
		// ensure that newTop is at least 0 so it doesn't hide close button
		this.top             = Math.max( (dims.viewHeight - height) * 0.5 + yOffset, 0 );
		this.left            = Math.max( (dims.viewWidth  - width ) * 0.5 + xOffset, 0 );
		
		return {
				 'x': -(startX - this.left),
				 'y': -(startY - this.top)
			   }
	
	},
	
	setCursorIfDifferent: function( element, cursorType )
	{
        return;
		if ( element.getStyle('cursor') != cursorType )
		{
			element.setStyle( { cursor: cursorType } );
		}
	},
	
	prepCaption: function( photo )
	{
		if (photo.options.caption.length > 0)
		{
			this.captionDiv.innerHTML = photo.options.caption;
		}	
	},
	
	showCaption: function()
	{
		if (this.curPhoto.options.caption.length > 0)
		{
			this.captionDiv.innerHTML = this.curPhoto.options.caption;
			appear( this.captionDiv, { duration: 0.2, to: 0.8 } );
		}
		else
		{
			disappear( this.captionDiv, { duration: 0.2 } );
		}
	},

	show: function( photo, e ) {
	
		// Begin loading image if haven't already
		photo.imageToShow.src = photo.src;
		
		// Do nothing if currently moving
		if ( this.isActive )
		{
			return;
		}
	
		this.photoIdx = this.findPhoto( photo );
		var that = this;
		
		if ( this.photoIdx == -1 )
		{
			alert('Photo not found in set!');
			return;
		}
		
		// Enable or disable mouse cursor -> pointer
		if ( this.photoIdx == 0 )
		{
			disappear( this.leftArrow );
			this.setCursorIfDifferent( this.leftDiv, 'default' );
		}
		else
		{
			this.setCursorIfDifferent( this.leftDiv, 'pointer' );
		}
		
		if ( this.photoIdx == this.modalPhotos.length - 1 )
		{
			disappear( this.rightArrow );
			this.setCursorIfDifferent( this.rightDiv, 'default' );
		}
		else
		{
			this.setCursorIfDifferent( this.rightDiv, 'pointer' );
		}
	
		if ( photo.isLoaded || photo.hasError )
		{
			this.isActive = true;
			
			// Hide loader
			if ( this.loadingImg.getStyle('opacity') > 0 )
			{
				disappear( this.loadingImg, { duration: 0.2 } );
			}
            
            // Hide the left &right divs (for IE)
            this.leftDiv.hide();
            this.rightDiv.hide();
            
            
			if ( this.isOpen )
			{				
				// swap photos
				new Effect.Parallel([
				
					new Effect.Fade( that.photoImg, { sync: true } ),
					new Effect.Fade( that.captionDiv, { sync: true } )
				], {
					duration: 0.2,
					afterFinish: function(effect) {
						// resize box
						var placement = that.getDivPlacement( that.left, that.top, photo.width, photo.height );
						new Effect.Parallel([
							new Effect.Move(  that.outerDiv, { x: placement.x, y: placement.y, sync: true } ),
							new Effect.Morph( that.outerDiv, { style: { width: photo.width + 'px', height: photo.height + 'px' }, sync: true } )
						], {
							duration: 0.2,
							afterFinish: function(effect)
							{								
								// swap in new image
								that.photoImg.setStyle( {opacity:0, display:'block'} );
								that.photoImg.src = photo.imageToShow.src;
								that.prepCaption( photo );
								
								// fade it in
								new Effect.Parallel([
									new Effect.Appear( that.photoImg, { sync: true } ),
									new Effect.Appear( that.captionDiv, { to: 0.8, sync: true } )
								], {
									duration: 0.2,
									afterFinish:function(effect)
									{
										that.isActive = false;
										that.curPhoto = photo;
                                        that.leftDiv.show();
                                        that.rightDiv.show();
									}
								});
							}
						});
					}}
				);
			}
			else
			{
				// No box open?  Open a box
				if (e)
				{
					this.startLeft = e.pointerX() - 16;
					this.startTop  = e.pointerY() - 16;
				}
				
				var dims = this.windowSize();
				this.overlay.setStyle( {width: (dims.pageWidth-15) + 'px', height: dims.pageHeight + 'px' } );
				
				var placement = that.getDivPlacement( this.startLeft, this.startTop, photo.width, photo.height );
                
				var startingHeight = (32 * photo.height / photo.width);
                
				this.outerDiv.setStyle( {
					display:'block',
					opacity: 0,
					width: '32px',
					height: startingHeight + 'px',
					left: this.startLeft + 'px',
					top:  this.startTop + 'px'
				});
				
				photo.imageToShow.setStyle({
					width: '100%',
					height: '100%'
				});

				new Effect.Parallel([
					new Effect.Appear( that.overlay, { to: modalPhotoOptions.overlayOpacity, sync: true } ),
					new Effect.Appear( that.outerDiv, { from:.5, sync: true } ),
					new Effect.Move( that.outerDiv, { x: placement.x, y: placement.y, sync: true } ),
/*					new Effect.Morph( photo.imageToShow, { style: { width: photo.width + 'px', height: photo.height + 'px' }, sync: true } ),*/
					new Effect.Morph( that.outerDiv, {
						style: { width: photo.width + 'px', height: photo.height + 'px' },
						sync: true,
						beforeStart: function() {
							// insert photo
							that.outerDiv.setStyle({display:'block'});
							that.photoImg.setStyle({ opacity: 1 });
							that.captionDiv.setStyle({ opacity: 0 });
							that.photoImg.src = photo.imageToShow.src;
						},
						afterFinish: function(effect) {
							appear( that.closeImg, { duration: 0.2 } );
							that.isActive = false;
							that.curPhoto = photo;
							that.showCaption();
                            that.leftDiv.show();
                            that.rightDiv.show();
                            
						}
					})
				], { duration: 0.5 } );
			}
			
			this.isOpen = true;
		}
		else
		{
			if ( !photo.hasError )
			{
				// show loading dealy
				var dims = this.windowSize();
				
				// show loader
				var yOffset  = document.viewport.getScrollOffsets()[1];
				var xOffset  = document.viewport.getScrollOffsets()[0];
		
				// ensure that newTop is at least 0 so it doesn't hide close button
				var top  = Math.max( (dims.viewHeight - this.loadingImg.height) * 0.5 + yOffset, 0 );
				var left = Math.max( (dims.viewWidth - this.loadingImg.width) * 0.5 + xOffset, 0 );
				
				this.loadingImg.setStyle( { left: left + 'px', top: top + 'px' } );
				
				// Is it already fading in?
				if (findEffect( this.loadingImg, 'opacity' ) == null)
				{
					appear( this.loadingImg, { duration: 0.2, to: 0.7 } );
				}
				
				// install timer to check for image finished loading
				setTimeout( function()
					{
						that.show( photo, e );
					},
					
					500
				);
			}
		}
	},
	
	hide: function()
	{
		if( this.isActive )
		{
			return;
		}
		
		this.isActive = true;
		var that = this;
		
		//alert( this.left + ' ' + this.startLeft );
        
        this.leftDiv.hide();
        this.rightDiv.hide();
		
		new Effect.Parallel([
			new Effect.Fade( this.overlay, {sync:true} ),
			new Effect.Fade( this.outerDiv, {sync:true} ),
			new Effect.Morph( this.outerDiv, {style:{ width: '32px', height: (32 * this.curPhoto.height / this.curPhoto.width) + 'px' }, sync: true } ),
			new Effect.Move( this.outerDiv, { x: (this.startLeft - this.left), y: (this.startTop - this.top) } )
		], {
			duration: 0.5,
			afterFinish: function()
			{
				that.isActive = false;
				that.isOpen   = false;
				that.photoImg.src = '';
				that.closeImg.setStyle({opacity:0});
			}
		});
		
		/*
		// Fade image
		new Effect.Fade( this.curPhoto.imageToShow, {
			duration: 0.2,
			afterFinish: function()
			{
				// Collapse the box
				var newx = that.curPhoto.width / 2;
				var newy = that.curPhoto.height / 2;
				
				new Effect.Parallel([
					new Effect.Fade( that.outerDiv, { sync: true } ),
					new Effect.Move( that.outerDiv, { x: newx, y: newy, sync: true } ),
					new Effect.Morph( that.outerDiv, { style: { width: '0px', height: '0px' }, sync: true } )
				], {
					duration: 0.5,
					afterFinish: function()
					{
						that.isActive = false;
						that.isOpen   = false;
					}
				})
			}
		});
		*/
	},
	
	link: function( domElement, imageToShow, options ) {
		
		this.modalPhotos.push( new modalPhoto( domElement, imageToShow, this, options ) );
		
	}
}