/* --------------------------------------------------------------------*\
*                                                                       *
*  This file is a part of ArtWeb effects manager, created by ArtWeb OÜ. *
*                                                                       *
*  Any unauthorized use of this file is strictly prohibited.            *
*  For all questions concerning the usage of this code please send an   * 
*  email to info@art-web.ee or contact us on http://www.art-web.ee      *
*                                                                       *
/* --------------------------------------------------------------------*/

var artWebEffectsManager = new function()
{
	this.startEffect = function(effectName, element, parameters, callback)
	{
		var effectPlugin = false;
		if (effectPlugin = this.getEffectPlugin(effectName, element))
		{
			this.setEffectParameters(effectPlugin, parameters);
			
			var effectInfo = null;
			if (effectInfo = this.registerEffectInfo(effectName, element))
			{
				effectInfo.clearTimeOuts(effectName);
				
				this.assignTimeouts(effectPlugin, effectInfo, callback);
			}
		}
	}
	this.queueEffect = function(effectName, element, parameters, callback)
	{
		var effectPlugin = false;
		if (effectPlugin = this.getEffectPlugin(effectName, element))
		{
			this.setEffectParameters(effectPlugin, parameters);
			
			var effectInfo = null;
			if (effectInfo = this.registerEffectInfo(effectName, element))
			{
				this.assignTimeouts(effectPlugin, effectInfo, callback);
			}
		}
	}
	this.assignTimeouts = function(effectPlugin, effectInfo, callback)
	{
		var timeOutDelay = this.timeOutDelay;
		
		var offsetTimeout = effectInfo.getOffsetTimeout(effectPlugin.effectName);
		var timeoutsArray = effectInfo.getTimeoutList(effectPlugin.effectName);
		
		var olderFrames = timeoutsArray.length;

		var framesCount = effectPlugin.calculateFramesCount();
		
		var currentDelay = offsetTimeout;
		var time = null;
		for (var frame = 1; frame <= framesCount; frame++)
		{
			time = frame;
			
			var currentDelay = offsetTimeout + time * timeOutDelay;
			
			timeoutsArray[currentDelay] = setTimeout(
			function(effectPlugin, time)
			{
				return function(){effectPlugin.renderFrame(time);};
			}(effectPlugin, time), currentDelay);
		}
		if (time < framesCount)
		{
			time = framesCount;
			frame = framesCount;
			var currentDelay = offsetTimeout + time * timeOutDelay;
			
			timeoutsArray[currentDelay] = setTimeout(
			function(effectPlugin, time)
			{
				return function(){effectPlugin.renderFrame(time);};
			}(effectPlugin, time), currentDelay);
			
		}
		
		if (callback)
		{
			var currentDelay  = offsetTimeout + (framesCount +1) * timeOutDelay;
			timeoutsArray[framesCount + 1  + olderFrames] = setTimeout(callback, currentDelay);
		}

		effectInfo.setTimeoutList(timeoutsArray, effectPlugin.effectName);
		effectInfo.calculateEndDate(currentDelay, effectPlugin.effectName);
	}
	this.setEffectParameters = function(effectPlugin, parameters)
	{
		effectPlugin.parameters = new Array();
		if (effectPlugin.defaults)
		{
			effectPlugin.parameters = effectPlugin.defaults;
		}
		for (var index in parameters)
		{
			effectPlugin.parameters[index] = parameters[index];
		}
	}
	this.registerEffectInfo = function(effectName, element)
	{
		if (!element.artWebEffects)
		{
			element.artWebEffects = new effectsInfo();
		}
		element.artWebEffects.register(effectName);
		
		return element.artWebEffects;
	}
	this.getEffectPlugin = function(effectName, element)
	{
		var newEffect = false;
		try
		{
			newEffect = eval('new artWebEffect_'+effectName);
			newEffect.effectName = effectName;
			newEffect.element = element;
		}
		catch(error)
		{
			alert('Effect "'+ effectName +'" load error');
		}
		return newEffect;
	}
	
	this.fps = 50;
	this.timeOutDelay = 1000 / this.fps;
}

function effectsInfo()
{
	this.register = function(effectName)
	{
		if (!this.effects[effectName])
		{
			this.effects[effectName] = new Array();
		}
		if (!this.effects[effectName].timeoutList)
		{
			this.effects[effectName].timeoutList = new Array();
		}
		if (!this.effects[effectName].endDate)
		{
			this.calculateEndDate(0, effectName);
		}
	}
	this.calculateEndDate = function(offsetValue, effectName)
	{
		var offsetDate = new Date();
		
		offsetDate.setTime(parseInt(offsetDate.getTime() + offsetValue));
		
		
		this.effects[effectName].endDate = offsetDate;
	}
	this.getOffsetTimeout = function(effectName)
	{
		var resultOffset = 0;
		var nowDate = new Date();
		var endDate = this.effects[effectName].endDate;
		
		if (nowDate < endDate)
		{
			resultOffset = endDate.getTime() - nowDate.getTime();
		}
		return resultOffset;
	}
	this.getTimeoutList = function(effectName)
	{
		try
		{
			var timeoutList = this.effects[effectName].timeoutList;
		}
		catch(error)
		{
			var timeoutList = false;
		}
		return timeoutList;
	}
	this.setTimeoutList = function(timeoutList, effectName)
	{
		this.effects[effectName].timeoutList = timeoutList;
	}
	this.clearTimeOuts = function(effectName)
	{
		var timeOutsList = this.getTimeoutList(effectName);
		for (var index in timeOutsList)
		{
			clearTimeout(timeOutsList[index]);
		}
		timeOutsList = new Array();
		this.setTimeoutList(timeOutsList, effectName);
		
		this.calculateEndDate(0, effectName);
	}
	
	this.effects = new Array();
}
