/**
 * @author	Wonil Suh (wonil.suh@atmospherebbdo.com, wonil@wonilSuh.com)
 * @date	2011
 */
function PreloaderServices() {
	
	var _this = this;
	
	var loadAssets;
	var loadParams;
	var fileSizes = [];
	
	var checkTotalByteCount;
	var checkTotalBytesCallbackFunc;
	var totalBytes;
	var loadedBytes;
	
	var loadCount;
	
	var bytesPerSec;
	var loadStartTime;
	var preloaderInterval;
	
	var progressBeaconId;
	
	var moveToNext = false;
	var moveToNextIntervalId;
	
	this.preloadImages = function(_loadAssets, _loadParams) {
		//traceOut('PreloaderServices.preloadImages()...');
		
		loadAssets = _loadAssets;
		loadParams = _loadParams;
		
		if(!loadParams.progressReportInterval) loadParams.progressReportInterval = 100;
		
		prevProgress = 0;
		bytesPerSec = 0;
		
		checkTotalBytes(loadImages);
		
		moveToNextIntervalId = setInterval(moveToNextCheck, 60);
		
	}
	
	function checkTotalBytes(_checkTotalBytesCallbackFunc) {
		
		checkTotalBytesCallbackFunc = _checkTotalBytesCallbackFunc;
		
		totalBytes = 0;
		
		checkTotalByteCount = 0;
		checkTotalByte(loadAssets[checkTotalByteCount], checkNextTotalByte);
		
	}
	
	function checkTotalByte(loadParam, _callbackFunc) {
		
		if(loadParam.fileSize) {
			totalBytes += loadParam.fileSize;
			_callbackFunc();
		} else {
			var request;
			request = $.ajax({
				type: "HEAD",
				url: loadParam.src,
				success:function() {
					var currentBytes = parseInt(request.getResponseHeader("Content-Length"));
					totalBytes += currentBytes;
					loadAssets[checkTotalByteCount].fileSize = currentBytes;
					_callbackFunc();
				}
			});
		}
		
	}
	
	function checkNextTotalByte() {
		checkTotalByteCount++;
		if(checkTotalByteCount < loadAssets.length) {
			checkTotalByte(loadAssets[checkTotalByteCount], checkNextTotalByte);
		} else {
			checkTotalBytesCallbackFunc();
		}
	}
	
	function loadImages() {
		//traceOut('PreloaderServices.loadImages()...');
		
		var d = new Date();
		loadStartTime = d.getTime();
		
		loadedBytes = 0;
		loadCount = 0;
		loadImage(loadCount);
		
		progressBeaconId = setInterval(function() {
			loadParams.onProgress({bytesLoaded:loadedBytes, bytesTotal:totalBytes});
		}, preloaderInterval);
		
	}
	
	function loadImage(id) {
		//traceOut('PreloaderServices.loadImage():id=='+id+', src=='+loadAssets[id].src);
		
		var tar;
		if(loadAssets[id].src.indexOf('.png') >= 0 || loadAssets[id].src.indexOf('.jpg') >=0) {
			tar = $('<img/>');
			tar.load(function() {
				onLoadImageComplete(tar);
			});
			tar.attr('src',loadAssets[id].src);
		} else {
			tar = $('<div></div>');
			tar.load(loadAssets[id].src, function() {
				onLoadImageComplete(tar);
			});
		}
		
	}
	
	function onLoadImageComplete(tarObj) {
		//traceOut("PreloaderServices.onLoadImageComplete():loadCount=="+loadCount+'/'+loadAssets.length+', which is '+loadAssets[loadCount]);
		loadedBytes += loadAssets[loadCount].fileSize;
		var d = new Date();
		bytesPerSec = loadedBytes / ((d - loadStartTime) / 1000);
		loadAssets[loadCount].callbackFunc(loadAssets[loadCount]);
		loadCount++;
		moveToNext = true;
	}
	
	function moveToNextCheck() {
		
		if(moveToNext == true) {
			moveToNext = false;
			if(loadCount<loadAssets.length) {
				loadImage(loadCount);
			} else {
				clearInterval(progressBeaconId);
				clearInterval(moveToNextIntervalId);
				loadParams.onComplete();
			}
		}
		
	}
	
	var prevProgress;
	function getProgress() {
		if(loadParams.usePredictiveProgressReport==true) {
			var d = new Date();
			var ret = getBytesPerSec() * ((d.getTime() - loadStartTime) / 1000) / getTotalBytes();
			if(ret > 1) ret = 1;
			if(ret < prevProgress) ret = prevProgress;
			prevProgress = ret;
			return ret;
		} else {
			return loadedBytes/totalBytes;
		}
		
	}
	this.getProgress = getProgress;
	
	function getCurrentFileProgress() {
		return getProgress - (loadedBytes / totalBytes);
	}
	this.getCurrentFileProgress = getCurrentFileProgress;
	
	function getTotalBytes() {
		return totalBytes;
	}
	this.getTotalBytes = getTotalBytes;
	
	function getLoadedBytes() {
		return loadedBytes;
	}
	
	function getBytesPerSec() {
		return bytesPerSec;
	}
	this.getBytesPerSec = getBytesPerSec;
	
	function getTotalBytesOfFile(loadParam, callback) {
		checkTotalByte(loadParam, callback);
	}
	this.getTotalBytesOfFile = getTotalBytesOfFile;
	
}

