------------------------------------------------------------------------------
class 'AnimationBundle'

function AnimationBundle:__init(loadingRoutine)
	self.loadingRoutine = loadingRoutine
	self.nextAnimationDelay = 0.0
	self.animations = loadingRoutine()
	self.enabledAnimations = {}
	
	self:EnableAnimation()
end

function AnimationBundle:UpdatePeriodicAnimations(dt, period)
	assert(self.animations and 
		   (type(period) == 'number' or (type(period) == 'table' and #period == 2)))
	local minPeriod = (type(period) == 'number' and period or period[1])
	local maxPeriod = (type(period) == 'number' and period or period[2])
	assert(minPeriod <= maxPeriod)

	if (self.nextAnimationDelay == 0.0) then
		local periodicAnimations = {}

		for compositionName, composition in pairs(self.animations) do
			if (composition:IsCyclic() == false and composition:IsPaused() == true and self:IsAnimationEnabled(compositionName)) then
				table.insert(periodicAnimations, composition:GetName())
			end
		end
        if (#periodicAnimations > 0) then
		    local animName = periodicAnimations[math.random(1, #periodicAnimations)]

    		self:PlayAnimation(animName)
			self.nextAnimationDelay = math.random(minPeriod, maxPeriod)
            return animName;
        end
	else
		self.nextAnimationDelay = (self.nextAnimationDelay - dt >= 0.0 and self.nextAnimationDelay - dt or 0.0)
	end
	return nil
end

function AnimationBundle:GetAnimation(animationName)
	local animation = self.animations[animationName]
	assert(animation)
	return animation
end

function AnimationBundle:GetAnimationDuration(animationName)
    local animation = self:GetAnimation(animationName)
    
    return animation:GetDuration()
end

function AnimationBundle:PlayAnimation(animationName)
	local animation= self:GetAnimation(animationName)

	animation:SetVisible(true);
	animation:Play();
end

function AnimationBundle:StopAnimation(animationName)
	local animation= self:GetAnimation(animationName);

	animation:SetVisible(false);
	animation:Stop();
end

function AnimationBundle:IsAnimationEnabled(animationName)
    return (self.enabledAnimations[animationName] ~= nil);
end

function AnimationBundle:EnableAnimation(...)
    if (#{...} == 0) then
        for animName,_ in pairs(self.animations) do
            self.enabledAnimations[animName] = true;
        end   
    else
        for _,animName in ipairs({...}) do
            self.enabledAnimations[animName] = true;
        end
    end
end

function AnimationBundle:DisableAnimation(...)
    if (#{...} == 0) then
        self.enabledAnimations = {};
    else
        for _,animName in ipairs({...}) do
            self.enabledAnimations[animName] = nil;
        end
    end
end

function AnimationBundle:Destroy()
     for Name, Anim in pairs(self.animations) do
         Anim:Destroy()
     end
     
     self.animations = {}
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function CreateCompositionLoader(compositionRoutine, name, x, y, z, hotSpotX,hotSpotY, isCyclic, speed)
    assert(compositionRoutine and name and z)
	speed = speed or 1.0

	local Loader = function (parent)
		assert(parent);

	    local element = compositionRoutine()
	    element:SetName(name)
	    element:SetHotSpot(hotSpotX,hotSpotY)
	    element:SetXY(x, y)
	    element:SetZ(z)
	    element:AttachTo(parent)

	    element:SetScaleX(1)
	    element:SetScaleY(1)
	    element:SetAngle(0)
	    element:SetOpacity(1)
    
	    if isCyclic == true then
	        element:SetCyclic(true)
		else
			element:SetDestroysOnEnd(false)
	    end
		element:Stop()
	    element:SetVisible(false)
		if (parent.SetClippingRect) then
		    element:AssignClippingRect(parent)
		end
		element:SetConsiderParentOpacity(true)
		element:SetSpeed(speed)

		return name, element
	end
	return Loader;
end

function CreateAnimationLoadingRoutine(parent,
									   resourceFolder,
									   compositionsLoaders,	--  {routine1(parent), routin2(parent), ...}
									   elementsAdjusters)	--	{routine1(element,textureName), routine2(element,textureName), ...}
	assert(resourceFolder and compositionsLoaders)
	
	local origCreateCompositionElement = nil
	local compositionElementCreator = function (resourceName)
		assert(origCreateCompositionElement)
		local element = origCreateCompositionElement(resourceName)
		local fileName      = ExtractFileName(resourceName)
		local fileExt       = ExtractFileExtention(resourceName)
		local textureName   = fileName..'.'..fileExt
	    --local textureName   = string.sub(resourceName, string.len(resourceFolder) + 1);

		if elementsAdjusters then
			for _,adjuster in pairs(elementsAdjusters) do
				adjuster(element, textureName)
			end
		end
		return element
	end
	local loadingRoutine = function ()
		local compositions = {};
		assert(type(compositionsLoaders) == 'table' and #compositionsLoaders > 0);

		do
		    origCreateCompositionElement = CreateCompositionElement;
			CreateCompositionElement = compositionElementCreator;

			for _,loader in pairs(compositionsLoaders) do
				local compositionName, composition = loader(parent);
				compositions[compositionName] = composition;
			end

		    CreateCompositionElement = origCreateCompositionElement;
		    origCreateCompositionElement = nil;
		end
		return compositions;
	end
	return loadingRoutine;
end

