if (!YAHOO.cmsIT.imageLoader)
{
	YAHOO.cmsIT.imageLoader = function()
	{
		// Private
		var variables = {},
			thisLoader = this;


		variables.queues = {};
		variables.queueCount = 1;
		variables.imageCache = {};


		var CanAddImageToQueue = function(queueName)
		{
			if (!variables.queues[queueName] || variables.queues[queueName].loadStarted)
			{
				return false;	
			}

			return true;
		};


		var CreateEvent = function(queueName, eventName)
		{
			if (variables.queues[queueName])
			{
				variables.queues[queueName].events[eventName] = new YAHOO.util.CustomEvent(eventName, this);
			}
		};


		var CreateImageContainer = function()
		{
			var imageDiv = document.createElement("div");
			imageDiv.style.width = "2200px";
			imageDiv.style.position = "absolute";
			imageDiv.style.left = "-10000px";
			imageDiv.style.top = "-10000px";
			imageDiv.style.overflow = "hidden";

			document.body.appendChild(imageDiv);

			return imageDiv;
		};


		var CreateQueue = function()
		{
			var queueNumber = variables.queueCount;

			variables.queues["queue" + queueNumber] =
			{
				events: {},
				loaded: false,
				loadInOrder: false,
				loadStarted: false,
				imageContainer: CreateImageContainer(),
				images: [],
				imagesLoaded: 0,
				name: "queue" + queueNumber
			};

			CreateEvent("queue" + queueNumber, "queueImageLoaded");
			CreateEvent("queue" + queueNumber, "queueLoaded");

			variables.queueCount++;

			return variables.queues["queue" + queueNumber];
		};


		var LoadNextImage = function(queueName, nextImgID)
		{
			if (variables.queues[queueName])
			{
				var queue = variables.queues[queueName];

				if (nextImgID <= queue.images.length - 1)
				{
					queue.images[nextImgID].Load();
				}

				if (!queue.loadInOrder && nextImgID < queue.images.length - 1)
				{
					LoadNextImage(queueName, nextImgID + 1);
				}
			}
		};


		var OnImageLoaded = function(evName, args, queueName)
		{
			var imageProperties = args[0];
			var queue = variables.queues[queueName];

			queue.imagesLoaded++;
			variables.imageCache[imageProperties.url] = imageProperties;


			if (queue.imagesLoaded == queue.images.length)
			{
				queue.loaded = true;
			}



			// Fire off events
			var args = 
			{
				image: imageProperties,
				queue: YAHOO.cmsIT.imageLoader.GetQueueProperties(queueName)
			};


			queue.events["queueImageLoaded"].fire(args);

			if (queue.imagesLoaded == queue.images.length)
			{
				queue.events["queueLoaded"].fire(args);
				YAHOO.cmsIT.imageLoader.RemoveQueue(args.queue.name);
			}

			if (queue.loadInOrder)
			{
				LoadNextImage(queueName, Number(imageProperties.id) + 1);
			}
		};




		// Public
		return {
			GetImageProperties: function(url)
			{
				if (url in variables.imageCache)
				{
					return variables.imageCache[url];
				}

				return null;
			},


			GetNewQueue: function()
			{
				var newQueue = CreateQueue();

				return this.GetQueueProperties(newQueue.name);
			},


			GetQueueProperties: function(queueName)
			{
				if (variables.queues[queueName])
				{
					var queue = variables.queues[queueName];

					var properties =
					{
						name: queue.name,
						loaded: queue.loaded,
						images: queue.images.length,
						imagesLoaded: queue.imagesLoaded
					};

					return properties;
				}
			},


			ImagePreviouslyLoaded: function(url)
			{
				return (url in variables.imageCache);
			},


			LoadImages: function(queueName, loadInOrder)
			{
				if (loadInOrder == undefined || loadInOrder == null)
				{
					loadInOrder = false;	
				}

				if (variables.queues[queueName] && !variables.queues[queueName].loadStarted)
				{
					var queue = variables.queues[queueName];

					queue.loadStarted = true;
				}

				if (loadInOrder)
				{
					queue.loadInOrder = true;
				}

				LoadNextImage(queueName, 0);
			},


			QueueImage: function(queueName, url, onload, onloadObj)
			{
				if (CanAddImageToQueue(queueName))
				{
					var queue = variables.queues[queueName];
					var newLength = queue.images.push(null);

					var id = newLength - 1;

					var newImage = YAHOO.cmsIT.imageLoaderImage(id, url, queue.imageContainer);

					if (onload != undefined && onload != null)
					{
						newImage.Subscribe("imageLoaded", onload, onloadObj);
					};

					newImage.Subscribe("imageLoaded", OnImageLoaded, queueName);

					queue.images[id] = newImage;

					return true;
				}

				return false;
			},


			RemoveQueue: function(queueName)
			{
				if (variables.queues[queueName])
				{
					var queue = variables.queues[queueName];

					// Clear images
					for (var i = 0; i < queue.images.length; i++)
					{
						queue.images[i].Destroy();
					};

					// Clear Events
					for (eventName in queue.events)
					{
						queue.events[eventName].unsubscribeAll();
						queue.events[eventName] = null;
						delete queue.events[eventName];
					};

					document.body.removeChild(queue.imageContainer);

					variables.queues[queueName] = null;
					delete variables.queues[queueName];
				}
			},


			// args[0].image.id				-	image number/id
			// args[0].image.url				-	image url
			// args[0].image.height				-	image height
			// args[0].image.width				-	image width
			// args[0].queue.name				-	queue name
			// args[0].queue.loaded			-	# queue has completed loading
			// args[0].queue.images			-	# total images to load
			// args[0].queue.imagesLoaded		-	# images loaded
			//
			// EVENTS						RETURNS
			// queueImageLoaded				eventName, args, customObj
			// queueLoaded					eventName, args, customObj
			Subscribe: function(queueName, eventName, callback, obj)
			{
				if (variables.queues[queueName] && variables.queues[queueName].events[eventName])
				{
					variables.queues[queueName].events[eventName].subscribe(callback, obj);
				}
			}
		};
	}();
}




if (!YAHOO.cmsIT.imageLoaderImage)
{
	YAHOO.cmsIT.imageLoaderImage = function(id, url, container)
	{
		// Private
		var attempts = 0,
			events = new Object(),
			loaded = false,
			loadStarted = false,
			image = null,
			imageContainer = container,
			imageID = id,
			imageURL = url,
			thisImage = this;


		var CreateEvent = function(eventName)
		{
			events[eventName] = new YAHOO.util.CustomEvent(eventName, this);
		};


		var Init = function()
		{
			if (YAHOO.lang.isString(imageURL) && imageContainer != undefined && imageContainer != null)
			{
				CreateEvent("imageLoaded");
			}
		};


		var LoadImage = function()
		{
			if (!loadStarted)
			{
				loadStarted = true;

				image = new Image();
				image.src = imageURL;

				imageContainer.appendChild(image);

				if (
						!YAHOO.lang.isUndefined(image.complete) &&
						!YAHOO.lang.isNull(image.complete) &&
						YAHOO.lang.isBoolean(image.complete) &&
						image.complete
					)
				{
					TestImageLoaded();
				}
				else
				{
					image.onload = TestImageLoaded;
				}
			}
		};


		var TestImageLoaded = function()
		{
			if (image == null)
			{
				return;	
			}

			if (image.width > 0 && image.height > 0)
			{
				loaded = true;
				var region = YAHOO.util.Dom.getRegion(image);

				var imageProperties =
				{
					id: imageID,
					url: imageURL,
					height: region.height,
					width: region.width
				}

				events["imageLoaded"].fire(imageProperties);
			}

			// Check 10 times a second for the 1st 10 seconds
			else if (attempts <= 100)
			{
				YAHOO.lang.later(100, this, TestImageLoaded);
			}

			// Re-attempt once every 2 seconds
			else
			{
				YAHOO.lang.later(2000, this, TestImageLoaded);
			}
		}


		Init();




		// Public
		if (imageURL == undefined || imageURL == null || imageContainer == undefined || imageContainer == null)
		{
			return null;
		}

		return {
			Destroy: function()
			{
				for (var eventName in events)
				{
					events[eventName].unsubscribeAll();
					events[eventName] = null;
					delete events[eventName];
				}

				image.parentNode.removeChild(image);
				image = null;
			},


			IsLoaded: function()
			{
				return loaded;	
			},


			Load: function()
			{
				LoadImage();
			},


			// imageLoaded		returns: eventName, imageProperties, customObj
			Subscribe: function(eventName, callback, obj)
			{
				if (events[eventName])
				{
					events[eventName].subscribe(callback, obj);
				}
			}
		};
	};
}
