--------------------------------------------------------------------------------
INVENTORY_LAYER         = 2
TOOL_IN_INVENTORY_Z		= 2900;

local DROP_MOVE_TIME            = 0.3
local SLIDE_TIME                = 0.6
local OPEN_TIME                 = 0.3
local SHAKE_CELL_TIME           = 0.7

local SHAKE_CELL_MAX_POWER      = 10

local TOOL_NAME_TEXT_OFFSET_X   = 30
local TOOL_NAME_TEXT_OFFSET_Y   = -10
local TOOL_NAME_TEXT_Z		    = 1300

local TOOL_SCALE_IN_INVENTORY   = 0.9

local ROOT_SHOW_POSITION        = {x=0, y=0}
local ROOT_SLIDE_POSITION       = {x=0, y=70}
local ROOT_HIDE_POSITION        = {x=0; y=128}

local SLIDE_INV_TIME            = 0.4
local SLIDE_INV_DELAY           = 1

local START_ANCHOR_POS          = {x=242 + 32, y=700 + 32}
local VISIBLE_CELLS_COUNT       = 7
local CELLS_WIDTH               = 550 / VISIBLE_CELLS_COUNT --89

--------------------------------------------------------------------------------
class 'CInventory' (BaseScreen)

function CInventory:__init(name, screen)
	BaseScreen.__init(self, name, screen)
	
	screen:GetObject('fade'):Hide()
	
    screen:SetLayer(INVENTORY_LAYER)
    
    self.active_tools   = {}
    self.cells          = {}
    self.locked_tools   = {}
    self.flying_tools   = {}
    
    self.anchor         = nil
	self.anchorAux      = nil
    
    self.slideEff       = nil
    self.slideEffAux    = nil
    
    self.slideAction    = nil
    self.slideActionAux = nil
    
    self.anchor_col     = 0
    self.anchor_colAux  = self.anchor_col;
    
    self.cells_free_id  = 0
    self.cell_counter   = 0
    self.isOpen         = true
    self.slidingAnchor  = nil
    
    self.btn_left       = nil
    self.btn_right      = nil
    self.btn_lock       = nil
    self.btn_unlock     = nil
    
    self.tool_to_set    = nil
    self.tool           = nil
    
    self.hintText       = nil
    self.hintTextMaxX   = SCR_W
    self.hintedTool     = nil
    
    self.opened  = false
    self.sliding = false
    self.bSlidedUp = false
    self.fadeEff = nil
    
    self.toolsBlocker = FlagHolder:New()
    
    self:CreateContent(screen)
end
--------------------------------------------------------------------------------

function CInventory:CreateContent(screen)
	screen:IgnoreOnTestPoint('fade')
	local fade = screen:GetObject('fade')
	fade:SetOpacity(0.)
	
	-- Root
	self.root = CreateAutoRegisterEntity()
	self.root:AttachTo( screen )
	self.root:SetScrXY(ROOT_SHOW_POSITION.x, ROOT_SHOW_POSITION.y)
	self.root:SetZ(0)
	
	-- Anchors
	self.anchor    = screen:GetObject('tools_anchor')
	self.anchorAux = screen:GetObject('tools_anchorAux')
	
    self.anchor:SetXY(START_ANCHOR_POS.x + self.anchor_col*CELLS_WIDTH, START_ANCHOR_POS.y)
    self.anchor:SetOpacity(1.)
    self.anchor:AttachTo( self.root )
	
	self.anchorAux:SetXY(START_ANCHOR_POS.x + self.anchor_colAux*CELLS_WIDTH, START_ANCHOR_POS.y)
	self.anchorAux:SetOpacity(1.)
	self.anchorAux:AttachTo( self.root )
	
	screen:IgnoreOnTestPoint('tools_anchor')
	screen:IgnoreOnTestPoint('tools_anchorAux')
	
	-- lock button background
	do
	    local lockObject = screen:GetObject('bttn_inventory_lock')
	    
	    local anim   = CreateAnimationByTextureName('data/Texture/Common/area.png')
	    local scaleX = lockObject:GetAnimation():GetWidth()  * lockObject:GetScaleX() / anim:GetWidth()
	    local scaleY = lockObject:GetAnimation():GetHeight() * lockObject:GetScaleY() / anim:GetHeight()
	    local x      = lockObject:GetX()
	    local y      = lockObject:GetY()
	    local z      = lockObject:GetZ()
	    
	    anim:SetColor('0x01FFFFFF')
	    local object = screen:CreateObject('LockButtonBack', anim, x, y, z, 0, scaleX, scaleY)
	end
	
	-- Attach
	Helpers.AttachInPlace(screen:GetObject('LockButtonBack'),        self.root)
	Helpers.AttachInPlace(screen:GetObject('bttn_inventory_left'),   self.root)
	Helpers.AttachInPlace(screen:GetObject('bttn_inventory_right'),  self.root)
	Helpers.AttachInPlace(screen:GetObject('bttn_inventory_lock'),   self.root)
	Helpers.AttachInPlace(screen:GetObject('bttn_inventory_unlock'), self.root)
	Helpers.AttachInPlace(screen:GetObject('area_LButtonOver'),      self.root)
	Helpers.AttachInPlace(screen:GetObject('area_RButtonOver'),      self.root)
	
	
	-- Buttons
	self.btn_left   = self:CreateButton('bttn_inventory_left',   'InventoryLeft' )
    self.btn_right  = self:CreateButton('bttn_inventory_right',  'InventoryRight')
    self.btn_lock   = self:CreateButton('bttn_inventory_lock',   'InventoryLock')
    self.btn_unlock = self:CreateButton('bttn_inventory_unlock', 'InventoryUnlock')
    
    self.btn_lock:SetAction('OnLockButtonClick', self)
    self.btn_unlock:SetAction('OnUnlockButtonClick', self)
    
    self.btn_lock:SetActionSound("Inventory_lock")
    self.btn_unlock:SetActionSound("Inventory_lock")
    
    if GetCurrentLevel() and HasGameState('InventoryLocked') then
        self.btn_lock:Hide()
    else
        self.btn_unlock:Hide()
    end
    
    -- Hint text
    self.hintText = CreateTextEntity(INVENTORY_FONT, 'EMPTY')
    self.hintText:SetScale(1)
    self.hintText:AttachTo(screen)
    self.hintText:SetTextAlignment(0)
    self.hintText:SetVisible(false)
    self.hintText:SetZ(TOOL_NAME_TEXT_Z)
    
    -- Cells
    for i=1, VISIBLE_CELLS_COUNT do
        self:CreateCell()
    end
    
    -- Panel
    screen:GetObject('inventory_panel'    ):AttachTo( self.root )
    screen:GetObject('inventory_frame'    ):AttachTo( self.root )
    screen:GetObject('inventory_title_txt'):AttachTo( self.root )
    
	screen:IgnoreOnTestPoint('inventory_title_txt')
    
    self.root:SetScrXY(ROOT_SLIDE_POSITION.x, ROOT_SLIDE_POSITION.y)
end
--------------------------------------------------------------------------------

function CInventory:AddTool(name, info)
    local tool = info.tool
    local icon = info.icon
	self:IgnoreOnTestPoint(tool:GetName())
	self:IgnoreOnTestPoint(icon:GetName())
	
    tool:SetScale(TOOL_SCALE_IN_INVENTORY)
	icon:SetScale(TOOL_SCALE_IN_INVENTORY)
    
    icon:SetVisible(false)
	tool:SetVisible(true)

	self.active_tools[name] = info
	self:MoveToolToFreeSlot(name, 0)
end
--------------------------------------------------------------------------------

function CInventory:TakeTool(name)
    local info = self:GetToolInfo(name)
    
    play_field:SetTool(name)
    
    self.tool = info.tool
    self.tool:AttachTo(self.screen)
    self.tool:SetClippingRect(0, 0, SCR_W, SCR_H)
    info.icon:SetVisible(true)
    
    if info.on_get then
        local event = {}
        event.toolName = name
        info.on_get(event)
    end

    local eff = CreateAnimationEffector()
    eff:AttachTo( self.tool )
    eff:SetMode(_ANIM_LOOP)
    eff:SetKey(_TRACK_S, 0,    TOOL_SCALE_IN_INVENTORY)
    eff:SetKey(_TRACK_S, 0.65, TOOL_SCALE_IN_INVENTORY + 0.1)
    eff:SetKey(_TRACK_S, 1.,   TOOL_SCALE_IN_INVENTORY)
    eff:Play()
    
    GetCurrentLevel():OnDefaultSetTool(name)
end
--------------------------------------------------------------------------------

function CInventory:GetTool()
    return self.tool
end
--------------------------------------------------------------------------------

function CInventory:DropTool(custom_move_time)
    if self.tool == nil then
        return
    end
    
    local time = custom_move_time or DROP_MOVE_TIME
    local name = self:GetToolName(self.tool)
	
	self.tool:DestroyChildren()
    self.tool:SetScale(TOOL_SCALE_IN_INVENTORY)
    self.tool = nil
    play_field:SetTool('')
	
    self:MoveToolToFreeSlot(name, time)
    
    SetCursor('CursorDefault')
    
    local level = GetCurrentLevel()
    if level.tools[name].on_drop then
        local event    = {}
        event.toolName = name
        
        level.tools[name].on_drop(event)
    end
end
--------------------------------------------------------------------------------

function CInventory:RemoveTool(name)
    local info = self:GetToolInfo(name)
    
    if self.tool and (self.tool:GetName() == info.tool:GetName()) then
        local fadeTime = 0.2;
        local obj      = self.tool
        
        self.tool:ChangeOpacity(1., 0., fadeTime)
        self.tool = nil
        play_field:SetTool('')
        
        self.timer:Add( function()
                            self.screen:DeleteObject(obj:GetName())
                        end,
                        fadeTime)
    else
        self.screen:DeleteObject(info.tool:GetName())
    end
    
    self.active_tools[name] = nil
    self:RemoveCell(name)
end
--------------------------------------------------------------------------------

function CInventory:MoveToolToFreeSlot(name, time)
	assert(self:IsTool(name))
	local info     = self:GetToolInfo(name)
	local cellInfo = self:GetCellInfoByToolName(name)
	
	if not cellInfo then
    	cellInfo = self:CreateCell(name)
    	
    	info.icon:AttachTo(cellInfo.cell)
        info.icon:SetZ(1)
        info.icon:SetXY(0, 0)
        info.icon:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
        info.tool:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
	end
	
    local cell = cellInfo.cell
    info.tool:SetScrZ(cell:GetScrZ() + 10)
    
    self.flying_tools[name] = true
    
	if time == 0 then
	    info.tool:SetScrXY(cell:GetScrX(),cell:GetScrY())
		self:OnToolMoveToInventoryFinish(name, cell)
	else
	    local eff = info.tool:MoveTo(cell:GetScrX(), cell:GetScrY(), time)
	    --[[
	    local dx = cell:GetScrX() - info.tool:GetScrX()
	    local dy = cell:GetScrY() - info.tool:GetScrY()
	    local powerCoef = math.sqrt(dx*dx + dy*dy)/SCR_W
	    local angle     = math.atan2(dx, dy)
	    ]]
		self.timer:Add( function()
                            self:OnToolMoveToInventoryFinish(name, cell)
                            --self:ShakeCell(cell, angle, powerCoef)
                        end,
                        time)
	end
end
--------------------------------------------------------------------------------
function CInventory:RotateTargetCell(name, is_animation)
    local info = self:GetCellInfoByToolName(name)
    if info then
        if is_animation then
            info.cell:GetAnimation():SetMode(HGEANIM_FWD + HGEANIM_NOLOOP)
            info.cell:GetAnimation():Play()
        else
            info.cell:GetAnimation():Rewind(true)
        end
    end
end
--------------------------------------------------------------------------------
function CInventory:OnToolMoveToInventoryFinish(name, target_cell)
    self.flying_tools[name] = nil
	
	local info = self:GetToolInfo(name)
	local tool = info.tool
	
	tool:DestroyChildren()
	tool:AttachTo(target_cell)
	tool:SetZ(2)
	tool:SetXY(0, 0)
	tool:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
	
	if self:IsLockedTool(name) then
	    tool:SetVisible(false)
	    info.icon:SetVisible(true)
	else
        tool:SetVisible(true)
        info.icon:SetVisible(false)
    end
end
--------------------------------------------------------------------------------

function CInventory:ShakeCell(cell, angle, powerCoef)
    local power = SHAKE_CELL_MAX_POWER * powerCoef
    local dx    = power * math.sin(angle)
    local dy    = power * math.cos(angle)
    local cellX = cell:GetX()
    local cellY = cell:GetY()
    
    local eff = CreateAnimationEffector()
    eff:AttachTo(cell)
    eff:SetDestroysOnEnd(true)
    eff:SetKey(_TRACK_X, 0,                     cellX)
    eff:SetKey(_TRACK_X, SHAKE_CELL_TIME * 0.2, cellX + dx)
    eff:SetKey(_TRACK_X, SHAKE_CELL_TIME * 0.7, cellX - dx/2)
    eff:SetKey(_TRACK_X, SHAKE_CELL_TIME,       cellX)
    eff:SetKey(_TRACK_Y, 0,                     cellY)
    eff:SetKey(_TRACK_Y, SHAKE_CELL_TIME * 0.2, cellY + dy)
    eff:SetKey(_TRACK_Y, SHAKE_CELL_TIME * 0.7, cellY - dy/2)
    eff:SetKey(_TRACK_Y, SHAKE_CELL_TIME,       cellY)
    eff:Play()
end
--------------------------------------------------------------------------------

function CInventory:OnToolFound(toolName)
    self.active_tools[toolName].notInInventoryYet = nil
    
    local info      = self:GetToolInfo(toolName)
    local cellIndex = self:GetCellIndexByToolName(toolName)
    
    info.tool:SetVisible(true)
    
    local level = GetCurrentLevel()
    
    if level.tools[toolName].bDogTarget then
        self:MarkDogCell(toolName)
        level:GetPanelLuaObject():SetActiveDogState(true)
    end
    
    self:CheckSlideBtnsEnable()
end
--------------------------------------------------------------------------------

function CInventory:IsTool(obj)
    assert(obj)
    
	if type(obj) == 'string' then
		return self.active_tools[obj] ~= nil
	else
		for i, info in pairs(self.active_tools) do			
			if info.tool:GetName() == obj:GetName() then
				return true
			end
		end
		
		return false
	end
end
--------------------------------------------------------------------------------

function CInventory:GetToolInfo(name)
	assert(self:IsTool(name))
	return self.active_tools[name]
end
--------------------------------------------------------------------------------

function CInventory:GetToolName(obj)
	assert(self:IsTool(obj))

	for name, info in pairs(self.active_tools) do					
		if info.tool:GetName() == obj:GetName() then
			return name
		end
	end

	return nil;
end
--------------------------------------------------------------------------------

function CInventory:GetToolObject(tool_name)
    return self.active_tools[tool_name].tool;
end
--------------------------------------------------------------------------------

function CInventory:LockTool(tool_name)
    self.locked_tools[tool_name] = true
    
    if not self:IsFlyingTool(tool_name) then
        local info = self:GetToolInfo(tool_name)
        
        info.tool:SetVisible(false)
        info.icon:SetVisible(true)
    end
end
--------------------------------------------------------------------------------

function CInventory:UnlockTool(tool_name)
    self.locked_tools[tool_name] = nil
    
    if not self:IsFlyingTool(tool_name) then
        local info = self:GetToolInfo(tool_name)
        
        info.tool:SetVisible(true)
        info.icon:SetVisible(false)
    end
end
--------------------------------------------------------------------------------

function CInventory:IsLockedTool(tool_name)
    return (self.locked_tools[tool_name] == true)
end
--------------------------------------------------------------------------------

function CInventory:IsFlyingTool(tool_name)
    return (self.flying_tools[tool_name] == true)
end
--------------------------------------------------------------------------------

function CInventory:IsOpened()
    return self.opened
end
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- S L I D E ------------------------------------------------------------------
--------------------------------------------------------------------------------

function CInventory:SetStartPos()
    local index = 0;
    --[[
    for toolName, info in pairs(self.active_tools) do
        if info.notInInventoryYet then
            index = self:GetCellIndexByToolName(toolName) - 2;
            break;
        end
    end
    ]]
    self.anchor_col = index;
    self.anchor:SetX( START_ANCHOR_POS.x + (self.anchor_col * CELLS_WIDTH) )
    
    self:CheckCellsOpacity()
    self:CheckSlideBtnsEnable()
end
--------------------------------------------------------------------------------

function CInventory:RestoreShift()
    local state  = GetGameManager():GetCurrPlayer().gameState
 
    if state:HasState(INVENTORY_SHIFT) then
       self:SlideInventoryAt(tonumber(state:GetState(INVENTORY_SHIFT):Get(0)), nil, true)
    end
end
--------------------------------------------------------------------------------

function CInventory:SetXY(X, Y)
    X = X and X or self:GetX()
    Y = Y and Y or self:GetY()

    self.root:SetXY(X, Y)
end
--------------------------------------------------------------------------------

function CInventory:GetX()
    return self.root:GetX()
end
--------------------------------------------------------------------------------

function CInventory:GetY()
    return self.root:GetY()
end
--------------------------------------------------------------------------------

function CInventory:GetVisibleCellsCount()
    return VISIBLE_CELLS_COUNT
end
--------------------------------------------------------------------------------

function CInventory:SetIndex(index)
    if #self.cells<VISIBLE_CELLS_COUNT then
        index = 0    
    elseif index > (#self.cells-VISIBLE_CELLS_COUNT) then
        index = #self.cells-VISIBLE_CELLS_COUNT
    end
    
    self.anchor_col = -index
    self.anchor:SetX( START_ANCHOR_POS.x + (self.anchor_col * CELLS_WIDTH) )
    
    self:CheckCellsOpacity(0)
    self:CheckSlideBtnsEnable()
end
--------------------------------------------------------------------------------

function CInventory:GetIndex(index)
    return -self.anchor_col
end
--------------------------------------------------------------------------------

function CInventory:SlideInventoryAt(deltaCol, isAuxAnchor, restoring)
    local state  = GetGameManager():GetCurrPlayer().gameState
    local posrfix = (isAuxAnchor) and 'Aux' or ""
    
    local slide_time = SLIDE_TIME
    if restoring then
        slide_time = 0 
    end
    
    self.slidingAnchor = self['anchor'..posrfix]
    
    local effName      = 'slideEff'..posrfix
    local actionName   = 'slideAction'..posrfix
    local colName      = 'anchor_col'..posrfix
    
    if self[effName] then
        self[effName]:Destroy()
        self[effName] = nil
        
        self[actionName]:Kill()
    end
    
    self[colName] = self[colName] + deltaCol
    if #self.cells == VISIBLE_CELLS_COUNT then
        state:SetState(INVENTORY_SHIFT, '0')
    else
        state:SetState(INVENTORY_SHIFT, tostring(self[colName]))
    end
    
    local newX = START_ANCHOR_POS.x + (self[colName] * CELLS_WIDTH)
    local dx   = newX - self.slidingAnchor:GetX()
    local dir  = (dx ~= 0) and dx/math.abs(dx) or 0
    local momentumX = 5

    local eff = CreateAnimationEffector()
    eff:AttachTo( self.slidingAnchor )
    eff:SetMode( _ANIM_NOLOOP )
    eff:SetKey(_TRACK_X, 0,              self.slidingAnchor:GetX())
    eff:SetKey(_TRACK_X, slide_time*0.5, newX)
    eff:SetKey(_TRACK_X, slide_time*0.7, newX + momentumX*dir)
    eff:SetKey(_TRACK_X, slide_time,     newX)
    eff:Play()
    
    self[effName] = eff
    self[actionName] = self.timer:Add(  function()
                                            self[effName]:Destroy()
                                            self[effName] = nil
                                                        
                                            --self.slidingAnchor:SetX(newX)
                                            self:OnSlidingFinish()
                                        end,
                                        slide_time)
    
    self:CheckCellsOpacity(slide_time*0.5)
    self:CheckSlideBtnsEnable()
end
---------------------------------------------------------------------------

function CInventory:SlideInventoryTo(col)
    local deltaCol = -(self.anchor_col + col)
    
    if (deltaCol ~= 0) then
        self:SlideInventoryAt(deltaCol)
    end
end
---------------------------------------------------------------------------

function CInventory:IsSliding()
    return (self.slidingAnchor ~= nil)
end
---------------------------------------------------------------------------

function CInventory:OnSlidingFinish()
    self.slidingAnchor = nil;
    self:DettachCellsFromAuxAnchor()
end
---------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- C E L L S -------------------------------------------------------------------
--------------------------------------------------------------------------------

function CInventory:CreateCell(toolName)
	local index
    
    if toolName then
        if HasGameState(CELL_INDEX..toolName) then
            index = tonumber(GetGameState(CELL_INDEX..toolName):Get(0))
        else
            if HasGameState(CELL_FREE_INDEX) then
                index = tonumber(GetGameState(CELL_FREE_INDEX):Get(0))
            else
                index = 1;
            end
        
            SetGameState(CELL_FREE_INDEX, tostring(index+1))
            SetGameState(CELL_INDEX..toolName, tostring(index))
        end
        
        --if index < (self.cells_free_id+1) then
        if self.cells[index] then
            local info = self.cells[index]
            info.toolName = toolName
            return info
        end
    else
        index = self.cells_free_id+1
    end
    
    local holderObject
    local dividerObject
	
	do
        local cellX = (index-1) * CELLS_WIDTH;
        local cellY = 0
        local cellZ = 0
        
        local anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_cell.png',0,0,64,64,1,0)
        anim:SetHotSpot(32,32)
        anim:SetBlendMode(2)
        anim:SetColor('0x01FFFFFF')
        
        holderObject = self.screen:CreateObject('ToolHolder'..self.cell_counter, anim, cellX, cellY, cellZ, 0, 1, 1)
        holderObject:AttachTo( self.anchor )
        holderObject:SetOpacity(0)
        holderObject:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
        holderObject:GetAnimation():Stop()
    end
    
    -- create divider
    do
        local anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_divider.png',0,0,8,48,1,0)
        anim:SetHotSpot(4,24)
        anim:SetBlendMode(2)
        anim:SetColor('0xFFFFFFFF')
        
        local dividerObjectName = 'ToolDivider'..self.cell_counter
        dividerObject = self.screen:CreateObject(dividerObjectName, anim, CELLS_WIDTH/2, 0, 1, 0, 1, 1)
        dividerObject:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
        dividerObject:AttachTo( holderObject )
        
        self.screen:IgnoreOnTestPoint(dividerObjectName)
    end
    
    local info = {
                    cell     = holderObject,
                    divider  = dividerObject,
                    toolName = toolName,
                    eff      = nil,
                    show     = false,
                    dogPrint = nil,
                    dogGlow  = nil
                 };
    
	self.cells[index] = info
    self.cells_free_id = self.cells_free_id + 1
    self.cell_counter  = self.cell_counter  + 1
    return info
end
--------------------------------------------------------------------------------

function CInventory:RemoveCell(toolName)
    local info  = self:GetCellInfoByToolName(toolName)
    local index = self:GetCellIndexByInfo(info)
    local cell  = info.cell;
    
    local scrX = cell:GetScrX()
    local scrY = cell:GetScrY()
    local scrZ = cell:GetScrZ()
    
    cell:AttachTo( self.screen )
    cell:SetScrX( scrX )
    cell:SetScrY( scrY )
    cell:SetScrZ( scrZ )
    cell:ChangeOpacity(cell:GetOpacity(), 0, SLIDE_TIME)
    cell:Move(0, 100, SLIDE_TIME/2)
    
    self.timer:Add( function()
                        self:DeleteCell(cell)
                    end,
                    SLIDE_TIME)
    
    if (#self.cells-1)<VISIBLE_CELLS_COUNT then
        self:CreateCell()
    end
    
    self.anchor_colAux = self.anchor_col;
    self.anchorAux:SetX( self.anchor:GetX() )
    self:AttachCellsToAuxAnchor(index + 1)
        
    table.remove(self.cells, index)
    
    if HasGameState(CELL_INDEX..toolName) then
        RemoveGameState(CELL_INDEX..toolName)
    end
    
    for i=index, #self.cells do
        if self.cells[i].toolName then
            SetGameState(CELL_INDEX..self.cells[i].toolName, tostring(i))
        end
    end
    
    if HasGameState(CELL_FREE_INDEX) then
        local maxIndex = tonumber(GetGameState(CELL_FREE_INDEX):Get(0))
        SetGameState(CELL_FREE_INDEX, tostring(maxIndex - 1))
    end
    
    self.cells_free_id = self.cells_free_id-1
    
    if ((-self.anchor_col)+VISIBLE_CELLS_COUNT-1)~=#self.cells then
        self:SlideInventoryAt(-1, true)
    else
        self:SlideInventoryAt(1, false)
    end
end
--------------------------------------------------------------------------------

function CInventory:DeleteCell(cell)
    self.screen:DeleteObject(cell:GetName())
end
--------------------------------------------------------------------------------

function CInventory:MarkDogCell(toolName)
    local info  = self:GetCellInfoByToolName(toolName)
    
    if info then
        local cell = info.cell
        
        local glow
        local print
        
        do
            local anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_dog_glow.png',0,0,114,104,1,0)
            anim:SetHotSpot(57,52)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            
            local name = cell:GetName()..'_glow'
            self:IgnoreOnTestPoint(name)
            
            glow = self.screen:CreateObject(name, anim, 0, 0, 2, 0, 1, 1)
            glow:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
            glow:AttachTo( cell )
            
            local time = 1
            local eff = CreateAnimationEffector()
            eff:AttachTo(glow)
            eff:SetMode(_ANIM_FWD + _ANIM_LOOP)
            eff:SetKey(_TRACK_O, 0,          0.8)
            eff:SetKey(_TRACK_O, time * 0.5, 1)
            eff:SetKey(_TRACK_O, time,       0.8)
            eff:Play()
        end
        
        do
            local anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_dog_print.png',0,0,30,32,1,0)
            anim:SetHotSpot(15,16)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            
            local name = cell:GetName()..'_print'
            self:IgnoreOnTestPoint(name)
            
            print = self.screen:CreateObject(name, anim, 15, -10, 3, 0, 1, 1)
            print:SetClippingRect( Helpers.GetObjectScrRect( self.screen:GetObject('area_CellsRect') ) )
            print:AttachTo( cell )
            print:SetOpacity(0.5)
        end
        
        
        info.dogGlow  = glow
        info.dogPrint = print
    end
end
--------------------------------------------------------------------------------

function CInventory:GetCellInfoByToolName(toolName)
    for i, info in pairs(self.cells) do
        if info.toolName == toolName then
	        return info;
	    end
	end
	
	return nil;
end
--------------------------------------------------------------------------------

function CInventory:GetCellInfoByObjName(objName)
    for i, info in ipairs(self.cells) do
        if info.cell:GetName() == objName then
	        return info
	    end
	end
	
	return nil
end
--------------------------------------------------------------------------------

function CInventory:GetCellIndexByToolName(toolName)
    for i, info in ipairs(self.cells) do
        if info.toolName == toolName then
	        return i;
	    end
	end
	
	return nil;
end
--------------------------------------------------------------------------------

function CInventory:GetCellIndexByInfo(info)
    for i, currInfo in ipairs(self.cells) do
        if currInfo == info then
            return i;
        end
    end
    
    return nil;
end
--------------------------------------------------------------------------------

function CInventory:GetToolByCell(cell)
    if not cell then
        return nil
    end
    
    for i, cell_info in ipairs(self.cells) do
        if cell_info.cell:GetName() == cell:GetName() then
	        return cell_info.toolName;
	    end
	end
	
    return nil;
end
--------------------------------------------------------------------------------

function CInventory:AttachCellsToAuxAnchor(startIndex)
    startIndex = startIndex or 1
    local cnt = #self.cells;
    
    for i = startIndex, cnt do
        local cell = self.cells[i].cell;
        
        cell:AttachTo( self.anchorAux )
        cell:SetX( (i - 1) * CELLS_WIDTH )
        cell:SetY( 0 )
    end
end
--------------------------------------------------------------------------------

function CInventory:DettachCellsFromAuxAnchor()
    for i, cellInfo in ipairs(self.cells) do
        local cell = cellInfo.cell;
        
        if cell:GetParent():GetName() == self.anchorAux:GetName() then
            cell:AttachTo( self.anchor )
            cell:SetX( (i - 1) * CELLS_WIDTH )
            cell:SetY( 0 )
        end
    end
end
--------------------------------------------------------------------------------

function CInventory:CheckCellsOpacity(time)
    time = time or 0
    
    for index, info in ipairs(self.cells) do
        local cell_col = self.anchor_col + index - 1

        if cell_col < 0 or cell_col >= VISIBLE_CELLS_COUNT then
            if info.show then
                
                info.show = false;
                
                if info.eff then
                    info.eff:Destroy()
                    info.eff = nil;
                end
                
                if time == 0 then
                    info.cell:SetOpacity(0)
                else
                    info.eff = info.cell:ChangeOpacity(1, 0, time)
                    info.eff:SetDestroysOnEnd(false)
                end
            end
        else
            if not info.show then
                
                info.show = true;
                
                if info.eff then
                    info.eff:Destroy()
                    info.eff = nil;
                end
                
                if time == 0 then
                    info.cell:SetOpacity(1)
                else
                    info.eff = info.cell:ChangeOpacity(0, 1, time)
                    info.eff:SetDestroysOnEnd(false)
                end
            end
        end
    end
end
--------------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- B U T T O N S ---------------------------------------------------------------
--------------------------------------------------------------------------------

function CInventory:CheckSlideBtnsEnable()
    
    local cnt = #self.cells
    
    if self.cells[cnt].notInInventoryYet then
        cnt = cnt-1
    end
    
    if cnt <= VISIBLE_CELLS_COUNT or (self.anchor_col ) >= 0 then
        self.btn_left:Stop()
        self.btn_left:SetPressed(false)
        --self.btn_left:SetOpacity(0)
    else
        self.btn_left:Go()
        --self.btn_left:SetOpacity(1)
    end
    
    if cnt <= VISIBLE_CELLS_COUNT or (self.anchor_col + cnt) <= VISIBLE_CELLS_COUNT then
        self.btn_right:Stop()
        self.btn_right:SetPressed(false)
        --self.btn_right:SetOpacity(0)
    else
        self.btn_right:Go()
        --self.btn_right:SetOpacity(1)
    end
end
--------------------------------------------------------------------------------

function CInventory:OnButtonPress(title)
    if self.tool then
        self:DropTool()
    end
    
    if self.tool_to_set then
        self.tool_to_set = nil
    end
    
    if title == 'InventoryLeft' then
        self:SlideInventoryAt(1)
    end
    
    if title == 'InventoryRight' then
        self:SlideInventoryAt(-1)
    end
    --[[
    if title == 'InventoryLock' then
        AddUniqueGameState('InventoryLocked', 'y')
        self.btn_lock:Hide()
        self.btn_unlock:Show()
        
        self:SlideUp(0.4)
    end
    
    if title == 'InventoryUnlock' then
        if HasGameState('InventoryLocked') then
            RemoveGameState('InventoryLocked')
        end
        self.btn_unlock:Hide()
        self.btn_lock:Show()
        
        self:SlideDown(0.4)
    end
    --]]
end
--------------------------------------------------------------------------------

function CInventory:OnLockButtonClick()
    AddUniqueGameState('InventoryLocked', 'y')
    self.btn_lock:Hide()
    self.btn_unlock:Show()
    
    self:SlideUp(0.4)
end
--------------------------------------------------------------------------------

function CInventory:OnUnlockButtonClick()
    if HasGameState('InventoryLocked') then
        RemoveGameState('InventoryLocked')
    end
    self.btn_unlock:Hide()
    self.btn_lock:Show()
    
    self:SlideDown(0.4)
end
--------------------------------------------------------------------------------

function CInventory:OnButtonDepress(title)
    
end
--------------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- EVENTS ----------------------------------------------------------------------
--------------------------------------------------------------------------------

function CInventory:OnScreenObjectMouseDown(object)
    local level = GetCurrentLevel()
    
    DropObjectRequest(nil, false)
    
    if not self.tool and not self:IsSliding() and not self.toolsBlocker:IsHold() then
        local newTool = self:GetToolByCell(object)
        
        if not self:IsLockedTool(newTool) and
           not self:IsFlyingTool(newTool)
        then
            self.tool_to_set = newTool
        end
    end
    
    -- TODO: voloshin
    --[[
    if (not IsMouseBlocked()) and (level.comics and level.comics.IsMonolog()) then
        UpdateComicsRequest()
    end
    --]]
    
    if not IsMouseBlocked() then
        HideBlackBar()
    end
end
--------------------------------------------------------------------------------

function CInventory:OnObjectMouseEnter(object)
    if not self.opened then
        return
    end
	
	if self.SlideTimer then
	    self.SlideTimer:Kill()
	    self.SlideTimer = nil
	end
	
    self:SlideUp(SLIDE_INV_TIME)
end
--------------------------------------------------------------------------------

function CInventory:OnObjectMouseLeave(object)
    if self.bSlidedUp then
        local function Timer_SlideDown()
            self:SlideDown(SLIDE_INV_TIME)
        end
        self.SlideTimer = self.timer:Add(Timer_SlideDown, SLIDE_INV_DELAY)
    end
end
-------------------------------------------------------------------------------

function CInventory:SlideUp(speed)
    self.bSlidedUp = true
    
    speed = speed and speed or 0
    
    if self.SlideEff then
        self.SlideEff:Destroy()
        self.SlideEff = nil
    end
    
    if self.SlideSoundTimer then
        self.SlideSoundTimer:Kill()
        self.SlideSoundTimer = nil
    end
        
    if speed == 0 then
        self.root:SetXY(ROOT_SHOW_POSITION.x, ROOT_SHOW_POSITION.y)
    else
        local dy  = ROOT_SHOW_POSITION.y - self.root:GetY()
        local dir = (dy ~= 0) and dy/math.abs(dy) or 0
        local momentumY = 3
        
        local SpeedK = (self.root:GetY()-ROOT_SHOW_POSITION.y)/(ROOT_SLIDE_POSITION.y-ROOT_SHOW_POSITION.y)
        local time = speed*SpeedK
        
        local eff = CreateAnimationEffector()
        eff:SetMode(_ANIM_NOLOOP)
        eff:SetDestroysOnEnd(false)
        eff:AttachTo(self.root)
        eff:SetKey(_TRACK_Y, 0,         self.root:GetY())
        eff:SetKey(_TRACK_Y, time*0.7,  ROOT_SHOW_POSITION.y + momentumY*dir)
        eff:SetKey(_TRACK_Y, time,      ROOT_SHOW_POSITION.y)
        eff:Play()
        
        self.SlideEff = eff
        
        if time > 0 then
            self.SlideSoundTimer = self.timer:Add(function()
                                                    PlaySound('Inventory_move')
                                                  end,
                                                  time-0.4)
        end
    end
end
-------------------------------------------------------------------------------

function CInventory:SlideDown(speed)
    self.bSlidedUp = false
    
    speed = speed and speed or 0
    
	if HasGameState('InventoryLocked') then
        return
    end
    
    if self.SlideEff then
        self.SlideEff:Destroy()
        self.SlideEff = nil
    end
    
    if self.SlideSoundTimer then
        self.SlideSoundTimer:Kill()
        self.SlideSoundTimer = nil
    end
    
    if speed == 0 then
        self.root:SetXY(ROOT_SLIDE_POSITION.x, ROOT_SLIDE_POSITION.y)
    else
        local SpeedK = (ROOT_SLIDE_POSITION.y-self.root:GetY())/(ROOT_SLIDE_POSITION.y-ROOT_SHOW_POSITION.y)
        local time = speed*SpeedK
        
        self.SlideEff = self.root:MoveTo(ROOT_SLIDE_POSITION.x, ROOT_SLIDE_POSITION.y, time)
        self.SlideEff:SetDestroysOnEnd(false)
        
        PlaySound('Inventory_move')
    end
    
    self:UpdateHintText()
end
-------------------------------------------------------------------------------

function CInventory:OnUpdate(dt)
    local panel = play_field:GetLevelScreen():GetPanel():GetAssociatedLuaObject()
    
    if panel:GetMode() ~= EPanelMode.PM_QUEST
        -- TODO: voloshin
        --and panel:GetMode() ~= EPanelMode.PM_COMICSMONOLOG
    then
        return
    end
	
    if self.tool_to_set then
        local cellInfo = self:GetCellInfoByToolName(self.tool_to_set)
        
        if cellInfo.show then
            self:TakeTool(self.tool_to_set)
        end
        self.tool_to_set = nil
    end
    
    if self.tool then
        local mouse_pos = GetMousePos()
        self.tool:SetScrXY(mouse_pos.x, mouse_pos.y)
        self.tool:SetZ(TOOL_IN_INVENTORY_Z)
    end
    
    self:UpdateHintText()
end
--------------------------------------------------------------------------------

function CInventory:UpdateHintText()
    local obj       = self:GetObjectUnderMouse()
    local cellInfo  = obj and self:GetCellInfoByObjName(obj:GetName()) or nil
    
	if self.bSlidedUp
	    and self.opened
        and cellInfo
        and cellInfo.show
        and cellInfo.toolName
        and not self.tool
        and not self:IsFlyingTool(cellInfo.toolName)
        and not self:IsLockedTool(cellInfo.toolName)
    then
        local tool_name = cellInfo.toolName
        local mouse     = GetMousePos()
		
		if tool_name ~= self.hintedTool then
		    local info = self.active_tools[tool_name]
		    
		    self.hintText:SetText( GetString(info.hint_text) )
		    self.hintTextMaxX = SCR_W - self.hintText:GetWidth()
		    self.hintedTool   = tool_name
		    
		    local hintTextX = math.min(mouse.x + TOOL_NAME_TEXT_OFFSET_X, self.hintTextMaxX)
		    self.hintText:SetXY(hintTextX, mouse.y + TOOL_NAME_TEXT_OFFSET_Y)
		    self.hintText:SetVisible(true)
		    
		    if currentCursor ~= 'CursorActive' then
                SetCursor('CursorActive')
            end
        else
            local hintTextX = math.min(mouse.x + TOOL_NAME_TEXT_OFFSET_X, self.hintTextMaxX)
            self.hintText:SetXY(hintTextX, mouse.y + TOOL_NAME_TEXT_OFFSET_Y)
		end
    else
        if self.hintedTool ~= nil then
            if currentCursor ~= 'CursorDefault' then
                SetCursor('CursorDefault')
            end
            
            self.hintText:SetVisible(false)
            self.hintedTool = nil
        end
    end
end
--------------------------------------------------------------------------------

function CInventory:Open(time)
    time = time or OPEN_TIME
    
    self.opened = true
    
    if self.fadeEff ~= nil then
        self.fadeEff:Destroy()
        self.fadeEff = nil
    end
    
    local position = ROOT_SLIDE_POSITION.y
    if HasGameState('InventoryLocked') then 
		position = ROOT_SHOW_POSITION.y
		time     = 0
	end
    
    self.screen:GetObject('area_panel_top_over'):SetVisible(true)
    
    if time == 0 then
        self.root:SetY(position)
    else
        self.fadeEff = CreateAnimationEffector()
        self.fadeEff:AttachTo(self.root)
        self.fadeEff:SetKey(_TRACK_Y, 0,    self.root:GetY())
        self.fadeEff:SetKey(_TRACK_Y, time, position)
        self.fadeEff:Play()
    end
end
--------------------------------------------------------------------------------

function CInventory:Close(time)
    time = time or OPEN_TIME
    
    self.opened = false
    
    if fadeEff ~= nil then
        fadeEff:Destroy();
        fadeEff = nil
    end
    
    self.screen:GetObject('area_panel_top_over'):SetVisible(false)
    
    if time == 0 then
        self.root:SetY(ROOT_HIDE_POSITION.y)
    else
        self.fadeEff = CreateAnimationEffector()
        self.fadeEff:AttachTo(self.root)
        self.fadeEff:SetKey(_TRACK_Y, 0,    self.root:GetY())
        self.fadeEff:SetKey(_TRACK_Y, time, ROOT_HIDE_POSITION.y)
        self.fadeEff:Play()
    end
    
    self:UpdateHintText()
end
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- CLEAR_ON_SAVE_BEGIN
-- Do not edit code listed below (generated by the editor on each save)
function CInventory:LoadData(screen)
	local anim
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_panel.png',0,0,760,118,1,0)
	anim:SetHotSpot(380,59)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('inventory_panel',anim,514,711,290,0,1,1)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(0)
	anim:SetColor('0x00FFFFFF')
	screen:CreateObject('tools_anchor',anim,150,724,291,0,1,1)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(0)
	anim:SetColor('0x00FFFFFF')
	screen:CreateObject('tools_anchorAux',anim,150,724,291,0,1,1)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/bttn/bttn_inventory_right.png',0,0,32,30,3,0)
	anim:SetHotSpot(16,15)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('bttn_inventory_left',anim,203,731,291,0,-1,1)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/bttn/bttn_inventory_right.png',0,0,32,30,3,0)
	anim:SetHotSpot(16,15)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('bttn_inventory_right',anim,821,731,291,0,1,1)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_title_txt.png',0,0,132,20,1,0)
	anim:SetHotSpot(66,10)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('inventory_title_txt',anim,514,684,291,0,1,1)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	screen:CreateObject('area_CellsRect',anim,512,731,100,0,68,8)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_LButtonOver',anim,221,728,499,0,5,10)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_RButtonOver',anim,803,728,499,0,5,10)
	
	anim = CreateAnimation('data/Texture/Common/area.png',0,0,8,8,1,0)
	anim:SetHotSpot(4,4)
	anim:SetBlendMode(2)
	anim:SetColor('0x01FFFFFF')
	screen:CreateObject('area_panel_top_over',anim,512,750,100,0,45,4.5)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/inventory_frame.png',0,0,544,68,1,0)
	anim:SetHotSpot(272,34)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('inventory_frame',anim,512,732,300,0,1,1)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/bttn/bttn_inventory_lock.png',0,0,70,74,3,0)
	anim:SetHotSpot(35,37)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('bttn_inventory_lock',anim,600,668,292,0,0.7,0.7)
	
	anim = CreateAnimation('data/Texture/GUI/Panel/inventory/bttn/bttn_inventory_unlock.png',0,0,70,68,3,0)
	anim:SetHotSpot(35,34)
	anim:SetBlendMode(2)
	anim:SetColor('0xFFFFFFFF')
	screen:CreateObject('bttn_inventory_unlock',anim,600,670,292,0,0.7,0.7)
	
end
-- CLEAR_ON_SAVE_END
