var gallery;
$(function() {
	gallery = new Gallery();
	
	// left/right buttons
	$(document).keyup(function(e) {
		if(e.keyCode == 39) {
			gallery.next();
		} else if(e.keyCode ==  37) {
			gallery.prev();
		}
		//$.log(e);
	});
});

function Gallery(options)
{
	options = options || {};

	// establish option defaults
	options = $.extend({
	    mainImage: 'div.featured-image img',
	    mainImageTitle: 'div.featured-image h3',
		nextImage: 'div.featured-image .controls .next a',
		prevImage: 'div.featured-image .controls .prev a',
		tn: 'div.thumbnails',
		tnList: 'div.thumbnails .tn'
	}, options);

	// private variables
	var self = this;
	var _hoverTimer;
	var _imagePos = 0;
	var _tnPos = 0;
	var _tnExpanded = false;

	/**
	 * constructor
	 */
	function _init()
	{
		_imagePos	= _calcCurrentImagePostion();
		//_tnPos		= Math.ceil(_imagePos/5);
		_initMainImageHover();
		_initPrevNext();
		_initGalleryCache();
		_initThumbnailViewer();
		_initLoadRotator();
		
		$(options.mainImage).css('height', 'auto');
		alt = $(options.mainImage).next();
		alt.text('1 of '+_getTotalImages()+' - '+alt.text());
		if(window.location.hash != '' && window.location.hash.indexOf('pic-') > -1) {
			_displayImage(parseInt(window.location.hash.substr(5))-1);
		}
	}
	
	// public methods
	this.next = function()
	{
		this.show(_imagePos + 1);
	}

	this.prev = function()
	{
		this.show(_imagePos - 1);
	}

	this.getPosition = function()
	{
		return _imagePos;
	}

	this.prevThumbs = function()
	{
		var tmp = _tnPos - 5;
		_moveTnListToShowPos(tmp);
	}

	this.nextThumbs = function()
	{
		var tmp = _tnPos+ 5;
		_moveTnListToShowPos(tmp);
	}

	this.toggleExpandThumbs = function()
	{
		if(_tnExpanded) {
			_tnExpanded = false;
			$('div.thumbnails, div.thumbnails .mask').css({
				height: ''
			});

			$(options.tnList).css({
				width: ''
			});

			_tnExpanded = false;

			if(!_isTnVisible(_imagePos)) {
				_moveTnListToShowPos(_imagePos);
			}
		} else {
			var height = Math.ceil(_getTotalImages()/5) * 80;

			$('div.thumbnails, div.thumbnails .mask')
				.animate({
					height: height
				}, {
					duration: 300
				})
			.css({
				height: height
			})

			$(options.tnList).css({
				width: 'auto'
			});

			_tnExpanded = true;
		}

		
	}

	/**
	 * Show the image at the specific position within the list of thumbnails
	 */
	this.show = function(position)
	{
		_displayImage(position)
	}

	// PRIVATE METHODS

	/**
	 * Display a large image by providing the images position in the list of
	 * displayed thumbnails
	 *
	 * @param int position
	 */
	function _displayImage(position)
	{
		var totalImages = _getTotalImages();
		// is the position within scope
		if(position < 0 || position >= totalImages) {
			// unable to load that image
			return;
		}

		//console.log('showing image %d', position);
		window.location.hash = 'pic-'+(position+1);

		// update shown image
		var src = $('li:eq(' + position + ')>a', options.tnList).attr('href');

		$(options.mainImage)
			.attr('src', src)
			.next()
			.text((position+1)+' of '+totalImages+' - '+$('li:eq(' + position + ')>a>img', options.tnList).attr('alt'));
		

		// update selected tn
		$(options.tnList).children()
			.removeClass('current-image')
			.filter(':eq('+position+')')
				.addClass('current-image');

		// update the tn position
		if(!_isTnVisible(position)) {
			_moveTnListToShowPos(position);
		}

		// disable ui
		if(position == 0) {
			_disableUi('prev', true);
			_disableUi('next', false);
		} else if(position == totalImages - 1) {
			_disableUi('prev', false);
			_disableUi('next', true);
		} else {
			_disableUi('prev', false);
			_disableUi('next', false);
		}

		_imagePos = position;
	}

	/**
	 * Determines if the thumbnail at the provided position is visiblie in
	 * the tn selection list
	 *
	 * @return boolean
	 */
	function _isTnVisible(pos)
	{
		return ((pos >= _tnPos && pos <= _tnPos + 4) || _tnExpanded);
	}

	/**
	 * Move the thumbnail list to show the provided position
	 * Since the list is moved in increments of 5, the method figures out which
	 * block the position belongs to and moves to that block
	 */
	function _moveTnListToShowPos(pos)
	{
		var currentBlockPos = Math.floor(_tnPos/5);
		var newBlockPos = Math.floor(pos/5);

		if(currentBlockPos == newBlockPos || pos < 0 || pos > _getTotalImages()) {
			return;
		}
		
		$(options.tnList).animate({
			left: '-'+(newBlockPos * 595)+'px'
		}, {
			duration: 300
		});

		// disable ui
		if(pos <= 4) {
			_disableUi('tnprev', true);
			_disableUi('tnnext', false);
		} else if(pos + 5 >  _getTotalImages() + 1) {
			_disableUi('tnprev', false);
			_disableUi('tnnext', true);
		} else {
			_disableUi('tnprev', false);
			_disableUi('tnnext', false);
		}

		_tnPos = newBlockPos * 5;
	}

	/**
	 * Disables the specific control element
	 *
	 * @param string what
	 * @param boolean disabled
	 */
	function _disableUi(what, disabled)
	{
		var hash = {
			prev: options.prevImage,
			next: options.nextImage,
			tnprev: 'div.thumbnails .controls .prev a',
			tnnext: 'div.thumbnails .controls .next a'
		};

		if(disabled) {
			$(hash[what]).addClass('disabled');
		} else {
			$(hash[what]).removeClass('disabled');
		}
	}

	function _calcCurrentImagePostion()
	{
		return $(options.tnList).children('.current-image').index();
	}

	/**
	 * Get the number of images in this gallery
	 *
	 * @return int
	 */
	function _getTotalImages()
	{
		return $(options.tnList).children().length;
	}

	/**
	 * @todo implement caching solution to help the loading of images
	 */
	function _initGalleryCache()
	{
		
	}

	function _initLoadRotator()
	{
		/*// preload the asset
		img = new Image;
		img.src = '/Layout/Skins/Default/images/loading-64.gif';
		
		$('<img />')
			.css({
				position: 'absolute',
				top: '143px',
				left: '291px'
			})
			.attr('src', img.src)
			.insertBefore(options.mainImage);
		*/
	}
	
	/**
	 * Initialise the thumbnail viewer & controls
	 */
	function _initThumbnailViewer()
	{
		$(options.tnList).wrap('<div class="mask"></div>');

		// inject controls
		//<li class="expand"><a href="#">Expand</a></li>
		$('<ul class="controls"><li class="prev"><a href="#">Previous</a></li><li class="next"><a href="#">Next</a></li></ul>').appendTo(options.tn);

		// handle control functionality
		$('.controls .prev a', options.tn).click(function() {
			if($(this).hasClass('disabled') == false) {
				self.prevThumbs();
			}
			return false;
		})
		$('.controls .next a', options.tn).click(function() {
			if($(this).hasClass('disabled') == false) {
				self.nextThumbs();
			}
			return false;
		});
		$('.controls .expand a', options.tn).click(function() {
			//self.toggleExpandThumbs();
			return false;
		});

		if(_imagePos != 0) {
			_moveTnListToShowPos(_imagePos);
		} else {
			_disableUi('tnprev', true);
		}
		

		$('li>a', options.tnList).click(function() {
			var pos = $(this).parent().index();
			self.show(pos);
			return false;
		})
	}

	/**
	 * Initialises the prev/next image controls
	 */
	function _initPrevNext()
	{
		$(options.nextImage).click(function() {
			if($(this).hasClass('disabled') == false) {
				self.next();
			}
			return false;
		});
		$(options.prevImage).click(function() {
			if($(this).hasClass('disabled') == false) {
				self.prev();
			}
			return false;
		});

		if(_imagePos == 0) {
			_disableUi('prev', true);
		} else if(_imagePos == _getTotalImages() - 1) {
			_disableUi('next', true);
		}
	}

	/**
	 * Initialises hovering over the main image, and hiding the next/prev controls
	 */
	function _initMainImageHover()
	{
		$(options.mainImage)
			.hover(function() {
				if(_hoverTimer > 0) {

					clearTimeout(_hoverTimer);
				}

				$(this).siblings('.controls').show();
			}, function() {
				var self = this;
				_hoverTimer = setTimeout(function() {
					$(self).siblings('.controls').hide();
				}, 50);

			})
			.siblings('.controls')
				//.hide()
				.hover(function() {
					clearTimeout(_hoverTimer);
				}, function() {
					var self = this;
					_hoverTimer = setTimeout(function() {
						$(self).parent().children('.controls').hide();
					}, 50);
				})
			.end();
	}



	// call constructor
	_init();
}
