local tool_to_set_on_next_update = nil
local ItemHolders = {};
CurrentItemHolder = nil;
ToolsToAddOnInventoryShown = LuaStack:New();

if not game_state then  
    game_state = {}
end
game_state.is_inventory_opened = false

function LoadInventoryData(screen)
	local anim = CreateAnimation('data/Texture/Scenes/Common/area.png',0,0,8,8,1,0);
	anim:SetHotSpot(4,4);
	anim:SetBlendMode(0);
	anim:SetColor('0xFF000000')
	screen:CreateObject('tools_anchor',anim,950,720,270,0,1,1)
	screen:GetObject('tools_anchor'):SetLayer(5);
	screen:SetToolsAnchor(screen:GetObject('tools_anchor'));
end

function InventoryOnSceneLoad(screen)
    screen:SetLayer(5);
end

function InventoryOnUpdate(dt)
    local inv = play_field:GetLevelScreen():GetInventory();
    
    if tool_to_set_on_next_update then
        local info = inv:GetToolInfo(tool_to_set_on_next_update)
        
        info.m_tool:SetVisible(true)
        
        if info.m_icon then
            info.m_icon:SetVisible(false)
        end
        
        game_state.tool = info.m_tool
        game_state.tool:SetLayer(game_state.tool:GetLayer() + 1);
        
        play_field:SetTool(tool_to_set_on_next_update)
    
        tool_to_set_on_next_update = nil
    end
    
    if game_state.tool then
        local mouse_pos = GetMousePos()
        game_state.tool:SetScrXY(mouse_pos.x, mouse_pos.y)
    end
    
    local obj_under_mouse = inv:GetObjectUnderMouse()
    local tool_name       = nil;
    
    if game_state.is_inventory_opened and obj_under_mouse then
        if inv:IsTool(obj_under_mouse)
        then
            tool_name = inv:GetToolName(obj_under_mouse);
        elseif (string.find(obj_under_mouse:GetName(), "ItemHolder"))
        then
            tool_name = GetToolForHolder(obj_under_mouse);
        end
    end
    
    if tool_name
        and not inv:IsToolMoving(tool_name)
        and play_field:GetTool() == ''
        and game_state.ignore_get_tool[tool_name] == nil
    then
        if not game_state.hint_text then
            game_state.hint_text = CreateTextEntity("data/Font/comics.fnt", 'EMPTY')
            game_state.hint_text:AttachTo( play_field:GetLevelScreen():GetInventory() )
            game_state.hint_text:SetTextAlignment(0)
            --game_state.hint_text:Hide();
        end
        
        local ht = game_state.hint_text;
        
        if currentCursor ~= 'CursorActive' then
            SetCursor('CursorActive');
        end
        
        local info = game_state.tools[tool_name]
        
        ht:SetText(GetString(info.hint_text))
        ht:SetLayer(obj_under_mouse:GetLayer() + 1)
        
        local x = math.min(GetMousePos().x + 30., 1024 - ht:GetWidth())
        
        ht:SetXY(x, GetMousePos().y - 17.)
        
        if ht and ht:IsHidden() then
            ht:Show();
        end
    else
        local ht = game_state.hint_text;
        
        if ht and not ht:IsHidden() then
           -- game_state.hint_text = nil;
            
            if currentCursor == 'CursorActive' then
                SetCursor('CursorDefault');
            end
            
            ht:Hide();
        end
    end
end

function InventorySetButtonsEnabled()
end

function DropTool(custom_move_time)
    local inv       = play_field:GetLevelScreen():GetInventory();
    local tool_name = inv:GetToolName(game_state.tool)
    local info      = inv:GetToolInfo(tool_name)
    local move_time = 0.3
    
    game_state.tool:DestroyChildren();
    
    if custom_move_time then
        move_time = custom_move_time
    end
    
    game_state.tool:SetLayer(game_state.tool:GetLayer() - 1);
    
    local holder = GetHolderForTool(tool_name);
    if holder then
        
        local maxZ = 0;
        
        for i, h in ipairs(ItemHolders) do
            if h:GetZ() > maxZ then
                maxZ = h:GetZ();
            end
        end
        
        game_state.tool:SetZ(maxZ + 1.000001);
    end
    
    inv:MoveToolToFreeSlot(tool_name, move_time)
    play_field:SetTool('')
    game_state.tool = nil
    
    if game_state.tools[tool_name].on_drop then
        game_state.tools[tool_name].on_drop(tool_name)
    end
    
    TimerDoString('InventorySetButtonsEnabled()', move_time, inv:GetTimer());
end

function InventoryOnObjectMouseDown(object)
    
    if game_state.tool or not game_state.is_inventory_opened then
        --game_state.tool = nil
        --Log("game_state.tool = nil")
    else
        local inv      = play_field:GetLevelScreen():GetInventory();
        local toolName = nil;
        
        if inv:IsTool(object) then
            toolName = inv:GetToolName(object);
            
        elseif (string.find(object:GetName(), "ItemHolder")) then
            toolName = GetToolForHolder(object);
            
        end
        
        if tutorScreen and (game_state.forcedTool == nil or game_state.forcedTool ~= toolName) then
            return;
        end
        
        if game_state.ignore_get_tool[toolName] then
            toolName = nil;
        end
        
        if toolName
            and play_field:GetTool() == ''
            and not inv:IsToolMoving(toolName)
        then
            tool_to_set_on_next_update = toolName;
            
            if tutorScreen then
                tutorScreen:Hide();
            end
        end
    end

    UpdateComicsRequest()
end

function HideInventory()

    if game_state.is_inventory_opened
    then
        game_state.is_inventory_opened = false;
        
        local inv = play_field:GetLevelScreen():GetInventory();
        inv:SetToolsVisible(false, 0);
        
        for i, holder in ipairs(ItemHolders)
        do
            if holder.fe then
                holder.fe:Destroy();
            end
            
            holder.fe = holder:ChangeOpacity(1, 0, 0.2);
        end
    end
end

function ShowInventory()

    if not game_state.is_inventory_opened
    then
        game_state.is_inventory_opened = true;
        
        local inv = play_field:GetLevelScreen():GetInventory();
        
        while ToolsToAddOnInventoryShown:GetTop()
        do
            toolName = ToolsToAddOnInventoryShown:GetTop();
            ToolsToAddOnInventoryShown:Pop();
            
            local index = game_state.tools[toolName].proposedIndex;
            
            if index == nil then
                index = table.maxn(ItemHolders);
            end
            
            local holder = LoadItemHolder(toolName, index);
            
            local itemPosition = inv:GetToolPosition(index);
            local anchorPos    = inv:GetAnchorPosition();
            
            holder:SetX(itemPosition.x + anchorPos.x);
        end
        
        
        inv:SetToolsVisible(true, 0);
        
        for i, holder in ipairs(ItemHolders)
        do
            if holder.fe then
                holder.fe:Destroy();
            end
            
            holder.fe = holder:ChangeOpacity(0, 1, 0.2);
        end
    end
end

function InventoryOnButtonPress(title)
end

function PlayItemsPassingMechanismAnimation()

    local panel = play_field:GetLevelScreen():GetPanel();
    panel:GetObject('mechanism'):GetAnimation():Play();
    panel:GetObject('WheelRight'):GetAnimation():Play();
    TimerDoString("play_field:GetLevelScreen():GetPanel():GetObject('WheelRight'):GetAnimation():Stop();",
                  0.6, play_field:GetTimer());
end

function ClearHoldersList()
    local inv  = play_field:GetLevelScreen():GetInventory();
    
    for i, h in ipairs(ItemHolders)
    do
        if h.toolName then
            local toolObj = inv:GetToolInfo(h.toolName).m_tool
            toolObj:Detach();
        end
        
        h:DestroyChildren();
        
        local objName = h:GetName();
        if (inv:HasObject(objName)) then
            inv:DeleteObject(objName);
        end
    end

    ItemHolders = {};
end

function ReloadInventoryContent()

    ClearHoldersList();
    
    local inventory     = play_field:GetLevelScreen():GetInventory();
    local itemsCount    = inventory:GetToolsCount();
    local anchorPos     = inventory:GetAnchorPosition();
    local holder        = nil;
    local itemPosition  = nil;
    local toolName      = nil;
    
    for i=0, itemsCount-1
    do
        toolName = inventory:GetToolName(i);
        
        if not game_state.tools[toolName].notInInventoryYet
        then
            holder       = LoadItemHolder(toolName, i);
            itemPosition = inventory:GetToolPosition(i);
            
            holder:SetX(itemPosition.x + anchorPos.x);
        else
            game_state.tools[toolName].proposedIndex = i;
        end
        
        local tool = inventory:GetToolInfo(toolName).m_tool;
        
        if game_state.ignore_get_tool[toolName] then
            tool:SetVisible(false);
        else
            tool:SetVisible(true);
        end
    end
end

local invItemsCnt = 0; -- temp

function LoadItemHolder(toolName, posIndex)
    local anim = CreateAnimation('data/Texture/GUI/Inventory/item_holder_simple.png',0,0,110,108,1,0)
	anim:SetHotSpot(52,51)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	
	local inventory  = play_field:GetLevelScreen():GetInventory();
	local itemHolder = inventory:CreateObject('ItemHolderSimple'..invItemsCnt,anim,0,0,220 - posIndex * 2,0,1,1)
        
    invItemsCnt = invItemsCnt + 1;
    
    if toolName
        and not inventory:IsToolMoving(toolName)
        and ( (game_state.tool == nil) or (toolName ~= inventory:GetToolName(game_state.tool)) )
    then
        local tool = inventory:GetToolInfo(toolName).m_tool;
        
        tool:DestroyChildren();
        tool:AttachTo(itemHolder);
        tool:SetXY(0, 0);
        tool:SetLayer(itemHolder:GetLayer())
        tool:SetZ(1);
        tool:SetOpacity(1.);
        tool:SetVisible(true);
        tool:Show();
    end
    
    local anchorPos = inventory:GetAnchorPosition();
    
    itemHolder:SetXY(anchorPos.x, anchorPos.y);
    itemHolder.toolName = toolName;
    ItemHolders[posIndex + 1] = itemHolder;
    
    return itemHolder;
end

function GetHolderForTool(toolName)

    for i, h in ipairs(ItemHolders)
    do
        if (h.toolName == toolName)
        then
            return h;
        end
    end
    
    return nil;
end

function GetToolForHolder(holder)

    for i, h in ipairs(ItemHolders)
    do
        if (h:GetName() == holder:GetName())
        then
            return h.toolName;
        end
    end
    
    return nil;

end

function CreateEffectorItemHolderAppearing(posIndex)

    local inventory    = play_field:GetLevelScreen():GetInventory();
    local itemPosition = inventory:GetToolPosition(posIndex);
    local anchorPos    = inventory:GetAnchorPosition();
    
    local effector = CreateAnimationEffector();
    
    effector:SetKey(_TRACK_X, 0.04166666666667, anchorPos.x);
    effector:SetKey(_TRACK_X, 0.16666666666667, itemPosition.x + anchorPos.x - 10);
    effector:SetKey(_TRACK_X, 0.375, itemPosition.x + anchorPos.x);
    
    return effector;
end

function CreateEffectorItemHolderDissapearing(posIndex)

    local inventory    = play_field:GetLevelScreen():GetInventory();
    local itemPosition = inventory:GetToolPosition(posIndex);
    local anchorPos    = inventory:GetAnchorPosition();
    
    local effector = CreateAnimationEffector();
    effector:SetKey(_TRACK_X, 0.25, itemPosition.x + anchorPos.x);
    effector:SetKey(_TRACK_X, 0.33333333333333, itemPosition.x + anchorPos.x - 10);
    effector:SetKey(_TRACK_X, 0.5, anchorPos.x);
    effector:SetKey(_TRACK_O, 0.49, 1);
    effector:SetKey(_TRACK_O, 0.5, 0);
    
    return effector;
end

function CreateEffectorItemHolderSlideLeft(posIndex)

    local result = CreateAnimationEffector();
    -- todo
    return result;
end

function CreateEffectorItemHolderSlideRight(posIndex, baseIndex)

    local effector = CreateAnimationEffector();
    
    local inventory    = play_field:GetLevelScreen():GetInventory();
    local itemPosition = inventory:GetToolPosition(posIndex);
    local posToSlideTo = inventory:GetToolPosition(posIndex - 1);
    local anchorPos    = inventory:GetAnchorPosition();
    
    local timeShift = (posIndex - baseIndex - 1) * 0.05;
    
    effector:SetKey(_TRACK_X, 0.375 + timeShift, itemPosition.x + anchorPos.x);
    effector:SetKey(_TRACK_X, 0.5 + timeShift, posToSlideTo.x + anchorPos.x);
    
    -- todo
    return effector;
    
end

function InventoryOnToolApplied(toolName)
    local inventory     = play_field:GetLevelScreen():GetInventory();
    local holderIndex   = nil;
    local currentHolder = nil;
    
    for i, holder in ipairs(ItemHolders)
    do
        if holder.toolName == toolName
        then
            holderIndex   = i;  
            currentHolder = holder;
            break;
        end
    end
    if not holderIndex then return end;
    
    local eff = CreateEffectorItemHolderDissapearing(holderIndex - 1);
    eff:AttachTo(currentHolder);
    eff:Play();
    ItemHolders[holderIndex] = nil;
    
    for i = holderIndex, table.maxn(ItemHolders) - 1
    do
        ItemHolders[i] = ItemHolders[i + 1];
        ItemHolders[i + 1] = nil;
        
        local effector = CreateEffectorItemHolderSlideRight(i, holderIndex - 1);
        effector:AttachTo(ItemHolders[i]);
        effector:Play();
    end
    
    CurrentItemHolder = currentHolder;
    TimerDoString("CurrentItemHolder:Destroy()", 0.5, inventory:GetTimer());

    PlayItemsPassingMechanismAnimation();
end

function InventoryOnToolFound(toolName)
    
    game_state.tools[toolName].notInInventoryYet = nil;
    --[[
    if toolName == 'E_tile3' then
        CustomToolApply('E_tile3');
        
        local newToolName = 'E_tile1';
        
        if not HasGameState('ToolFound', newToolName) then
            AddGameState('ToolFound', newToolName)
            AddGameState('ToolInfoShown', newToolName)
            AddTool(newToolName);
            InventoryOnToolFound(newToolName);
        end
    else
    --]]
        if not game_state.is_inventory_opened
        then
            ToolsToAddOnInventoryShown:Push(toolName);
            return;
        end
        
        local itemIndex = game_state.tools[toolName].proposedIndex
        
        if not itemIndex then
            itemIndex = table.maxn(ItemHolders);
        end
        
        local itemHolder = LoadItemHolder(toolName, itemIndex);
        
        local eff = CreateEffectorItemHolderAppearing(itemIndex);
        eff:AttachTo(itemHolder);
        eff:Play();
        
        PlayItemsPassingMechanismAnimation();
  --  end
end

function ReattachToolToInventory(toolName)

    local inventory = play_field:GetLevelScreen():GetInventory();
    local tool      = inventory:GetToolInfo(toolName).m_tool;
    
    local currentHolder = nil;
    for i, holder in ipairs(ItemHolders)
    do
        if holder.toolName == toolName
        then
            currentHolder = holder;
            break;
        end
    end
    
    if currentHolder then
        tool:DestroyChildren();
        tool:AttachTo(currentHolder);
        tool:SetXY(0, 0);
        tool:SetZ(1);
        tool:SetLayer(currentHolder:GetLayer())
        tool:SetVisible(true);
    else
        tool:SetVisible(false);
    end
end

function SetToolHidden(toolName)
    game_state.ignore_get_tool[toolName] = true;
    
    local inventory = play_field:GetLevelScreen():GetInventory();
    
    if inventory:IsTool(toolName) then
        local tool = inventory:GetToolInfo(toolName).m_tool;
        
        if tool then
            tool:SetVisible(false);
        end
    end
end

-- CLEAR_ON_SAVE_BEGIN
-- Do not edit code listed below (generated by the editor on each save)
function LoadData(screen)
end

function FreeData(screen)
end
-- CLEAR_ON_SAVE_END
