function OnSceneLoad(screen)
    LoadData(screen)

    local pf = play_field
    local level = pf:GetLevelScreen()
    custom_cursors = {}
    locked_objects = {}
    
    g_screen = screen;
    g_timer = screen:GetTimer()
    
    SetContinueMode(2)                                              -- миниигру нужно заканчивать вручную
    
    screen:GetObject('lighter_take'):SetVisible(false) 
    screen:GetObject('lighter_blink'):SetVisible(false) 
    margin = 30 -- margin window boder when drag
    margin_right = 270;
    delta = 50  -- +/- area to match slot
    
    shester_anim = screen:GetObject('shester1'):GetAnimation();
    shester_anim:Stop();
    shester_anim:SetMode(0);    -- HGE needs that
    door_anim = screen:GetObject('door'):GetAnimation();
    door_anim:Stop();
    door_anim:SetMode(0);
    
    screen:IgnoreOnTestPoint('lighter_take')
    screen:IgnoreOnTestPoint('lighter_blink')
    top_z = 120.0           -- Max z-order of gears
	
	CreateObjects();
	ShuffleGears();
	
	gear_sound = MakeSoundEntity("05_mg_gear_rotate")
	gear_sound:AttachTo(screen)
	gear_sound:Play(true)
end

function CreateObjects()
    OBJECTS_AMOUNT = 9;
    Objects = {};
    for i = 0, OBJECTS_AMOUNT do
        Objects[i] = {};
        Objects[i].Index = i;
        Objects[i].Entity = g_screen:GetObject('gear_' .. i);
        Objects[i].RightPos = Vector(Objects[i].Entity:GetScrX(), Objects[i].Entity:GetScrY());
        Objects[i].Rivet = g_screen:GetObject('A_' .. i);   -- Set visible only when gear inplace
        Objects[i].Rivet:SetScrXY(Objects[i].RightPos.x, Objects[i].RightPos.y);
        Objects[i].Rivet:SetVisible(false)
        Objects[i].Inplace = false;
        Objects[i].Effector = CreateEffector(Objects[i]);
    end
    Objects[0].Inplace = true;  -- inital moving gear
    Objects[0].Effector:Play();
end

function ShuffleGears()
    math.randomseed(os.clock())
    math.random()
    for i = 1, OBJECTS_AMOUNT do
        local x = math.random(margin, 1024 - margin_right)
        local y = math.random(margin, 768 - margin)
        Objects[i].Entity:SetXY(x, y)
        Objects[i].Entity:SetZ(120  - i);
    end
end

function CreateEffector(obj)
    local ef = CreateAnimationEffector();
    ef:AttachTo(obj.Entity);
    ef:SetMode(_ANIM_LOOP);
    local angle = M_TWO_PI;
    if obj.Index % 2 ~= 0 then   -- odd gears rotate anticlockwise
        angle = - angle;
    end
        
    toothes = {[0] = 64, 36, 25, 32, 12, 25, 28, 19, 32, 15}
    local div = 8;
    local time = toothes[obj.Index] / div;  -- time rotation proportional to toothes amount
    
    ef:SetKey(_TRACK_A, 0, obj.Entity:GetAngle())
    ef:SetKey(_TRACK_A, time, obj.Entity:GetAngle() + angle)
    
    return ef;
end

function GetObjectByName(obj_name)
    for i = 1, OBJECTS_AMOUNT do
        if obj_name == Objects[i].Entity:GetName() then
            return Objects[i]
        end
    end
    
    return nil
end

function IsInplace()
    local ret = false
    for i = 1, OBJECTS_AMOUNT do 
        obj = Objects[i]
        if Objects[i-1].Inplace and not obj.Inplace then                 -- do only if previous gear inplace
            local delta_x = obj.RightPos.x - obj.Entity:GetX()
            local delta_y = obj.RightPos.y - obj.Entity:GetY()
            if math.abs(delta_x) < delta and math.abs(delta_y) < delta then
                obj.Entity:Move(delta_x, delta_y, 0.2)
                obj.Inplace = true
                obj.Entity:SetZ(100 + obj.Index)
                TimerDoString('Objects['..i..'].Rivet:SetVisible(true)', 0.2, g_timer)
                TimerDoString('Objects['..i..'].Effector:Play()', 0.2, g_timer)
                TimerDoString('IsCompleted()', 0.2, g_timer)
                PlaySound('05_mg_gear_set')
                ret = true
            end
        end
    end
    return ret
end

function IsCompleted()
    for i = 1, OBJECTS_AMOUNT do
        if not Objects[i].Inplace then
            return false
        end
    end
    
    PlayFinalAnimation()
    return true
end

function PlayFinalAnimation()
    local time = 2
    g_screen:GetObject('strip'):Move(0, -500, time)
    PlaySound('05_mg_open')
    
    door_anim:Play()
    shester_anim:Play()
    
    g_screen:GetObject('lighter_blink'):SetOpacity(0.0)
    g_screen:GetObject('lighter_take'):SetVisible(true)
    g_screen:GetObject('lighter_blink'):SetVisible(true)
    TimerDoString("g_screen:DoNotIgnoreOnTestPoint('lighter_take')", 2.3, g_timer)
    -- TODO Blink
    local fin_anim = CreateAnimationEffector()
    fin_anim:AttachTo(g_screen:GetObject("lighter_blink"))
    fin_anim:SetMode(_ANIM_FWD)
    
    local time = 2.0
    fin_anim:SetKey(_TRACK_O, time+0, 0)
    fin_anim:SetKey(_TRACK_O, time+0.4, 1)
    fin_anim:SetKey(_TRACK_O, time+0.8, 0)
    fin_anim:SetKey(_TRACK_O, time+1.2, 1)
    fin_anim:SetKey(_TRACK_O, time+1.6, 0)
    fin_anim:Play()
            
    MiniGameCompleted()
end
------------------------------------------------------------------------
-- Drag functions
function StartDrag(obj)
    DragObject = obj
    --DragObject.Entity:SetZ(120 + DragObject.Index);
    top_z = top_z + 1
    DragObject.Entity:SetZ(top_z);
    DragDeltaX = GetMousePos().x - DragObject.Entity:GetX()
    DragDeltaY = GetMousePos().y - DragObject.Entity:GetY()
end

function UpdateDrag()
    if DragObject then
        local mouse_x = GetMousePos().x - DragDeltaX
        local mouse_y = GetMousePos().y - DragDeltaY
        if mouse_x < margin then
            mouse_x = margin
        elseif mouse_x > 1024 - margin_right then
            mouse_x = 1024 - margin_right
        end
        if mouse_y < margin then
            mouse_y = margin
        elseif mouse_y > 768 - margin then
            mouse_y = 768 - margin
        end
        DragObject.Entity:SetXY(mouse_x, mouse_y)
    end
end

function StopDrag()
    if DragObject then
        if not IsInplace(DragObject) then
            -- Decrease z-orders
            local next_z = 101.0
            local objs = {}
            for i = 1, OBJECTS_AMOUNT do
                objs[i] = Objects[i]
            end
            for i = 1, OBJECTS_AMOUNT do
                local min = i
                for j = i, OBJECTS_AMOUNT do
                    if i ~= j and objs[j].Inplace == false then
                        local j_z = objs[j].Entity:GetZ()
                        local min_z = objs[min].Entity:GetZ()
                        if (j_z < min_z) and (j_z >= next_z) then
                            min = j
                        end
                    end
                end
                objs[min].Entity:SetZ(next_z)
                if i ~= min then
                    local swap = {}
                    swap = objs[i]
                    objs[i] = objs[min]
                    objs[min] = swap
                end
                next_z = next_z + 1
            end
            top_z = 120.0    
        end
            
        DragObject = nil
        DragDeltaX = nil
        DragDeltaY = nil
    end
end
------------------------------------------------------------------------
function OnSceneFree()
    FreeData()
end

function OnScreenShown()
end

function ShowMiniGameHelp() 
    CreateDialogMiniGameHelp('MINI_GAME_HELP_GEAR')
end

function OnUpdate(dt)
    DefaultOnUpdate(dt);
    if not game_state.minigame_complete then
        UpdateDrag();
    end
end

function OnLose()
end

function OnExit()
end

function OnObjectMouseEnter(object)
    DefaultOnObjectMouseEnter(object)
end

function OnObjectMouseLeave(object)
    DefaultOnObjectMouseLeave(object)
end

function OnObjectMouseDown(object)
    obj_name = object:GetName()
    local pf = play_field
    local is_wrong_click = true

--  is_wrong_click = DefaultOnObjectMouseDown(object);
    
    obj = GetObjectByName(obj_name)
    if not game_state.minigame_complete then
        if obj and not obj.Inplace then
            StartDrag(obj)
        end
    else
        if obj_name == 'lighter_take' then
            g_screen:GetObject('lighter_blink'):Hide()
            g_screen:IgnoreOnTestPoint('lighter_take')
            local ef = CreateAnimationEffector();
            ef:AttachTo(object)
            ef:SetMode(_ANIM_FWD)
                
            ef:SetKey(_TRACK_O, 0, object:GetOpacity())
            ef:SetKey(_TRACK_O, 0.75, 0)
                                
            ef:Play()
            TimerDo(g_timer, 0.8, OnCompletedGame)
        end
    end
    
    return is_wrong_click;
end

function OnObjectMouseUp(object)
    if not game_state.minigame_complete and DragObject then
        StopDrag();
    end
end

function OnObjectRightMouseDown(object)
end

function OnObjectRightMouseUp(object)
end

function OnObjectFound(object)
end

function OnToolFound(tool)
end

function OnToolApply(tool, object)
    DefaultOnToolApply(tool, object);
end

function OnObjectReachPanel(object)
end

function OnPhotographing()
	DefaultOnPhotographing();
end

function OnSkipMiniGame()
    if game_state.minigame_complete then
        return
    end
    
    for i = 1, OBJECTS_AMOUNT do
        if not Objects[i].Inplace then
            local delta_x = Objects[i].RightPos.x - Objects[i].Entity:GetX()
            local delta_y = Objects[i].RightPos.y - Objects[i].Entity:GetY()
            Objects[i].Entity:Move(delta_x, delta_y, 1)
            Objects[i].Inplace = true
            Objects[i].Entity:SetZ(100 + i)
            TimerDoString('Objects['.. i ..'].Rivet:SetVisible(true)', 1, g_timer)
            TimerDoString('Objects['.. i ..'].Effector:Play()', 1, g_timer)
        end
    end
    TimerDo(g_timer, 1.0, PlayFinalAnimation) 
end

function OnButtonPress(title)
    DefaultMinigameOnButtonPress(title)
end

function OnMouseMove(previous_pos, current_pos)
end

function OnSetTool(tool)
end

function OnMinigameCompleted()
end

function OnLostFocus()
    DefaultMinigameOnLostFocus()
end

function OnGainFocus()
    DefaultMinigameOnGainFocus()
end

-- CLEAR_ON_SAVE_BEGIN
-- Do not edit code listed below (generated by the editor on each save)
function LoadData(screen)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/2n.dds',0,0,1024,768,1,0)
	anim:SetHotSpot(512,384)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('cover',anim,512,384,150,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/5n.dds',0,0,192,428,1,0)
	anim:SetHotSpot(96,214)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('rust',anim,906,265,140,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/background.jpg',0,0,783,721,1,0)
	anim:SetHotSpot(391,360)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('background',anim,408,377,99,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/door.dds',0,0,247,419,21,10)
	anim:SetHotSpot(124,212)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('door',anim,899,263,151,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/shester1.DDS',0,0,148,102,21,10)
	anim:SetHotSpot(74,51)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('shester1',anim,740,727,130,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/zazhigalka.png',0,0,103,174,1,0)
	anim:SetHotSpot(51,87)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('lighter_take',anim,904,282,145,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/zazhigalka.png',0,0,103,174,1,0)
	anim:SetHotSpot(51,87)
	anim:SetBlendMode(0)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('lighter_blink',anim,904,282,146,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/strip.png',0,0,91,1537,1,0)
	anim:SetHotSpot(45,768)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('strip',anim,788,195,125,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_0.png',0,0,462,462,1,0)
	anim:SetHotSpot(231,231)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_0',anim,146,778,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_0.png',0,0,128,128,1,0)
	anim:SetHotSpot(64,64)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_0',anim,146,778,101,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_1.png',0,0,283,284,1,0)
	anim:SetHotSpot(141,142)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_1',anim,202,438,101,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_1.png',0,0,64,64,1,0)
	anim:SetHotSpot(32,32)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_1',anim,202,441,102,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_2.png',0,0,199,197,1,0)
	anim:SetHotSpot(99,98)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_2',anim,110,244,102,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_2.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_2',anim,110,245,103,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_3.png',0,0,241,242,1,0)
	anim:SetHotSpot(120,121)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_3',anim,288,155,103,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_3.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_3',anim,290,155,104,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_4.png',0,0,109,109,1,0)
	anim:SetHotSpot(54,54)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_4',anim,434,94,104,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_4.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_4',anim,435,93,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_5.png',0,0,225,225,1,0)
	anim:SetHotSpot(112,112)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_5',anim,554,183,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_5.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_5',anim,556,183,106,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_6.png',0,0,225,225,1,0)
	anim:SetHotSpot(112,112)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_6',anim,459,362,106,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_1.png',0,0,64,64,1,0)
	anim:SetHotSpot(32,32)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_6',anim,460,364,107,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_7.png',0,0,149,149,1,0)
	anim:SetHotSpot(74,74)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_7',anim,421,526,107,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_7.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_7',anim,422,527,108,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_8.png',0,0,237,238,1,0)
	anim:SetHotSpot(118,119)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_8',anim,577,603,108,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_8.png',0,0,64,64,1,0)
	anim:SetHotSpot(32,32)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_8',anim,577,604,109,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/gear_9.png',0,0,136,135,1,0)
	anim:SetHotSpot(68,67)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('gear_9',anim,694,483,109,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/6_rock_skull_day_gear/A_9.png',0,0,32,32,1,0)
	anim:SetHotSpot(16,16)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('A_9',anim,695,485,110,0,1,1)
end

function FreeData(screen)
end
-- CLEAR_ON_SAVE_END
