function RandomBool()
    return math.random(0, 1)
end

function RandomTableSort(t)
    table_size = table.getn(t)
    for i = 1, table_size, 1 do
        ind1 = math.random(1, table_size)
        ind2 = math.random(1, table_size)
        tmp = t[ind1]
        t[ind1] = t[ind2]
        t[ind2] = tmp
    end
end

function CEntity:Move(dx, dy, time)
    local af = CreateAnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_X, 0.0, self:GetX())
    af:SetKey(_TRACK_Y, 0.0, self:GetY())
    af:SetKey(_TRACK_X, time, self:GetX() + dx)
    af:SetKey(_TRACK_Y, time, self:GetY() + dy)
    af:Play()
end

function CEntity:MoveTo(x, y, time)
    local af = CreateAnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_X, 0.0, self:GetX())
    af:SetKey(_TRACK_Y, 0.0, self:GetY())
    af:SetKey(_TRACK_X, time, x)
    af:SetKey(_TRACK_Y, time, y)
    af:Play()
end

function CEntity:Rotate(dangle, time)
    local af = CreateAnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_A, 0.0, self:GetAngle())
    af:SetKey(_TRACK_A, time, self:GetAngle() + dangle)
    af:Play()
end

function CEntity:ChangeOpacity(start, finish, time)
    local af = CreateAnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_O, 0.0, start)
    af:SetKey(_TRACK_O, time, finish)
    af:Play()
end

function CAutoRegisterEntity:ChangeOpacity(start, finish, time)
    local af = CreateAnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_O, 0.0, start)
    af:SetKey(_TRACK_O, time, finish)
    af:Play()
end

function CreateCloseButton(pos, message, listener)
    local up = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,0,68,29,1,0)
	up:SetHotSpot(17,14);
    local over = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,29,68,29,1,0)
    over:SetHotSpot(17,14);
    local down = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,0,68,29,1,0)
    down:SetHotSpot(17,14);
	local button = CreateButton(up, over, down, message, listener)
	button:AttachTo(parent)
	button:SetX(pos.x)
	button:SetY(pos.y)
	button:SetZ(500)
    return button
end

function CreateOKButton(pos, message, listener)
    local up = CreateAnimation('data/Texture/GUI/Button/button_ok.png',0,0,128,38,1,0)
	up:SetHotSpot(64,19);
    local over = CreateAnimation('data/Texture/GUI/Button/button_ok.png',0,38,128,38,1,0)
    over:SetHotSpot(64,19);
    local down = CreateAnimation('data/Texture/GUI/Button/button_ok.png',0,76,128,38,1,0)
    down:SetHotSpot(64,19);
	local button = CreateButton(up, over, down, message, listener)
	button:AttachTo(parent)
	button:SetX(pos.x)
	button:SetY(pos.y)
	button:SetZ(500)
	
    return button
end

function CreateNextButton(pos, message, listener)
	local button = CreateButton('ButtonNextUp',
								'ButtonNextOver',
								'ButtonNextDown',
								message,
								listener)
	button:AttachTo(play_field)
	button:SetX(pos.x)
	button:SetY(pos.y)
	button:SetZ(220)
	--button:SetRect(-17, -14, 34, 28)
    return button
end

function Vector:__tostring()
    return 'X: '..self.x..' Y: '..self.y
end

function CGameObject:__tostring()
    local str = 'Name: '..self:GetName().." X: "..self:GetX().." Y: "..self:GetY().." Z: "..self:GetZ()
    if self:GetAnimation():GetFrames() > 0 then
        str = str..' NFrames: '..self:GetAnimation():GetFrames()
    end
    str = str..' Color:'..tostring(self:GetAnimation():GetColorStr())
    return str
end

function Task:__tostring()
    return 'Text singular: '..self:GetTextSingular()
end

function GetAnimationLength(anim)
    assert(anim:GetSpeed() ~= 0.)
    return anim:GetFrames() / anim:GetSpeed()
end

function PlayCompositionPeriodicallyVsRandDelay(composition, start_delay, end_delay)
    local duration = composition:GetDuration()
    local time = GetRandomFloat(duration + start_delay, duration + end_delay)
    
    RunComposition = function(composition)
        composition:Rewind(false)
        composition:Play()
        PlayCompositionPeriodicallyVsRandDelay(composition, start_delay, end_delay)
    end
    
    TimerDo(play_field:GetTimer(), time, RunComposition, composition)
end

function PlayCompPeriodicallyVsRandDelayScreen(screen, composition, start_delay, end_delay)
    local duration = composition:GetDuration();
    local time = GetRandomFloat(duration + start_delay, duration + end_delay);
    
    RunComposition = function()
        composition:Rewind(false);
        composition:Play();
        PlayCompPeriodicallyVsRandDelayScreen(screen, composition, start_delay, end_delay);
    end
    
    TimerDo(screen:GetTimer(), time, RunComposition);
end

function PlayAnimationPeriodicallyVsRandDelay(anim_obj, start_delay, end_delay)
    local anim = anim_obj:GetAnimation()
    local duration = GetAnimationLength( anim )
    local time = GetRandomFloat(duration + start_delay, duration + end_delay)
    
    GoAnimation = function()
        anim_obj:SetOpacity(1)
        anim:Play()
        PlayAnimationPeriodicallyVsRandDelay(anim_obj, start_delay, end_delay)
    end
    
    StopAnimation = function()
        anim_obj:SetOpacity(0)
        anim:Stop()
    end
    
    TimerDo(play_field:GetTimer(), time, GoAnimation)
    TimerDo(play_field:GetTimer(), duration, StopAnimation)
end

function CallFunctionPeriodicallyVsRandDelay(call_function, start_delay, end_delay)
    local time = GetRandomFloat(start_delay, end_delay);
    
    RunFunction = function()
        call_function();
        CallFunctionPeriodicallyVsRandDelay(call_function, start_delay, end_delay);
    end
    
    TimerDo(play_field:GetTimer(), time, RunFunction);
end

