function PreloaderServices() {
	
	var _this = this;
	
	var loadParams;
	var fileSizes = [];
	var progressHandlerFunc;
	var allCallbackFunc;
	
	var checkTotalByteCount;
	var checkTotalBytesCallbackFunc;
	var totalBytes;
	var loadedBytes;
	
	var loadCount;
	
	var bytesPerSec;
	var loadStartTime;
	
	var progressBeaconId;
	
	var moveToNext = false;
	var moveToNextIntervalId;
	this.preloadImages = function(_loadParams, _allCallbackFunc, _progressHandlerFunc) {
		//traceOut('PreloaderServices.preloadImages()...');
		
		loadParams = _loadParams;
		allCallbackFunc = _allCallbackFunc;
		progressHandlerFunc = _progressHandlerFunc;
		
		bytesPerSec = 0;
		
		checkTotalBytes(loadImages);
		
		moveToNextIntervalId = setInterval(moveToNextCheck, 60);
		
	}
	
	function checkTotalBytes(_checkTotalBytesCallbackFunc) {
		
		checkTotalBytesCallbackFunc = _checkTotalBytesCallbackFunc;
		
		totalBytes = 0;
		
		checkTotalByteCount = 0;
		checkTotalByte(loadParams[checkTotalByteCount], checkNextTotalByte);
		
	}
	
	function checkTotalByte(loadParam, _callbackFunc) {
		var request;
		request = $.ajax({
			type: "HEAD",
			url: loadParam.src,
			success:function() {
				var currentBytes = parseInt(request.getResponseHeader("Content-Length"));
				totalBytes += currentBytes;
				loadParams[checkTotalByteCount].fileSize = currentBytes;
				_callbackFunc();
			}
		});
	}
	
	function checkNextTotalByte() {
		checkTotalByteCount++;
		if(checkTotalByteCount < loadParams.length) {
			checkTotalByte(loadParams[checkTotalByteCount], checkNextTotalByte);
		} else {
			checkTotalBytesCallbackFunc();
		}
	}
	
	function loadImages() {
		//traceOut('PreloaderServices.loadImages()...');
		
		loadedBytes = 0;
		loadCount = 0;
		loadImage(loadCount);
		
		progressBeaconId = setInterval(function() {
			progressHandlerFunc({bytesLoaded:loadedBytes, bytesTotal:totalBytes});
		}, 30);
		
	}
	
	function loadImage(id) {
		//traceOut('PreloaderServices.loadImage():id=='+id+', src=='+loadParams[id].src);
		
		var d = new Date();
		loadStartTime = d.getTime();
		
		var tar;
		if(loadParams[id].src.indexOf('.png') >= 0 || loadParams[id].src.indexOf('.jpg') >=0) {
			tar = $('<img/>');
			tar.load(function() {
				onLoadImageComplete(tar);
			});
			tar.attr('src',loadParams[id].src);
		} else {
			tar = $('<div></div>');
			tar.load(loadParams[id].src, function() {
				onLoadImageComplete(tar);
			});
		}
		
	}
	
	function onLoadImageComplete(tarObj) {
		traceOut("PreloaderServices.onLoadImageComplete():loadCount=="+loadCount+'/'+loadParams.length+', which is '+loadParams[loadCount]);
		loadedBytes += loadParams[loadCount].fileSize;
		var d = new Date();
		var currentBytesPerSec = loadParams[loadCount].fileSize / ((d.getTime() - loadStartTime) / 1000);
		bytesPerSec = (bytesPerSec + currentBytesPerSec) / 2;
		loadParams[loadCount].callbackFunc(tarObj);
		loadCount++;
		moveToNext = true;
	}
	
	function moveToNextCheck() {
		
		if(moveToNext == true) {
			moveToNext = false;
			if(loadCount<loadParams.length) {
				loadImage(loadCount);
			} else {
				clearInterval(progressBeaconId);
				clearInterval(moveToNextIntervalId);
				allCallbackFunc();
			}
		}
		
	}
	
	this.getProgress = function() {
		return loadedBytes/totalBytes;
	}
	
	this.getTotalBytes = function() {
		return totalBytes;
	}
	
	this.getTotalBytesOfFile = function(loadParam, callback) {
		checkTotalByte(loadParam, callback);
	}
	
}

var preloaderServices = new PreloaderServices();
