﻿/// <reference path='~/jQuery/jQuery-vsdoc.js' />

function ImageSet(setName, folder, images, fontSize, totalWidth, numWidth, totalName)
{
	this.setName = setName
	this.folder = folder
	this.images = images				// The set of images {name:"",width:w,height:h} with .ext of the fullsize image
	this.fontSize = fontSize
	this.totalWidth = totalWidth
	this.numWidth = numWidth
	this.totalName = totalName
	this.imageIndex = 0
}

ImageSet.prototype = {
	GetImageId: function(idx) { return this.setName + idx },
	GetThumbId: function(idx) { return this.setName + idx + 't' },
	ImageInDom: function(idx) { return $('#' + this.GetImageId(idx)) },
	ThumbInDom: function(idx) { return $('#' + this.GetThumbId(idx)) },

	OnLoad: function()
	{
		ImageSet.prev = $('.prev')
		ImageSet.stop = $('.stop')
		ImageSet.next = $('.next')
		ImageSet.topCtrlsFrontPages = _mp.Frame.height - _mp.Footer.height - _mp.PrevNextNumOverlap
		ImageSet.topCtrlsThumbPages = _mp.Frame.height - ImageSet.prev.height()
	},

	LoadInitImages: function()
	{
		if (this.images.length != 0)
		{
			// Preload the numbers
			for (var idx in this.images)
				this.LoadNumber(idx)

			// Preload the 1st image
			this.LoadImage(0)

			// Load the '/total' image
			img = new Image()
			img.src = this.totalName
			_mp.Frame.Div.append(this.totalName = $(img))
		}
	},

	// Load an image if it's not already loaded. Returns $img
	LoadImage: function(idx)
	{
		var imageInfo = this.images[idx]
		var id = this.GetImageId(idx)
		var $img = $('#' + id)
		if ($img.length != 0)
			return $img
		var img = new Image();
		img.id = id
		img.src = 'Photo/' + this.folder + '/' + imageInfo.name
		_mp.Images.Div.append(img)
		img.ownerObj = this
		img.originalWidth = imageInfo.width
		img.originalHeight = imageInfo.height
		img.aspectRatio = imageInfo.width / imageInfo.height
		return $(img).addClass('photo')
	},

	// Load an image name if it's not already loaded. Returns $img
	LoadImageName: function(idx)
	{
		var imageInfo = this.images[idx]
		var $img = $('#' + imageInfo.name)
		if ($img.length != 0)
			return $img
		var img = new Image();
		img.id = imageInfo.name
		img.src = imageInfo.textImg
		_mp.Frame.Div.append(img)
		return $(img).css({ top: ImageSet.topCtrls + 'px',
												left: this.leftNum - 110 - imageInfo.textLen + 'px'
											})
								 .show()
	},

	Init: function(ownerObj)
	{
		_mp.Images.Div.unbind('click')
									.click(function(event) { event.target.ownerObj.DrawNext(event.pageX < _mp.Images.centre ? -1 : 1) })
		_mp.Images.Div[0].ownerObj = this

		ImageSet.prev.unbind()
								 .bind('click', function(event) { ownerObj.DrawNext(-1) })
		ImageSet.next.unbind()
								 .bind('click', function(event) { ownerObj.DrawNext(1) })
		$('.prev.top, .next.top').bind('mouseover', _mp.FadeIn)
														 .bind('mouseout', _mp.FadeOut)
	},

	HidePage: function()
	{
		this.HideFullImage()
	},

	DrawImage: function()
	{
		this.Position(ImageSet.topCtrlsFrontPages)
		ImageSet.next.show()
		ImageSet.prev.show()
		if (this.currentPhoto)
			this.currentPhoto.stop().fadeOut('slow')
		if (this.currentNumber)
			this.currentNumber.hide()
		this.currentNumber = this.ShowNumber(this.imageIndex)
		this.totalName.show()
		this.currentPhoto = this.LoadImage(this.imageIndex)
		this.currentPhoto.fitToSize(_mp.Images.width, _mp.Images.height, { justify: 'left' })
										 .stop()
		var $this = this
		_mp.Images.Div.show()
		this.currentPhoto.animate({ opacity: 'show' }, { duration: 500, complete: function() { $this.PreLoadAdjacentImages($this.imageIndex) } })
	},

	Position: function(top)
	{
		ImageSet.topCtrls = top
		ImageSet.prev.add(ImageSet.next)
								 .css({ top: ImageSet.topCtrls - 2 + 'px' })
		ImageSet.stop.css({ top: ImageSet.topCtrls + 'px' })

		var rightMarginInImage = 3
		this.leftNum = _mp.Frame.width - _mp.Frame.padding - this.totalWidth + rightMarginInImage
		this.totalName.css({ top: ImageSet.topCtrls + 'px', left: this.leftNum + 'px' })
		this.leftNum -= this.numWidth - rightMarginInImage + 1
		ImageSet.next.css({ left: this.leftNum - 30 + 'px' })
		ImageSet.prev.css({ left: this.leftNum - 60 + 'px' })
		_mp.Images.Div.css({ left: _mp.Images.left + 'px', width: _mp.Images.width })
	},

	// Load, position and show the number. NOTE number == idx + 1
	GetNumberId: function(idx)
	{
		return "pnid" + ++idx + this.fontSize;
	},

	// Load, the number if it's not already loaded. NOTE number == idx + 1
	LoadNumber: function(idx)
	{
		var id = this.GetNumberId(idx);
		if ($('#' + id).length == 0)
		{
			// Load this number into the DOM
			var sizeExt = this.fontSize + ".png"
			var img = new Image()
			img.src = "cache/pn " + ++idx + " " + sizeExt
			img.id = id
			_mp.Frame.Div.append(img)
		}
	},

	// Show the number. NOTE number == idx + 1
	ShowNumber: function(idx)
	{
		var id = this.GetNumberId(idx);
		return $('#' + id).css({ top: ImageSet.topCtrls + 'px',
														 left: this.leftNum + 'px'
													})
											.show()
	},

	// Move to the previous/next photo
	DrawNext: function(inc)
	{
		this.imageIndex += inc;
		if (this.imageIndex < 0)
			this.imageIndex = this.images.length - 1
		else if (this.imageIndex >= this.images.length)
			this.imageIndex = 0
		this.DrawImage()
	},

	PrevStopNextImage: function(pageX)
	{
		this.currentPhoto.hide()
		if (pageX < _mp.Thumbs.limitLeft)
			this.ShowNextFullImage(-1)
		else if (pageX > _mp.Thumbs.limitMid)
			this.ShowNextFullImage(1)
		else
			this.HideFullImage()
	},

	HideFullImage: function()
	{
		ImageSet.prev.hide()
		ImageSet.stop.hide()
		ImageSet.next.hide()
		_mp.Images.Div.hide()
		if (this.totalName) this.totalName.hide()
		if (this.currentNumber) this.currentNumber.hide()
		if (this.currentImageName) this.currentImageName.hide()
		if (this.currentPhoto) this.currentPhoto.hide()
	},

	ShowFullImage: function()
	{
		var $this = this
		_mp.Images.Div.css({ top: _mp.Thumbs.top + 'px',
												 left: _mp.Thumbs.left + 'px',
												 width: _mp.Thumbs.width,
												 height: _mp.Thumbs.height })
									.show()
									.unbind('click')
									.click(function(event) { $this.PrevStopNextImage(event.pageX); return false })
		this.currentPhoto = this.LoadImage(this.imageIndex)
		this.currentPhoto.fitToSize(_mp.Thumbs.width, _mp.Thumbs.height, { justify: 'left' })
										 .stop()
										 .unbind()
										 .click(function(event) { $this.PrevStopNextImage(event.pageX); return false })
										 .animate({ opacity: 'show' }, { duration: 500, complete: function() { $this.PreLoadAdjacentImages($this.imageIndex) } })

		if (this.currentNumber)
			this.currentNumber.hide()
		this.LoadNumber(this.imageIndex)
		
		if (this.currentImageName)
			this.currentImageName.hide()
		this.currentImageName = this.LoadImageName(this.imageIndex)

		this.currentNumber = this.ShowNumber(this.imageIndex)
		this.totalName.show()
		ImageSet.prev.unbind()
								 .bind('click', function(event) { $this.ShowNextFullImage(-1) })
		ImageSet.stop.unbind()
								 .bind('click', function(event) { $this.HideFullImage() })
		ImageSet.next.unbind()
								 .bind('click', function(event) { $this.ShowNextFullImage(1) })
		$('.prev.top, .stop.top, .next.top').bind('mouseover', _mp.FadeIn)
																				.bind('mouseout', _mp.FadeOut)
		ImageSet.prev.show()
		ImageSet.stop.show()
		ImageSet.next.show()
	},

	// Move to the previous/next photo
	ShowNextFullImage: function(inc)
	{
		this.imageIndex += inc;
		if (this.imageIndex < 0)
			this.imageIndex = this.images.length - 1
		else if (this.imageIndex >= this.images.length)
			this.imageIndex = 0
		this.currentPhoto.stop().fadeOut('slow')
		this.ShowFullImage()
	},

	// Pre-load a maximum of 2 images, looking for a maximum of 4 forward and/or 3 backward images
	PreLoadAdjacentImages: function(idx)
	{
		if (this.images.length <= 1)
			return
		var next = idx + 1
		var prev = idx - 1
		var count = this.PreLoadImage(next) + this.PreLoadImage(prev)
		if (count == 2) return
		if ((count += this.PreLoadImage(++next)) == 2) return
		if ((count += this.PreLoadImage(--prev)) == 2) return
		if ((count += this.PreLoadImage(++next)) == 2) return
		if ((count += this.PreLoadImage(--prev)) == 2) return
		if ((count += this.PreLoadImage(++next)) == 2) return
	},

	// Returns 0 or 1 - the number of images that were loaded
	PreLoadImage: function(idx)
	{
		// Ensure idx is valid
		while (idx >= this.images.length)
			idx -= this.images.length
		while (idx < 0)
			idx += this.images.length
		if (this.ImageInDom(idx).length != 0)
			return 0;
		this.LoadImage(idx)
		return 1;
	},
	
		/////////// Thumbs ///////////

	CurrentThumbSet: null,

	HideThumbSet: function(thumbSet)
	{
		if (ImageSet.CurrentThumbSet != null)
		{
			ImageSet.CurrentThumbSet.HideFullImage()
			ImageSet.CurrentThumbSet.Table.hide()
		}
		ImageSet.CurrentThumbSet = thumbSet
	},

	// Load or show (if already loaded) all the thumbs in folder
	// Each thumb is given the properties:
	//		img.ownerObj = this
	//		img.idx = idx
	LoadThumbs: function()
	{
		this.HideThumbSet(this)
		_mp.Images.Div.hide()
		_mp.Thumbs.Div.show()
		if (this.Table)
		{
			this.Table.show()
		}
		else
		{
			LoadTable.call(this)
			// Load the '/total' image
			img = new Image()
			img.src = this.totalName
			_mp.Frame.Div.append(this.totalName = $(img))
			this.Position(ImageSet.topCtrlsThumbPages)
			ImageSet.prev.unbind()
									 .bind('click', function(event) { ownerObj.DrawNext(-1) })
			ImageSet.next.unbind()
									 .bind('click', function(event) { ownerObj.DrawNext(1) })
			$('.prev.top, .stop.top, .next.top').bind('mouseover', _mp.FadeIn)
																					.bind('mouseout', _mp.FadeOut)
			ImageSet.prev.css({ left: this.leftNum - 80 + 'px' })
			ImageSet.stop.css({ left: this.leftNum - 51 + 'px' })
			ImageSet.next.css({ left: this.leftNum - 30 + 'px' })
		}

		UpdateScroll(false)

		function LoadTable()
		{
			this.Table = $('<table></table>')
			this.count = 0
			_mp.Thumbs.Scroll.append(this.Table)
			var cols = 2
			var colIdx = cols
			var width = Math.floor(_mp.Thumbs.width / cols)
			for (var idx in this.images)
			{
				if (++colIdx >= cols)
				{
					// Create a new row
					var row = document.createElement('tr')
					this.Table.append(row)
					colIdx = 0
				}
				var imageInfo = this.images[idx]
				var td = document.createElement('td')
				td.width = width
				row.appendChild(td)
				var imgNum = Number(idx) + 1
				td = $(td).attr('align', 'center')
									.html('<div><img class="clickThumb" src="Thumb/' + this.folder + '/' + imageInfo.name.replace(/...$/, 'png') + '"/>' +
														 '<img class="clickThumb" src="' + imageInfo.textImg + '"/>' +
														 '<img class="clickThumb" src="cache/tn ' + imgNum + ' ' + this.fontSize + '.png"/>' +
												'</div>')
				var img = td.find('img.clickThumb')
										.load(ThumbLoaded)
										.click(ThumbClicked)[0]
				img.ownerObj = this
				img.idx = idx
			}
		}

		function ThumbLoaded(event)
		{
			var img = event.target
			if (img.ownerObj == undefined)
				return
			var $this = img.ownerObj
			if ($this.Timer)
				clearTimeout($this.Timer)
			if (++$this.count == $this.images.length)
				UpdateScroll(true)
			else
				$this.Timer = setTimeout(function() { UpdateScroll(true) }, 2000)
		}

		function UpdateScroll(mPos)
		{
			_mp.Thumbs.Scroll.jScrollPane({ maintainPosition: mPos })
		}

		function ThumbClicked(event)
		{
			var img = event.target
			var $this = img.ownerObj
			$this.imageIndex = Number(img.idx)
			$this.ShowFullImage()
		}

		function HideImage(event)
		{
			var img = event.target
			var $this = img.ownerObj
			$(img).hide()
			_mp.Images.Div.hide()
		}
	}
}
