var mkPhoto = Class.create({
	
	img: null,
	
	width: 0,
	
	height: 0,
	
	ratio: 1,
	
	isReady: false,
	
	src: '',
	
	originalImg: null,
	
	onClickCallback: null,
	
	onClickCallback: null,
	
	id: 0,

	initialize: function( id, src, thumbImg, onLoadCallback, onClickCallback )
	{
		this.id       = id;
		this.src      = src;
		
		if (onLoadCallback)
			this.onLoadCallback = onLoadCallback;
		if (onClickCallback)
			this.onClickCallback = onClickCallback;
		
		// Create a copy of the thumbnail
		this.thumbImg = $(document.createElement('img'));
		this.thumbImg.src = thumbImg.src;
	},
	
	load: function( )
	{
		if (this.isReady)
		{
			this.fireReady();
			return;
		}
		
		if (this.img == null)
		{
			// Create image and begin loading
			this.img = $(document.createElement('img'));
			this.img.observe( 'load', this.onLoad.bind(this) );

			if (this.onClickCallback)
			{
				this.img.observe( 'click', this.fireClick.bind(this) );
				this.img.setStyle({cursor: 'pointer'});
			}
			
			// begin loading
			this.img.src = this.src;
		}
	},
	
	onLoad: function()
	{
		// Size accordingly
		this.width  = this.img.width;
		this.height = this.img.height;
		if (this.height != 0)
		{
			this.ratio = this.width / this.height;
		}
		
		this.fireReady();
	},
	
	fireClick: function()
	{
		if (this.onClickCallback)
		{
			this.onClickCallback( this );
		}
	},

	fireReady: function()
	{
		this.isReady = true;
		
		if (this.onLoadCallback)
		{
			this.onLoadCallback( this );
		}
	}
	
});

var mkPhotoViewer = Class.create({

	cache: [],
	
	photos: [],
	
	photo: null,	// current photo
	
	overlay: null,
	
	currentImage: null,
	
	image: null,
	
	emptyImage: null,
	
	isOpen: false,
	
	uidCounter: 0,
	
	addPhoto: function( img, largeUrl, onClickCallback )
	{
		var photo = new mkPhoto( this.uidCounter, largeUrl, $(img), this.onPhotoReady.bind(this), onClickCallback );
		this.photos.push( photo );
		
		// Preload the big image
		setTimeout( function(){ photo.load();}, this.uidCounter * 250 );
		
		++this.uidCounter;
		
		return photo;
	},

	initialize: function( )
	{
		var that = this;
		
		$$('a').each( function(a, i)
		{
			a = $(a);
			if (a.rel == 'lightbox')
			{
				var img = a.firstChild;
				var photo = that.addPhoto( img, a.href );
				a.observe('click', function(event) {
					that.showPhoto.call( that, photo );
					event.stop();
				});
				
				// Go ahead and preload, but stagger so
				// the browser doesn't grind to a halt
				setTimeout( function(){
					//var preloadImg = document.createElement('img');
					photo.load();
					//preloadImg.src = a.href;
					//that.cache.push( preloadImg );
				}, 250 * i);
			}
		});
		
		// Create the background element (overlay)
		this.overlay = $(document.createElement('div'));
		this.overlay.setStyle({
			background: '#000000',
			position: 'absolute',
			opacity: .9,
			left: '0px',
			top: '0px'
		});
		this.overlay.hide();
		
		// Close on clicking the overlay
		this.overlay.observe( 'click', this.end.bind(this) );
		
		// All browsers support keyup on the document, but IE fails for 'window'
		// Also, use keyup instead of keypress as IE doesn't detect "special characters" on keypress
		Event.observe( document, 'keyup', this.onKeyUp.bindAsEventListener(this) );
		Event.observe( window,   'resize', this.onResize.bind(this) );
		
		// Container for the photo viewer
		this.photoViewer = $(document.createElement('div'));
		this.photoViewer.setStyle({position: 'absolute', left:0, top:0});
		
		// The image container
		this.imageContainer = $(document.createElement('div'));
		this.imageContainer.setStyle({position: 'absolute', border: '1px solid black' });
		this.imageContainer.hide();
		
		// The image
		this.image = this.emptyImage = $(document.createElement('img'));
		this.loadingImage = $(document.createElement('img'));
		this.loadingImage.setStyle({
			position: 'absolute',
			opacity: .9
		});
		this.loadingImage.hide();
		this.loadingImage.src = 'http://hellomister.com/images/ajax-loader-bar2.gif';
		
		// Create a white overlay for the image
		this.whiteOverlay = $(document.createElement('div'));
		this.whiteOverlay.setStyle({
			opacity: 0,
			width: '100%',
			height: '100%',
			position: 'absolute',
			left: '0px',
			top: '0px',
			background: '#ffffff'
		});
		this.whiteOverlay.hide();

		this.imageContainer.appendChild( this.emptyImage );
		this.imageContainer.appendChild( this.whiteOverlay );
		this.imageContainer.appendChild( this.loadingImage );
						
		this.photoViewer.appendChild( this.imageContainer );
		this.photoViewer.hide();
	},
	
	onResize: function()
	{
		if (this.isOpen)
		{
			this.updatePageSize();
		}
	},
	
	updatePageSize: function()
	{
		this.pageSize = this.getPageSize();
		
		// Maximize background maximum size
		//this.pageSize = this.getPageSize();
		this.overlay.setStyle({
			width:  this.pageSize.pageWidth  + 'px',
			height: this.pageSize.pageHeight + 'px'
		});
		
		// Place photoViewer
        var pageScroll = document.viewport.getScrollOffsets();
        var top  = pageScroll[1];// + (document.viewport.getHeight() / 10);
        var left = pageScroll[0];
        this.photoViewer.setStyle({
        	left: left + 'px',
        	top: top + 'px'
        });
        
        this.setSize( this.image );

	},
	
	onKeyUp: function( event )
	{
		switch (event.keyCode)
		{
			case Event.KEY_ESC:
				this.end();
				break;
			case Event.KEY_LEFT:	// left
				this.moveToPhoto( this.photo.id - 1 );
				break;
			case Event.KEY_RIGHT:	// right
				this.moveToPhoto( this.photo.id + 1 );
				break;
		}
	},
	
	toString: function()
	{
		return 'mkPhotoViewer';
	},
	
	end: function()
	{
		// Hide everything
		this.photoViewer.hide();
		//new Effect.Fade( this.overlay, {duration: .3} );
		this.overlay.hide();
		
		this.isOpen = false;		
	},
	
	start: function()
	{
		// Attach to body if not already
		// Assume this only happens once
		if (this.overlay.parentNode == null)
		{
			var body = $$('body')[0];
			body.appendChild( this.overlay );
			body.appendChild( this.photoViewer );
		}
        
		// Fade in the background
		var that = this;
		//new Effect.Appear( this.overlay, {duration: .3, from: 0, to: .7, afterFinish:
		this.overlay.show();
			//function()
			{
				// FF doesn't like to fade scaled images
				//new Effect.Appear( that.photoViewer, {duration: 1, from: 0} );
				that.photoViewer.show();
			}
		//});
	},
	
	computeSize: function( img, maxWidth, maxHeight )
	{
		if (img.height == 0)
		{
			return {
				width:  newWidth,
				height: newHeight
			};
		}
		
		var ratio = img.width / img.height;
		var newWidth  = maxWidth;
		var newHeight = Math.min( maxHeight, newWidth / ratio );
		newWidth = newHeight * ratio;
		
		return {
			width:  Math.floor( newWidth ),
			height: Math.floor( newHeight )
		}
	},
	
	setLoadingState: function( state )
	{
		if (state)
		{
			// Show loading image
			this.loadingImage.setStyle({
				left: (parseInt(this.imageContainer.getStyle('width'))  - this.loadingImage.width)  * .5 + 'px',
				top:  (parseInt(this.imageContainer.getStyle('height')) - this.loadingImage.height) * .5 + 'px'
			})

			this.loadingImage.show();
			this.whiteOverlay.setOpacity( .3 );
			this.whiteOverlay.show();
		}
		else
		{
			this.imageContainer.setOpacity( 1 );
			new Effect.Fade( this.whiteOverlay, {duration: .3} );
			this.loadingImage.hide();
		}
	},
	
	setSize: function( img )
	{
		// Compute desired size
		var width  = this.pageSize.windowWidth  - 32;
		var height = this.pageSize.windowHeight - 32;
		var size   = this.computeSize( img, width, height );

		if (size)
		{
			img.width  = size.width;
			img.height = size.height;
			
			// Center the image container
			this.imageContainer.setStyle({
				width:  size.width  + 'px',
				height: size.height + 'px',
				left:   (this.pageSize.windowWidth  - size.width)  * 0.5 + 'px',
				top:    (this.pageSize.windowHeight - size.height) * 0.5 + 'px'
			});
		}
	},
	
	moveToPhoto: function( idx )
	{
		// Check bounds
		if (idx >= this.photos.length || idx < 0)
			return;
			
		this.imageContainer.hide();

		
		// Switch to that photo
		this.setPhoto( this.photos[idx] );
	},
	
	showPhoto: function( photo )
	{
		this.isOpen = true;
		
		// Get the page size
		this.updatePageSize();
		
		// Change photos
		this.setPhoto( photo );
		
		// Initialize, show containers, etc
		this.start();
	},
	
	// Replace current image node with img
	replaceImage: function( img )
	{
		// Set the image's size (max of window)
		this.setSize( img );
		
		// Replace the DOM element
		if (this.image)
		{
			this.imageContainer.replaceChild( img, this.image );
		}
		else
		{
			//this.imageContainer.appendChild( img );
			alert('this.image is null');
		}
		
		this.image = img;
	},
	
	setPhoto: function( photo )
	{
		// Set current photo
		this.photo = photo;
		
		// Set the image size
		if (!photo.isReady)
		{
			// Set the 'small' image
			this.replaceImage( photo.thumbImg );
			
			// Only do this if the images are significantly different
			//if (photo.thumbImg.width < 500 && photo.thumbImg.height < 500)
			{
				this.setLoadingState(true);
			}
			this.imageContainer.show();
		}
		else
		{
			this.setLoadingState(false);
		}
		
		// Begin loading the 'photo'
		this.photo.load();
	},
		
	onPhotoReady: function( photo )
	{
		if (photo != this.photo)
			return;
					
		// Set to larger version
		this.imageContainer.hide();
		this.replaceImage( photo.img );
		this.imageContainer.show();
		
		// Turn off the loading image
		this.setLoadingState( false );
	},
	
	// -- From lightbox:	
	//
	// getPageSize()
	// Returns array with page width, height and window width, height
	// Core code from - quirksmode.com
	// Edit for Firefox by pHaez
	//
	getPageSize: 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;
			}
			//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
		if(yScroll < windowHeight)
		{
			pageHeight = windowHeight;
		}
		else
		{ 
			pageHeight = yScroll;
		}
	
		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth)
		{
			pageWidth = xScroll;		
		}
		else
		{
			pageWidth = windowWidth;
		}
	
		return {
			pageWidth:    pageWidth,
			pageHeight:   pageHeight,
			windowWidth:  windowWidth,
			windowHeight: windowHeight
		}
	}
});

var g_photoViewer = null;

Event.observe( window, 'load', function(){ g_photoViewer = new mkPhotoViewer(); } );
