function OnSceneLoad(screen)
    LoadData(screen)
    
    g_screen = screen
    g_timer = screen:GetTimer()
    
    SetContinueMode(1)                     -- в этой миниигре будет работать кнопка "continue"
        
    OBJECTS_AMOUNT = 16
    Objects = {}
    for i = 1, OBJECTS_AMOUNT do
        CreateObjectInArray(i)
    end 
    
    Slots = {}
    for i = 1, OBJECTS_AMOUNT do
        Slots[i] = {}
        Slots[i].Pos = Vector(Objects[i].Entity:GetX(), Objects[i].Entity:GetY())
    end 
    margin = 70 -- margin window boder when drag
    delta = 30  -- +/- area to match slot
    top_z = 100 + 2 * OBJECTS_AMOUNT -- max object's z-order
    
    ShuffleNotes()
end

function ShuffleNotes()
    math.randomseed(os.clock())
    math.random()
    for i = 1, OBJECTS_AMOUNT do
        Objects[i].AngleIndex = math.random(4)
        Objects[i].Entity:SetAngle(M_PI_OVER_2 * (Objects[i].AngleIndex - 1))
        local x = math.random(margin, 1024 - margin)
        local y = math.random(margin, 768 - margin)
        Objects[i].Entity:SetXY(x, y)
    end
end

function CreateObjectInArray(index)
    Objects[index] = {}
    Objects[index].RightIndex = index
    Objects[index].Entity = g_screen:GetObject('Piece_'..index)
    Objects[index].Entity:SetZ(100 + OBJECTS_AMOUNT + index)
    Objects[index].AngleIndex = 1   -- no rotation
    Objects[index].Inplace = false
    Objects[index].Lock = false
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 CorrectAfterRotation(index, orig_hot_x, orig_hot_y, orig_mouse_x, orig_mouse_y, orig_drag_x, orig_drag_y)
    local rot_anim = Objects[index].Entity:GetAnimation();
    rot_anim:SetHotSpot(orig_hot_x, orig_hot_y);    -- restore hot spot
    
    local angle = -M_PI_OVER_2; -- angel that rotation occur
    
    -- calc rotated delta to set proper XY object coords
    local delta_x = orig_drag_x * math.cos(angle) - orig_drag_y * math.sin(angle);
    local delta_y = orig_drag_x * math.sin(angle) + orig_drag_y * math.cos(angle);
    Objects[index].Entity:SetXY(Objects[index].Entity:GetX() + delta_x, Objects[index].Entity:GetY() + delta_y);
    
    if DragObject then
        -- if we still dragging object set new DragDeltaXY
        DragDeltaX = orig_mouse_x - DragObject.Entity:GetX()
        DragDeltaY = orig_mouse_y - DragObject.Entity:GetY()
    end
    UnlockObject(index);    -- now we can unlock object
end

function RotateNote(obj)
    local rot_time = 0.15;
    local orig_hot_x;
    local orig_hot_y;
    -- rotation implemntation during dragging in mouse point hot spot position
    if DragObject then
        local rot_anim = DragObject.Entity:GetAnimation();
        orig_hot_x = rot_anim:GetHotX();    -- save original hot spot
        orig_hot_y = rot_anim:GetHotY();
        
        local angle = -DragObject.Entity:GetAngle();    -- get angle to unwind to 0 angle to proper calculate new hot spot

        local delta_x = DragDeltaX * math.cos(angle) - DragDeltaY * math.sin(angle);    -- calc drag delta if as sprite wasn't
        local delta_y = DragDeltaX * math.sin(angle) + DragDeltaY * math.cos(angle);    -- rotate. (Rotate DragDelta point. Pivot - original hot spot)
        
        local targ_hot_x = orig_hot_x + delta_x;    -- new hot spot
        local targ_hot_y = orig_hot_y + delta_y;       
        
        rot_anim:SetHotSpot(targ_hot_x, targ_hot_y);
        DragObject.Entity:SetXY(DragObject.Entity:GetX() + DragDeltaX, DragObject.Entity:GetY() + DragDeltaY);  -- Correct sprite pos due to hot spot changed
    end

    obj.Entity:Rotate(M_PI_OVER_2, rot_time)    -- rotate regardless hot spot change or not
    
    if DragObject then  -- after rotation while dragging - restore hot spot
        -- transfer to func original values
        -- DragObject.Entity:GetXY() - transfer original mouse pos
        TimerDo(g_timer, rot_time, CorrectAfterRotation, DragObject.RightIndex, orig_hot_x, orig_hot_y, DragObject.Entity:GetX(), DragObject.Entity:GetY(), DragDeltaX, DragDeltaY);
    end
    
    obj.Lock = true
    if not DragObject then  -- If dragging unlock in CorrectAfterRotation func
        TimerDoString('UnlockObject('.. obj.RightIndex ..')', rot_time, g_timer)
        TimerDoString('IsInplace(' .. obj.RightIndex .. ')', rot_time, g_timer) -- must check only when not dragging, when drag perform check in Stop Drag
    end
    obj.AngleIndex = obj.AngleIndex + 1
    if obj.AngleIndex == 5 then
        obj.AngleIndex = 1
    end
end

function UnlockObject(index)
    Objects[index].Lock = false
end

function OnSceneFree()
    FreeData()
end

function OnScreenShown()
end

function ShowMiniGameHelp()
    CreateDialogMiniGameHelp('MINI_GAME_HELP_PUZZLE_MEMORIAL')
end

function OnUpdate(dt)
    UpdateDrag()
end

function OnLose()
end

function OnExit()
end

function OnObjectMouseEnter(object)
    DefaultOnObjectMouseEnter(object)
end

function OnObjectMouseLeave(object)
    DefaultOnObjectMouseLeave(object)
end

function StartDrag(obj)
    DragObject = obj
    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 and not DragObject.Lock 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 then
            mouse_x = 1024 - margin
        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
        IsInplace(DragObject.RightIndex)
    
        DragObject = nil
        DragDeltaX = nil
        DragDeltaY = nil
    end
end

function IsInplace(index)
    if Objects[index].AngleIndex == 1 then
        local delta_x = Slots[Objects[index].RightIndex].Pos.x - Objects[index].Entity:GetX()
        local delta_y = Slots[Objects[index].RightIndex].Pos.y - Objects[index].Entity:GetY()
        if math.abs(delta_x) < delta and math.abs(delta_y) < delta then
            Objects[index].Entity:Move(delta_x, delta_y, 0.2)
            Objects[index].Inplace = true
            Objects[index].Entity:SetZ(100 + Objects[index].RightIndex)
            Objects[index].Entity:GetAnimation():SetColor('0xFFFFFFFF')
            TimerDoString('IsCompleted()', 0.2, g_timer)
        end
    end
end

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

function OnSkipMiniGame()
    if game_state.minigame_complete then
        return
    end
    
    for i = 1, OBJECTS_AMOUNT do
        Objects[i].Entity:Rotate(-(Objects[i].AngleIndex - 1) * M_PI_OVER_2, 1)
        Objects[i].Lock = true
        local delta_x = Slots[Objects[i].RightIndex].Pos.x - Objects[i].Entity:GetX()
        local delta_y = Slots[Objects[i].RightIndex].Pos.y - Objects[i].Entity:GetY()
        Objects[i].Entity:Move(delta_x, delta_y, 1)
        TimerDoString('Objects[' .. i .. '].Entity:GetAnimation():SetColor("0xFFFFFFFF")', 1, g_timer)
        Objects[i].Inplace = true
    end
    
    MiniGameCompleted(1.0)
end

function OnObjectMouseDown(object)
    obj_name = object:GetName()
    local pf = play_field
    local is_wrong_click = true
    
    obj = GetObjectByName(obj_name)
    if obj and obj_name ~= 'background' and not obj.Inplace and not obj.Lock and not game_state.minigame_complete then
        StartDrag(obj)
    end
    
    return is_wrong_click
end

function OnObjectMouseUp(object)
    StopDrag()
end

function OnObjectRightMouseDown(object)
    obj_name = object:GetName()
    
    obj = GetObjectByName(obj_name)
    if obj and not obj.Inplace and not obj.Lock then
        RotateNote(obj)
    end    
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(phone_screen_center_pos)
	DefaultOnPhotographing(phone_screen_center_pos);
end

function OnButtonPress(title)
    DefaultMinigameOnButtonPress(title)
end

function OnMouseMove(previous_pos, current_pos)
end

function OnSetTool(tool)
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/2_Prow_Puzzle/background.jpg',0,0,1024,768,1,0)
	anim:SetHotSpot(512,384)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('background',anim,512,384,95,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_1.png',0,0,272,227,1,0)
	anim:SetHotSpot(136,113)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_1',anim,204,244,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_2.png',0,0,227,176,1,0)
	anim:SetHotSpot(113,88)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_2',anim,382,237,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_3.png',0,0,235,195,1,0)
	anim:SetHotSpot(117,97)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_3',anim,489,197,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_4.png',0,0,328,230,1,0)
	anim:SetHotSpot(164,115)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_4',anim,654,212,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_5.png',0,0,233,176,1,0)
	anim:SetHotSpot(116,88)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_5',anim,222,319,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_6.png',0,0,282,244,1,0)
	anim:SetHotSpot(141,122)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_6',anim,383,357,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_7.png',0,0,325,230,1,0)
	anim:SetHotSpot(162,115)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_7',anim,551,284,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_8.png',0,0,254,249,1,0)
	anim:SetHotSpot(127,124)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_8',anim,713,308,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_9.png',0,0,285,341,1,0)
	anim:SetHotSpot(142,170)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_9',anim,249,456,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_10.png',0,0,205,309,1,0)
	anim:SetHotSpot(102,154)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_10',anim,442,461,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_11.png',0,0,357,252,1,0)
	anim:SetHotSpot(178,126)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_11',anim,587,381,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_12.png',0,0,463,388,1,0)
	anim:SetHotSpot(231,194)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_12',anim,392,573,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_13.png',0,0,346,349,1,0)
	anim:SetHotSpot(173,174)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_13',anim,564,574,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_14.png',0,0,254,338,1,0)
	anim:SetHotSpot(127,169)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_14',anim,616,500,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_15.png',0,0,372,232,1,0)
	anim:SetHotSpot(186,116)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_15',anim,773,582,100,0,1,1)
	local anim = CreateAnimation('data/Texture/Minigames/2_Prow_Puzzle/Piece_16.png',0,0,454,481,1,0)
	anim:SetHotSpot(227,240)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('Piece_16',anim,796,457,100,0,1,1)
end

function FreeData(screen)
end
-- CLEAR_ON_SAVE_END
