-- Items to use
-- 14_bearing 16_key

function OnSceneLoad(screen)
    LoadData(screen)
    DefaultOnSceneLoad('data/Scenes/minigames/16_lock.lua', 'quest', 'data/Scenes/16_Doctor_Main.lua')
    
    game_state.mini_game_finished = false
    play_field:IgnoreOnTestPoint('L3_wire')  
    
    zaklepka = play_field:GetObject('L6_zaklepka')
    -------------------------------------------------------------------------
    SLOTS_AMOUNT = 8
    Slots = {}
    for i = 1, 3 do
        Slots[i] = {}
        Slots[i].Pos = Vector(zaklepka:GetX() - 100 - (3 - i) * 66, zaklepka:GetY() - 128)
        Slots[i].free = true
    end
    Slots[4] = {}
    Slots[4].Pos = Vector(zaklepka:GetX(), zaklepka:GetY() - 128)
    Slots[4].free = true;
    for i = 5, 7 do
        Slots[i] = {}
        Slots[i].Pos = Vector(zaklepka:GetX() + 105 + (i - 5) * 66, zaklepka:GetY() - 128)
        Slots[i].free = true
    end
    Slots[8] = {}
    Slots[8].Pos = Vector(zaklepka:GetX(), zaklepka:GetY() - 63)
    Slots[8].free = true;
    -------------------------------------------------------------------------
    OBJECTS_AMOUNT = 4
    Objects = {}
    -- silver balls
    for i = 1, 2 do
        Objects[i] = {}
        Objects[i].Entity = play_field:GetObject('L2_podshipnik_1_' .. i)
        Objects[i].slot_index = i
        Objects[i].Entity:SetXY(Slots[i].Pos.x, Slots[i].Pos.y)
        Slots[i].free = false
    end
    -- gold balls
    for i = 3, 4 do
        Objects[i] = {}
        Objects[i].Entity = play_field:GetObject('L2_podshipnik_2_' .. i - 2)
        Objects[i].slot_index = i + 3
        Objects[i].Entity:SetXY(Slots[i + 3].Pos.x, Slots[i + 3].Pos.y)
        Slots[i + 3].free = false
    end
    
    InitScene()
    
    play_field:GetObject('area_keyhole'):SetVisible(false);
    play_field:GetObject('key'):SetOpacity(0);
    play_field:GetObject('L2_podshipnik_2_1' ):SetOpacity(0);
    
    RegisterToolApplyInfo('14_bearing', 'area_bearing_apply', nil, nil, function(tool_name)
                                                                            game_state.bearing_applied = true;
                                                                            
                                                                            play_field:GetObject('area_bearing_apply'):SetVisible(false);
                                                                            play_field:GetObject('L2_podshipnik_2_1' ):ChangeOpacity(0, 1, 0.2);
                                                                            
                                                                            PlaySound('16_PlacePart')
                                                                            
                                                                            game_state.level_mode = 'mini_game';
                                                                            play_field:GetLevelScreen():GetPanel():SetMode(PM_MINIGAME)
                                                                            
                                                                            ShowMonolog('C_16_LOCK_APPLY_BEARING_HINT', 'C_16_LOCK_APPLY_BEARING_HINT')
                                                                        end,
                                                                        function(tool_name)
                                                                            game_state.bearing_applied = true;
                                                                            
                                                                            play_field:GetObject('area_bearing_apply'):SetVisible(false);
                                                                            play_field:GetObject('L2_podshipnik_2_1' ):SetOpacity(1);
                                                                            
                                                                            if not CheckAddBearingsPlaced() then
                                                                                game_state.level_mode = 'mini_game';
                                                                                play_field:GetLevelScreen():GetPanel():SetMode(PM_MINIGAME)
                                                                                
                                                                                ShowMonolog('C_16_LOCK_APPLY_BEARING_HINT', 'C_16_LOCK_APPLY_BEARING_HINT')
                                                                            end
                                                                        end);
                                                                        
    RegisterToolApplyInfo('16_key', 'area_keyhole', nil, nil,           function(tool_name)
                                                                            play_field:GetObject('area_keyhole'):SetVisible(false);
                                                                            play_field:GetObject('key'):ChangeOpacity(0, 1, 0.5);
                                                                            
                                                                            game_state.key_applied = true;
                                                                            
                                                                            PlaySound('16_PlaceKey')
                                                                        end,
                                                                        function(tool_name)
                                                                            play_field:GetObject('area_keyhole'):SetVisible(false);
                                                                            play_field:GetObject('key'):SetOpacity(1);
                                                                            
                                                                            game_state.key_applied = true;
                                                                        end);
    RegisterActiveObject('key', function(obj_name)
                                    RotateKey(1)
                                    TimerDoString("RegisterCompleteMiniGame()", 1, play_field:GetTimer());
                                end,
                                function(obj_name)
                                    play_field:GetObject('key'):SetAngle( play_field:GetObject('key'):GetAngle() + M_PI);
                                    
                                    TimerDoString("RegisterCompleteMiniGame()", 1, play_field:GetTimer());
                                end);
    
    if not game_state.bearing_applied then
        ShowMonolog('C_16_LOCK_NEED_BEARING_HINT', 'C_16_LOCK_NEED_BEARING_HINT');
    elseif game_state.mini_game_finished and not game_state.key_applied then
        ShowMonolog('C_16_LOCK_NEED_KEY_HINT', 'C_16_LOCK_NEED_KEY_HINT');
    end
end

function CheckAddBearingsPlaced()
    if HasGameState('ActionCompleted', game_state.scene_path.."(AddBearingsPlaced)") then
        for i = 1, 4 do
            Objects[i].Entity:SetOpacity(0)
        end
        
        local scoba = play_field:GetObject('L5_skoba')
        local angle = scoba:GetAngle() - M_PI + M_PI_OVER_4 + M_PI_OVER_4 / 2
        scoba:SetAngle(angle)
        
        scoba = play_field:GetObject('L4_skoba')
        angle = scoba:GetAngle() + M_PI - M_PI_OVER_4 - M_PI_OVER_4 / 2
        scoba:SetAngle(angle)
        
        play_field:GetObject('L3_wire'):SetVisible(false);
        play_field:GetObject('area_keyhole'):SetVisible(true);
        
        game_state.mini_game_finished = true;
        
        return true;
    end
    
    return false;
end

function RotateKey(time)
    local key = play_field:GetObject('key')
    
    local eff = CreateAnimationEffector();
    eff:AttachTo( key )
    eff:SetMode(_ANIM_FWD + _ANIM_NOLOOP);
    
    eff:SetKey(_TRACK_A, 0,        key:GetAngle());
    eff:SetKey(_TRACK_A, time*0.9, key:GetAngle() + 182/180 * M_PI);
    eff:SetKey(_TRACK_A, time,     key:GetAngle() + M_PI);
    eff:Play();
    
    PlaySound('16_RotateKey');
end

function OnAllBearingsPlaced()
   -- game_state.level_mode = 'quest';
   -- play_field:GetLevelScreen():GetPanel():SetMode(PM_QUEST)
    
    play_field:GetObject('area_keyhole'):SetVisible(true);
end

function InitScene()
    for i = 1, 2 do
        if HasGameState(game_state.scene_path .. i) then
            local idx = tonumber(GetGameState(game_state.scene_path .. i):Get(0))
            RemoveGameState(game_state.scene_path .. i)
            Slots[i].free = true
            Slots[idx].free = false
            Objects[i].slot_index = idx
            Objects[i].Entity:SetXY(Slots[idx].Pos.x, Slots[idx].Pos.y)
        end
    end
    for i = 3, 4 do
        if HasGameState(game_state.scene_path .. i) then
            local idx = tonumber(GetGameState(game_state.scene_path .. i):Get(0))
            RemoveGameState(game_state.scene_path .. i)
            Slots[i + 3].free = true
            Slots[idx].free = false
            Objects[i].slot_index = idx
            Objects[i].Entity:SetXY(Slots[idx].Pos.x, Slots[idx].Pos.y)
        end
    end
end

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

function IsCompleted()
    for i = 1, 2 do
        if Objects[i].slot_index < 6 or Objects[i].slot_index > 7 then
            return false
        end
    end
    for i = 3, 4 do
        if Objects[i].slot_index > 2 then
            return false
        end
    end
    return true
end

function SkipMiniGame()
    UpdateComicsRequest();
    OnCompleteMiniGame();
end

function StartDrag(obj)
    DragObject = obj
    game_state.custom_cursors[DragObject.Entity:GetName()] = 'CursorHand';
    game_state.ignore_on_highlight[DragObject.Entity:GetName()] = true;
--    DragObject.Entity:SetZ(130)
    
    left = Slots[1].Pos.x
    right = Slots[7].Pos.x
    top = Slots[1].Pos.y - 5
    
    local index = DragObject.slot_index
    
    if index == 8 then
        index = 4
        
        if not Slots[4].free then
            top = Slots[8].Pos.y
            left = Slots[8].Pos.x - 5;
            right = Slots[8].Pos.x + 5;
            Slots[DragObject.slot_index].free = true
            return;
        end
    end
    
    for i = index - 1, 1, -1 do
        if not Slots[i].free then
            left = Slots[i + 1].Pos.x
            break
        end
    end
    for i = index + 1, 7 do
        if not Slots[i].free then
            right = Slots[i - 1].Pos.x
            break
        end
    end
    Slots[DragObject.slot_index].free = true
    
    game_state.disable_default_zoom_exit = true
    
    PlaySound('16_MG_Get')
end

function UpdateDrag()
    if DragObject then
        DragObject.Entity:SetXY(GetMousePos().x, GetMousePos().y)
        
        if DragObject.Entity:GetY() < top then
            DragObject.Entity:SetY(top)
        end
        
        if DragObject.Entity:GetX() < left then
            DragObject.Entity:SetX(left)
        elseif DragObject.Entity:GetX() > right then
            DragObject.Entity:SetX(right)
        end
        
        if DragObject.Entity:GetY() > Slots[4].Pos.y then
            if DragObject.Entity:GetX() > Slots[8].Pos.x - 10 and DragObject.Entity:GetX() < Slots[8].Pos.x + 10 and Slots[8].free then
                if DragObject.Entity:GetY() > Slots[8].Pos.y then
                    DragObject.Entity:SetY(Slots[8].Pos.y)
                end
            else
                DragObject.Entity:SetY(Slots[4].Pos.y)
            end
        end
        
        if DragObject.Entity:GetY() <= Slots[4].Pos.y then
            if DragObject.Entity:GetX() < left then
                DragObject.Entity:SetX(left)
            elseif DragObject.Entity:GetX() > right then
                DragObject.Entity:SetX(right)
            end
        else
            if DragObject.Entity:GetX() < Slots[8].Pos.x - 10 then
                DragObject.Entity:SetX(Slots[8].Pos.x - 10)
            elseif DragObject.Entity:GetX() > Slots[8].Pos.x + 10 then
                DragObject.Entity:SetX(Slots[8].Pos.x + 10)
            end
        end
    end
end

function StopDrag()
    if DragObject then
        
        PlaySound('16_MG_Get')
        
        game_state.custom_cursors[DragObject.Entity:GetName()] = nil;
        game_state.ignore_on_highlight[DragObject.Entity:GetName()] = nil;
        for i = 1, SLOTS_AMOUNT do
            local delta = 33
            if i == 4 then
                delta = 75
            end
            if math.abs(DragObject.Entity:GetX() - Slots[i].Pos.x) < delta then
                if i == 4 and Slots[8].free then
                    i = 8
                    if DragObject.Entity:GetX() - Slots[i].Pos.x > 10 then
                          DragObject.Entity:SetXY(Slots[i].Pos.x + 10, DragObject.Entity:GetY())
                    elseif Slots[i].Pos.x - DragObject.Entity:GetX() > 10 then
                          DragObject.Entity:SetXY(Slots[i].Pos.x  - 10, DragObject.Entity:GetY())
                    end
                end
                DragObject.Entity:Move(Slots[i].Pos.x - DragObject.Entity:GetX(), Slots[i].Pos.y - DragObject.Entity:GetY(), 0.2)
                Slots[i].free = false
                DragObject.slot_index = i
                break
            end
        end
        DragObject = nil
        
        if IsCompleted() then
            OnCompleteMiniGame()
        end
    end
    
    game_state.disable_default_zoom_exit = false
end

function OnCompleteMiniGame()
    game_state.level_mode = 'quest';
    play_field:GetLevelScreen():GetPanel():SetMode(PM_QUEST)
    
    play_field:TimerDoString("ShowMonolog('C_16_LOCK_NEED_KEY_HINT', 'C_16_LOCK_NEED_KEY_HINT')", 0.3)
    
    FinishGame()
end

function FinishGame()
    for i = 1, 4 do
        Objects[i].Entity:ChangeOpacity(1, 0, 0.4)
    end
    
    PlayOutro()
    game_state.mini_game_finished = true;
    AddGameState('ActionCompleted', game_state.scene_path.."(AddBearingsPlaced)");
    
    TimerDoString('OnAllBearingsPlaced()', 2, play_field:GetTimer())
end

function CreatePlayEffector(obj, angle1, time1, angle2, time2)
    local eff = CreateAnimationEffector()
    eff:AttachTo(obj)
    eff:SetMode(_ANIM_FWD)
        
    eff:SetKey(_TRACK_A, 0, obj:GetAngle())
    eff:SetKey(_TRACK_A, time1, obj:GetAngle() + angle1)
    eff:SetKey(_TRACK_A, time1 + time2, obj:GetAngle() + angle1 + angle2)
    eff:Play()
end

function PlayOutro()

    PlaySound('16_MG_LockOpen');
    
    local scoba = play_field:GetObject('L5_skoba')
    CreatePlayEffector(scoba, -M_PI + M_PI_OVER_4, 0.8, M_PI_OVER_4 / 2, 0.2)
    scoba = play_field:GetObject('L4_skoba')
    CreatePlayEffector(scoba, M_PI - M_PI_OVER_4, 0.8, -M_PI_OVER_4 / 2, 0.3)
    do
        local obj = play_field:GetObject('L3_wire')
        local eff = CreateAnimationEffector()
        eff:AttachTo(obj)
        eff:SetMode(_ANIM_FWD)
            
        eff:SetKey(_TRACK_X, 0, obj:GetX())
        eff:SetKey(_TRACK_X, 1.5, obj:GetX() + 100)
        eff:SetKey(_TRACK_Y, 0, obj:GetX())
        eff:SetKey(_TRACK_Y, 1.5, obj:GetX() + 900)
        eff:SetKey(_TRACK_A, 0, obj:GetAngle())
        eff:SetKey(_TRACK_A, 1.5, obj:GetAngle() + M_PI_OVER_2)
        eff:Play()
    end
end

function RegisterCompleteMiniGame()
    if not HasGameState('MiniGameCompleted', '16_lock') then
        AddGameState('MiniGameCompleted', '16_lock');
    end
    if not HasGameState('ClosedScene', game_state.scene_path) then
        AddGameState('ClosedScene', game_state.scene_path);
    end
    StartLevel(game_state.parent_scene);
--    StartLevel(game_state.scene_path);
end

function OnSceneFree(screen)
    DefaultOnSceneFree()
    FreeData(screen)
end

function OnUpdate(dt)
    DefaultOnUpdate(dt)
    UpdateDrag()
end

function OnAllItemsFound()
    DefaultOnAllItemsFound()
end

function OnLose()
    DefaultOnLose()
end

function OnExit()
    DefaultOnExit()
end

function OnClose()
    DefaultOnClose()
end

function OnObjectMouseEnter(object)
    DefaultOnObjectMouseEnter(object)
end

function OnObjectMouseLeave(object)
    DefaultOnObjectMouseLeave(object)
end

function OnObjectMouseDown(object)
    local is_wrong_click = not DefaultOnObjectMouseDown(object)
    local obj_name = object:GetName()
    local pf = play_field
    
    if (obj_name == "area_keyhole" or obj_name == "area_bearing_apply") and not game_state.bearing_applied then
        ShowMonolog('C_16_LOCK_NEED_BEARING_HINT', 'C_16_LOCK_NEED_BEARING_HINT');
        return;
    end
    
    if obj_name == "area_keyhole" and game_state.mini_game_finished and not game_state.key_applied then
        ShowMonolog('C_16_LOCK_NEED_KEY_HINT', 'C_16_LOCK_NEED_KEY_HINT');
    end
    
    local obj = GetObjectByName(obj_name)
    
    if obj then
        StartDrag(obj)
    end

    DefaultOnObjectMouseDownProcessed(is_wrong_click);
end

function OnObjectMouseUp(object)
    DefaultOnObjectMouseUp(object)
    StopDrag()
end

function OnObjectFound(object)
    DefaultOnObjectFound(object)
end

function OnToolFound(tool)
    DefaultOnToolFound(tool)
end

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

function OnObjectReachPanel(object)
    DefaultOnObjectReachPanel(object)
end

function OnButtonPress(title)
    DefaultOnButtonPress(title)
end

function OnMouseMove(previous_pos, current_pos)
    DefaultOnMouseMove(previous_pos, current_pos)
end

function OnSetTool(tool)
    DefaultOnSetTool(tool)
end

function LevelLoaded(level)
end

function OnSceneDestroy(playfield)
    DefaultOnSceneDestroy(playfield)
    
    if not game_state.mini_game_finished then
        for i = 1, OBJECTS_AMOUNT do
            AddGameState(game_state.scene_path .. i, tostring(Objects[i].slot_index))
        end
    end
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/16_lock/Background.jpg',0,0,1024,768,1,0)
	anim:SetHotSpot(512,384)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Background',anim,512,384,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L2_podshipnik.png',0,0,79,80,1,0)
	anim:SetHotSpot(39,40)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L2_podshipnik_1_1',anim,205,361,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L2_podshipnik.png',0,0,79,80,1,0)
	anim:SetHotSpot(39,40)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L2_podshipnik_1_2',anim,273,362,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L2_podshipnik_2.png',0,0,79,80,1,0)
	anim:SetHotSpot(39,40)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L2_podshipnik_2_2',anim,676,361,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L2_podshipnik_2.png',0,0,79,80,1,0)
	anim:SetHotSpot(39,40)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L2_podshipnik_2_1',anim,608,362,105,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L3_wire.png',0,0,559,43,1,0)
	anim:SetHotSpot(279,21)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L3_wire',anim,441,381,110,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L4_skoba.png',0,0,312,218,1,0)
	anim:SetHotSpot(24,191)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L4_skoba',anim,439,487,110,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L5_skoba.png',0,0,313,229,1,0)
	anim:SetHotSpot(293,201)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L5_skoba',anim,441,486,111,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/L6_zaklepka.png',0,0,39,40,1,0)
	anim:SetHotSpot(19,20)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('L6_zaklepka',anim,438,491,115,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/16_lock/key.png',0,0,105,636,1,0)
	anim:SetHotSpot(52,318)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('key',anim,445,216,120,0,0.7,0.7)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area_circle.png',0,0,128,128,1,0)
	anim:SetHotSpot(64,64)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_bearing_apply',anim,598,358,130,0,1.5,1.5)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area_circle.png',0,0,128,128,1,0)
	anim:SetHotSpot(64,64)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_keyhole',anim,439,269,130,0,3,4)
end

function FreeData(screen)
end
-- CLEAR_ON_SAVE_END
