/*
 * Image pre-loader
 * DEO 2010.05.22
 */
 
var preloader = (function() {
	var _index = 0, _curClass = 'preloader_cur';
						 
	var cacheList = {};
	
	var config = {
		LOADING	: 'Loading...',
		ERROR	: 'Error'
	};
	
	var status = {
		LOADING	: 'loading',
		LOADED	: 'loaded',
		ERROR	: 'error'
	};
	
	var effectTimerHandler = null;
	
	function Extend( destination, source ){
		for( var property in source )
			destination[ property ] = source[ property ];
	}
	
	function GetCache( boxID, conID, options ) {
		if( cacheList[boxID] )
			return cacheList[boxID];
		
		var data = {}, 
			
			tempImg = null, 
			
			imgs = document.getElementById( boxID ).getElementsByTagName('img');
		
		for( var i = 0; i < imgs.length; i ++ ) {
			tempImg = new Image();
			tempImg.src = imgs[i].src;//+ '?'+(new Date()).getTime();
			tempImg._i = i;
			
			if( !data[i] ) {
				data[i] = {};
				
				data[i].loaded 	= false;
				data[i].error 	= false;
				data[i].src 	= tempImg.src;
			}
			
			tempImg.onload = function() {
				data[this._i].loaded = true;
			};
			
			tempImg.onerror = function() {
				data[this._i].error = true;
			};
		}
		
		cacheList[boxID] = {};
		cacheList[boxID].image 		= data;
		cacheList[boxID].size 		= 0;
		cacheList[boxID].controlID	= conID;
		
		cacheList[boxID].autoTimerHandler = null;
		cacheList[boxID].listenerTimerHandler 	= null;
		
		
		cacheList[boxID].options = {
			curClass	: _curClass,
			index		: _index,
			auto		: false,
			autoTimer	: 3000
		};

		
		Extend( cacheList[boxID].options, options || {} );
		
		cacheList[boxID].autoIndex 	= cacheList[boxID].options.index;
	}
	
	function Main( boxID ) {
		
		var data = cacheList[boxID],
			
			con = document.getElementById( data.controlID ), 
		
			links = con.getElementsByTagName('a');
			
		data.size = links.length;
			
		for( var i = 0, len = links.length; i < len; i ++ ) {
			
			links[i].onclick = function() {
				
				var index = parseInt( this.getAttribute( 'rel' ) ) - 1;
				
				clearTimeout( cacheList[boxID].timer );
				cacheList[boxID].timer = null;
				
				Listener( boxID, data.autoIndex = index );
				
				var curStatus = status.LOADING;
				
				if( !data.image[index].error ) {
					if( data.image[index].loaded ) {
						curStatus = status.LOADED;
					}
					
				} else {
					curStatus = status.ERROR;
				}
				
				GetInfoBox( boxID, curStatus );
				
				SetLinkClass( boxID, index );
				
				data.autoIndex = data.autoIndex ++ >= data.size ? 0: index + 1;
				
				return false;
			}
			
			AutoControl( links[i], data, boxID );
			
		}
		
	}
	
	function Auto( boxID ) {
		var data = cacheList[boxID];
		
		clearTimeout( data.autoTimerHandler );
		
		if( data.autoIndex >= data.size ) {
			data.autoIndex = 0;
		}
		
		SetLinkClass( boxID, data.autoIndex );
		
		Listener( boxID, data.autoIndex ++ );
		
		data.autoTimerHandler = setTimeout( function(){ Auto( boxID ); }, data.options.autoTimer );
	}
	
	function AutoControl( elem, data, boxID ) {
		
		elem.onmouseover = function() {
			clearTimeout( data.autoTimerHandler );
		};
		
		elem.onmouseout = function() {
			data.autoTimerHandler = setTimeout( function(){ Auto( boxID ); }, data.options.autoTimer );
		};
	}
	
	function SetLinkClass( boxID, index ) {
		var data = cacheList[boxID],
		
			con = document.getElementById( data.controlID ), 
		
			links = con.getElementsByTagName('a');
			
		for( var i = 0; i < links.length; i ++ ) {
			
			if( index == i ) {
				
				ClassEvent( links[i] ).add( data.options.curClass );
			} else {
				
				ClassEvent( links[i] ).remove( data.options.curClass );
			}
			
		}
		
	}
	
	function Listener( boxID, i ) {
		var data = cacheList[boxID];
		
		clearTimeout( data.timer );
	
		var image = data.image[i];
		
		if( !image.loaded ) {
			
			if( data.listenerTimerHandler == null ) 
				ToDisplay( boxID, status.LOADING, i );
			
		} else {
			
			ToDisplay( boxID, status.LOADED, i );
		}
		
		if( image.error ) {
			
			ToDisplay( boxID, status.ERROR, i );
			
			clearTimeout( data.listenerTimerHandler );
			
			return;
		}
			
		if( !image.loaded )
			data.listenerTimerHandler = setTimeout( function() { Listener( boxID, i ); }, 100 );
	}
	
	function ToDisplay( boxID, curStatus, index ) {
		
		var data = cacheList[boxID],
			
			list = document.getElementById( boxID ).getElementsByTagName( 'a' );
		
		for( var i = 0, len = list.length; i < len; i ++ ) {
			
			if( index == i ) {
				
				list[i].style.display = 'block';
				
				var img = list[i].getElementsByTagName( 'img' )[0];
				
				opacity( list[i], n = 0 );
				// Fade in effect
				fadeIn( list[i] );
				
				// Loading
				if( curStatus == status.LOADING ) {
					
					GetInfoBox( boxID, curStatus );
					
				}
				
				// Error
				if( curStatus == status.ERROR ) {
					
					GetInfoBox( boxID, curStatus );
					
				}
				
				// LOADED
				if( curStatus == status.LOADED ) {
					
					GetInfoBox( boxID, curStatus );
					
					img.src = data.image[index].src;
					
				}
			} 
			
			else {
				
				list[i].style.display = 'none';
				
			}
			
			AutoControl( list[i], data, boxID );
		}
		
	}
	
	var n = 0;
	function fadeIn( elem ) {
		clearTimeout( effectTimerHandler );
		
		if( n <= 10 ) {		
			opacity( elem, ( n ++ ) / 10 );
			
			effectTimerHandler = setTimeout( function(){ fadeIn( elem ); }, 60 );
		}
	}
	
	function opacity( elem, num ) {
		elem.style.opacity = num;
		
		if( document.all )
			elem.style.filter = 'alpha(opacity='+num*100+')';
	}
	
	function GetInfoBox( boxID, curStatus ) {
		var infoBox = document.getElementById( 'preloader-info_' +boxID );
		
		ClassEvent( infoBox ).remove( 'preloader-info-hidden' );
		
		if( curStatus == status.LOADING ) {
			
			infoBox.innerHTML = IsImage( config.LOADING ) ? '<img src="'+ config.LOADING +'" alt="" />&nbsp;': config.LOADING;
		}
		
		else if( curStatus == status.ERROR ) {
			
			infoBox.innerHTML = IsImage( config.ERROR ) ? '<img src="'+ config.ERROR +'" alt="" />&nbsp;': config.ERROR;
		}
		
		else if( curStatus == status.LOADED ) {
			
			ClassEvent( infoBox ).add( 'preloader-info-hidden' );
			
		}
	}
	
	function CreateInfoBox( boxID ) {
		var info = document.createElement( 'div' );
			info.id = 'preloader-info_' + boxID;
			info.className = 'preloader-info';
		
		var elem = document.getElementById( boxID );
		
		info.style.width = elem.offsetWidth + 'px';
		info.style.height = elem.offsetHeight + 'px';
		info.style.lineHeight = elem.offsetHeight + 'px';
		
		elem.appendChild( info );
	}
	
	function DefaultDisplay( boxID, i ) {
		// 设置默认样式
		SetLinkClass( boxID, i );
		
		Listener( boxID, i );
	}
	
	function IsImage( src ) {
		return /.\.(jpg|gif|png|bmp)/.test( src );
	}
	
	function ClassEvent( elem ) {
		var arr = [], map = {}, isClass = false;
		
		function eachClass( elem, className ) {
			var hasClass = elem.className.split(/\s+/);
			for (var i = 0; i < hasClass.length; i ++) {
				if (hasClass[i] != className) { map[ hasClass[i] ] = hasClass[i]; }
				else { isClass = true; }
				arr.push( hasClass[i] );
			}
		}
		
		return {
			add: function( className ) {
				eachClass( elem, className );
				
				if ( !isClass ) { arr.push( className ); }
				elem.className = arr.join(" ").replace(/^\s*|\s*$/g,'');
			},
			remove: function( className ) {
				eachClass( elem, className );
				
				arr = []; for (var key in map) { arr.push( key ); }
				elem.className = arr.join(" ").replace(/^\s*|\s*$/g,'');
			}
		}
	}
	
	return {
		init: function( boxID, conID, options ) {
			
			ClassEvent( document.getElementById( boxID ) ).add( 'preloader' );
			CreateInfoBox( boxID );
			
			GetCache( boxID, conID, options );	
			
			Main( boxID );
			
			var defIndex = cacheList[boxID].options.index;
			DefaultDisplay( boxID, defIndex );
			
			if( cacheList[boxID].options.auto ) {
				Auto( boxID );
			}
		},
		
		setConfig: function( options ) {
			Extend( config, options );
		}
	};
	
})();
