// ----------------------------------------------------------------------
//
// Simple jQuery Slideshow with XML
// @author Lab-art http://www.lab-art.co.jp/
// 06.02.2011 Script created
// Requires jQuery 1.2.6 or higher
//
// ----------------------------------------------------------------------


(function(jQuery)
{
	jQuery.fn.slideshow = function(params)
	{
		var prms;
		var duration;
		var delay;
		
		var xmlArray = [];
		var imgNum = 0;
		var imgList;
		
		var wrapper;
		var container;
		var loadIcon;
		var timer;
		
		
		prms = jQuery.extend(jQuery.fn.slideshow.defaults, params);
		duration = prms.duration * 1000;
		delay = prms.delay * 1000;
		
		
		// ----------------------------------------------------------------------
		// XML読み込み
		// ----------------------------------------------------------------------
		
		function loadXML()
		{
			jQuery.ajax({
				type: "GET",
				url: prms.xmlPath,
				cache: false,
				dataType: "xml",
				success: xmlLoadComplete,
				error: xmlLoadError
			});
		}
		
		function xmlLoadError(XMLHttpRequest, textStatus, errorThrown)
		{
			loadIcon.remove();
			showMessage("XML読込エラーです", "#FF0000");
		}
		
		function xmlLoadComplete(xml)
		{
			jQuery(xml).find("image").each(function(){
				xmlArray.push(jQuery(this).text());
			});
			
			imgNum = xmlArray.length;
			
			if(imgNum != 0){
				loadImages();
			}else{
				loadIcon.remove();
				showMessage("画像がありません", "#FF0000");
			}
		}
		
		
		// ----------------------------------------------------------------------
		// 画像読み込み
		// ----------------------------------------------------------------------
		
		var successCnt = 0;
		var errorCnt = 0;
		var imgArray = [];
		
		function loadImages()
		{
			loadImage();
		}
		
		function loadImage()
		{
			var imgPath = xmlArray[successCnt + errorCnt];
			if(jQuery.browser.msie){
				imgPath += "?" + Math.floor(Math.random()*100000);
			}
			
			var img = jQuery("<img />")
			.load(loadCount)
			.error(errorCount)
			.attr("src", imgPath)
			.attr("alt", "")
			.css({
				 verticalAlign: "bottom",
				 border: "none",
				 position: "absolute",
				 top: 0,
				 left: 0
			});
			
			imgArray.push(img);
		}
		
		function errorCount()
		{
			imgArray.splice(successCnt, 1);
			errorCnt++;
			
			if((successCnt + errorCnt) != imgNum){
				loadImage();
			}else{
				imagesLoadComplete();
			}
		}
		function loadCount()
		{
			successCnt++;
			
			if((successCnt + errorCnt) != imgNum){
				loadImage();
			}else{
				imagesLoadComplete();
			}
		}
		
		function imagesLoadComplete()
		{
			imgNum = imgArray.length;
			
			if(imgNum != 0)
			{
				var c = new ElementList();
				for(var i=0; i<imgNum; i++){
					c.add(imgArray[i]);
				}
				imgList = c.createIterator();
				
				loadIcon.fadeOut("slow", function(){
					loadIcon.remove();
					firstSet();
				});
			}
			else
			{
				loadIcon.remove();
				showMessage("画像読込エラーです", "#FF0000");
			}
		}
		
		
		// ----------------------------------------------------------------------
		// 表示準備完了後、最初の処理
		// ----------------------------------------------------------------------
		
		function firstSet()
		{
			while(imgList.hasNext())
			{
				imgList.current()
				.appendTo(container)
				.css({
					display: "none"
				});
				imgList.next();
			}
			imgList.setIndex(0);
			
			imgList.current()
			.appendTo(container)
			.animate({
				opacity: "show"
			},{
				duration: duration
			});
			
			if(imgNum != 1){
				timer = setInterval(showNext, delay);
			}
		}
		
		
		// ----------------------------------------------------------------------
		// 表示画像の切替
		// ----------------------------------------------------------------------
		
		function showNext()
		{
			imgList.loopNext()
			.css({
				display: "none"
			})
			.appendTo(container)
			.animate({
				opacity: "show"
			},{
				duration: duration
			});
		}
		
		
		// ----------------------------------------------------------------------
		// エラー表示用
		// ----------------------------------------------------------------------
		
		function showMessage(msg, textColor)
		{
			var msg = jQuery("<div>" + msg +"</div>")
			.css({
				fontSize: "10px",
				color: textColor,
				textAlign: "center",
				paddingTop: parseInt(container.height() / 2) - 5 + "px"
			})
			.appendTo(container);
		}
		
		
		// ----------------------------------------------------------------------
		// コレクション
		// ----------------------------------------------------------------------
		
		function ElementList()
		{
			var _list = [];
			
			this.add = function(element){
				_list.push(element);
			}
			
			this.getElementAt = function(index){
				return _list[index];
			}
			
			this.length = function(){
				return _list.length;
			}
			
			this.createIterator = function(){
				return new ElementIterator(this);
			}
		}
		
		
		// ----------------------------------------------------------------------
		// イテレータ
		// ----------------------------------------------------------------------
		
		function ElementIterator(collection)
		{
			var _collection = collection;
			var _index = 0;
			
			this.setIndex = function(index){
				_index = index;
			}
			
			this.current = function(){
				return _collection.getElementAt(_index);
			}
			
			this.currentNext = function(){
				return _collection.getElementAt(_index + 1);
			}
			this.currentPrev = function(){
				return _collection.getElementAt(_index - 1);
			}
			
			this.next = function(){
				if(this.hasNext()){
					return _collection.getElementAt(++_index);
				}
			}
			this.prev = function(){
				if(this.hasPrev()){
					return _collection.getElementAt(--_index);
				}
			}
			
			this.hasNext = function(){
				return _index < _collection.length() - 1;
			}
			this.hasPrev = function(){
				return _index > 0;
			}
			
			this.currentLoopNext = function(){
				if(this.hasNext()){
					return this.currentNext();
				}else{
					return _collection.getElementAt(0);
				}
			}
			this.currentLoopPrev = function(){
				if(this.hasPrev()){
					return this.currentPrev();
				}else{
					return _collection.getElementAt(_collection.length() - 1);
				}
			}
			
			this.loopNext = function(){
				if(this.hasNext()){
					return this.next();
				}else{
					_index = 0;
					return this.current();
				}
			}
			this.loopPrev = function(){
				if(this.hasPrev()){
					return this.prev();
				}else{
					_index = _collection.length() - 1;
					return this.current();
				}
			}
		}
		
		
		// ----------------------------------------------------------------------
		// 
		// ----------------------------------------------------------------------
		
		return this.each(function()
		{
			wrapper = jQuery(this);
			
			container = jQuery("<div>")
			.attr("id", prms.id)
			.css({
				 position: "relative",
				 backgroundColor: prms.bgColor,
				 width: prms.width + "px",
				 height: prms.height + "px",
				 overflow: "hidden"
			})
			.appendTo(wrapper);
			
			if(prms.loadIcon) {
				loadIcon = jQuery("<img />").attr("src", prms.loadIcon);
				loadIcon.css({
					position: "absolute",
					top: parseInt((container.height() - jQuery(loadIcon).height()) / 2) + "px",
					left: parseInt((container.width() - jQuery(loadIcon).width()) / 2) + "px"
				})
				.appendTo(container);
			}
			
			loadXML();
		});
		
	}
	
	
	// ----------------------------------------------------------------------
	// デフォルト設定
	// ----------------------------------------------------------------------
	
	jQuery.fn.slideshow.defaults =
	{
		id: "simpleSlideshowContainer",
		xmlPath: "images.xml",
		loadIcon: "",
		width: 300,
		height: 300,
		bgColor: "#FFFFFF",
		duration: 0.5,
		delay: 3
	}
	
	
})(jQuery);
