
----------------------------------------------------------------------------------------------------
HOLevel = {}

HOLevel.PENALTY_TIME = 4.0
HOLevel.PENALTY_CLICK_COUNT = 5
HOLevel.PENALTY_CAP = 0.6
HOLevel.LEVEL_TIME = 5.0 * 60.0
HOLevel.ACTION_IDLE_TIME = 2.0

HOLevel.current = nil
HOLevel.opened = false
HOLevel.locked = false
HOLevel.playing_interacts = 0
HOLevel.ExitTarget = ""

HOLevel.list = {}

HOLevel.found_keys_now = 0

------------------------------------------------------------------------------------------------
SceneTestInfo = {}
local test_info_path = 'test_info/'

function SceneTestInfo:start(locname, scene)
    --SceneTestInfo.fd = io.open(test_info_path..locname..'_'..scene..'_info.txt', 'wt')
    --SceneTestInfo:put('Location: '..locname..'\n')
    --SceneTestInfo:put('Scene: '..scene..'\n')
end

function SceneTestInfo:put(string)
    --SceneTestInfo.fd:write(string..'\n')
end

function SceneTestInfo:stop()
	--SceneTestInfo.fd:close()
	--SceneTestInfo.fd = nil
end

----------------------------------------------------------------------------------------------------
function HOLevel:new(aLocation, aScene)
	local obj = {}
	setmetatable(obj, self)
	self.__index = self

    obj.name = aLocation.mName
	obj.mDisplay = level_mgr:get_layer(aLocation.mName)

	if aScene == nil then
	    obj.mScene = 1
	else
	    obj.mScene = aScene
	end

    obj.mHids = {}
    obj.mInteracts = {}
    obj.mTime = 0.0

    obj.mIsStarted = false
    obj.mIsFinished = false
    obj.mInventory = {}

	obj.mLocation = aLocation;

    obj.mClicks = 0
    obj.mClickTimer = 0
    obj.mPenaltyTimer = 0

    obj.mWinTerms = Profile:getWinTerms(obj.mLocation.mName, obj.mScene)
    obj.mMixes = Profile:getMixes(obj.mLocation.mName, obj.mScene)
    obj.mTask = Profile:getSceneTask(obj.mLocation.mName, obj.mScene)
    --obj.mRemark = Profile:getSceneRemark(obj.mLocation.mName, obj.mScene)
    obj.mAmbListeners = Profile:getAmbListeners(obj.mLocation.mName, obj.mScene)
    obj.showWin = false

    table.insert(HOLevel.list, obj)

	return obj
end

function HOLevel:attachExtraHids()
end

function HOLevel:onFindExtra()
    return 0
end

function HOLevel:onEventExtra(aEvent)
    if aEvent == 'start' then
        self:attachExtraHids()
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:postEvent(aEvent)
    if HOLevel.ExitTarget == "" then
        if self.mLocation ~= nil then
            self.mLocation:onEvent(self.mScene, aEvent)
        end
    else
        self:onEventExtra(aEvent)
    end

    for i = 1, #self.mWinTerms do
        if aEvent == self.mWinTerms[i].event then
            self.mWinTerms[i].handled = true
        end
    end

    if self.mIsStarted and self:isWin() and not self.mIsFinished then
        self.showWin = true
        HOLevel.locked = true
        self.mIsFinished = true
        self:setTask("")

        if HOLevel.ExitTarget == "" then
            if Profile.data[self.mLocation.mName]['pass'] == nil then
                Profile.data[self.mLocation.mName]['pass'] = 1
            else
                Profile.data[self.mLocation.mName]['pass'] = Profile.data[self.mLocation.mName]['pass'] + 1
            end
        end

        --Level:onLocationWin()
    end

end

----------------------------------------------------------------------------------------------------
function HOLevel:onChallengeComplete()
    Tutorial:sendMessage('challenge.complete')
    Levels:getCurrentLevel():setInfo(self.name, {challengePassed = true})
    Levels:getCurrentLevel():checkPassed()
end

----------------------------------------------------------------------------------------------------
function HOLevel:activateCloseUp(name, state)

    if self.mCloseUps[name] == nil then
        return
    end

    self.mCloseUps[name].state.active = state

    if state then
        self.mDisplay:get_element('cul_'..name):setActive(true)
        self.mDisplay:set_element_eh('cul_'..name, 
            function()
                self:onCloseUpOpen(self.mCloseUps[name])
            end)

        self.mDisplay:link_effect("hint_place",'cul_'..name)
    else
        self.mDisplay:get_element('cul_'..name):setActive(false)
        self.mDisplay:unlink_effect('cul_'..name)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:isWin()
    local win = true

    for i = 1, #self.mWinTerms do
        win = win and self.mWinTerms[i].handled
    end

    return win
end

----------------------------------------------------------------------------------------------------
function HOLevel:setWinTerms(aEvents)
    for i = #self.mWinTerms, 1, -1 do
        self.mWinTerms[i] = nil
    end

    for i = 1, #aEvents do
        self.mWinTerms[i] = {}
        self.mWinTerms[i].event = aEvents[i]
        self.mWinTerms[i].handled = false
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:processChildren(aDisplay, aElemName, aPrefix, aFunc)
    scene = aDisplay:get_element(aElemName)

    local size = aDisplay:get_element_count()
    for i = 0, size - 1 do
        elem = aDisplay:get_element_at(i)
        if scene == nil or scene:isParentOf(elem) then
            elemName = elem:getName()
            if string.sub(elemName, 0, aPrefix:len()) == aPrefix then
                aFunc(elem, parent_name)
            end
        end
    end
    
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadHidList()
    self.mHids = {}

    local count = 0
    local func = function(elem)
            table.insert(self.mLocation.mSharedHids, {elem = elem:getName(), capture = false});

            local name = string.gsub(elem:getName(), "hid_"..self.mScene.."_", "")
            SceneTestInfo:put('\t'..elem:getName())
            count = count + 1
            self.mHids[name] = {}
            self.mHids[name].elem = elem

            state = Profile:getHidState(self.mLocation.mName, self.mScene, name)
            if state == nil then
                state = {}
                state.visible = true
                state.attached = false
                state.found = false
                state.active = true
                state.inventory = false
                state.mix = false
                Profile:setHidState(self.mLocation.mName, self.mScene, name, state)
            end
            self.mHids[name].state = state

            self.mHids[name].elem_pos = Vec2(elem:getPos().x, elem:getPos().y)
            self.mHids[name].elem_scale = elem:getScale()
            self.mHids[name].elem_alpha = elem:getAlpha()
            self.mHids[name].elem_angle = elem:getAngle()
            self.mHids[name].elem_parent = elem:getParent()
            self.mHids[name].elem_depth = elem:getDepth()

            --local parent = elem:getParent()
            --if parent:get_name() == "cu_parent" then
                --local parent_base_name = string.gsub(parent:getParent():get_name(), "cu_", "")
                table.foreach(self.mCloseUps,
                    function(cu_name)
                        if self.mCloseUps[cu_name].mDisplay:get_element(elem:getName()) ~= nil then
                            --local v = parent:isVisible()
                            self.mHids[name].parent = self.mCloseUps[cu_name].mDisplay:get_element('cu_parent')
                            self.mHids[name].assist = self.mDisplay:get_element("cul_"..cu_name)
                        end
                    end)
            --end
        end

    SceneTestInfo:put('Hids:')
    self:processChildren(self.mDisplay, "", "hid_"..self.mScene.."_", func)
    table.foreach(self.mCloseUps,
        function(name)
            SceneTestInfo:put('\n\tIn closeup ['..name..']:')
            self:processChildren(self.mCloseUps[name].mDisplay, "", "hid_"..self.mScene.."_", func)
        end)

    SceneTestInfo:put('\n\tCount: '..count..'\n\n')
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadInteractList()
    self.mInteracts = {}

    local count = 0
    local func = function(elem)
            local name = string.gsub(elem:getName(), "int_"..self.mScene.."_", "")
            SceneTestInfo:put('\t'..elem:getName())
            count = count + 1
            self.mInteracts[name] = {}
            self.mInteracts[name].elem = elem

            state = Profile:getInteractState(self.mLocation.mName, self.mScene, name)
            if state == nil then
                state = {}
                state.visible = true
                state.twoWay = false
                state.mouse = nil
                state.activated = false
                state.attached = false
                state.active = false
                Profile:setInteractState(self.mLocation.mName, self.mScene, name, state)
            end
            self.mInteracts[name].state = state

            local parent_name = elem:getParent():get_name()
            local parent_base_name = string.gsub(parent_name, "cu_", "")
            if parent_name ~= parent_base_name then
                self.mInteracts[name].parent = self.mDisplay:get_element(parent_name)
                self.mInteracts[name].assist = self.mDisplay:get_element("cul_"..parent_base_name)
            end
        end

    self:processChildren(self.mDisplay, "", "int_"..self.mScene.."_", func)
end

----------------------------------------------------------------------------------------------------
function HOLevel:onCULClick(name)
    local i = 0
    self.mDisplay:get_element("cu_"..name):setVisible(true)
    self.mDisplay:get_element("stop_click"):setActive(true)

    self.mDisplay:set_element_eh("back_click",
        function()
            self.mDisplay:get_element("cu_"..name):setVisible(false)
            self.mDisplay:get_element("stop_click"):setActive(false)

            local func = function(elem)
                self.mDisplay:link_effect("hint_place",elem:getName())
            end
            self:processChildren(self.mDisplay, "", "cul_", func)
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadCULocatorsList()

    if self.mLocation.mLocators ~= nil then
        return
    end

    self.mLocation.mLocators = {}

    local func = function(elem)
        local name = string.gsub(elem:getName(), "cul_", "")
        table.insert(self.mLocation.mLocators, name)
        self.mDisplay:get_element("cu_"..name):setVisible(false)
        self.mDisplay:set_element_eh(elem:getName(),
            function()
                stop_all_effects()
                self:onCULClick(name)
            end)
    end

    self:processChildren(self.mDisplay, "", "cul_", func)
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadCloseUps()

    self.mCloseUps = {}
    local count = 0
    local func = function(elem)
        local name = string.gsub(elem:getName(), "cul_", "")
        count = count + 1
        self.mCloseUps[name] = Closeup:new(name, self.mScene)

        state = Profile:getCloseUpState(self.mLocation.mName, self.mScene, name)
        if state == nil then
            state = {}
            state.active = true
            Profile:setCloseUpState(self.mLocation.mName, self.mScene, name, state)
        end
        self.mCloseUps[name].state = state
        self.mCloseUps[name]:hide() --.mDisplay:set_visible(false)

        SceneTestInfo:put('\t'..name)
    end

    SceneTestInfo:put('CloseUps:')
    self:processChildren(self.mDisplay, "", "cul_", func)
    SceneTestInfo:put('\n\tCount: '..count..'\n\n')
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadExtrasList()
    
    if #self.mLocation.mExtras > 0 then -- если уже загрузили до нас, то не будем
        return
    end

    local func = function(elem)
            SceneTestInfo:put('\t'..elem:getName())
            local name = string.gsub(elem:getName(), "extra_", "")
            self.mLocation.mExtras[name] = {}
            self.mLocation.mExtras[name].elem = elem

            state = Profile:getExtraState(self.mLocation.mName, name)
            if state == nil then
                state = {}
                state.visible = true
                state.play_once = nil
                state.play_loop = nil
                state.frame = 0
                Profile:setExtraState(self.mLocation.mName, name, state)
            end
            self.mLocation.mExtras[name].state = state
            self:setExtraParams(name, state)
        end

    SceneTestInfo:put('Extras:')
    self:processChildren(self.mDisplay, "", "extra_", func)
end

----------------------------------------------------------------------------------------------------
function HOLevel:loadAmbients()
    if #self.mLocation.mAmbients > 0 then -- если уже загрузили до нас, то не будем
        return
    end

    local func = function(elem)
            local name = string.gsub(elem:getName(), "amb_", "")
            self.mLocation.mAmbients[name] = {}
            self.mLocation.mAmbients[name].elem = elem
        end

    self:processChildren(self.mDisplay, "", "amb_", func)
end

----------------------------------------------------------------------------------------------------
function HOLevel:removeHidHint(aName)
    if self.mHids[aName] ~= nil then
        Hint:removeElement(self.mHids[aName].elem)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:activateInteract(aName)
    local mouse = self.mInteracts[aName].state.mouse
    self.mDisplay:add_roll("int_"..self.mScene.."_"..aName, {with_element = mouse, over = "gear"})
    self.mDisplay:set_element_eh("int_"..self.mScene.."_"..aName, function() self:onInteractClick(aName) end)
    Hint:addElement(self.mDisplay:get_element("int_"..self.mScene.."_"..aName),
        self.mInteracts[aName].parent, self.mInteracts[aName].assist)

    if mouse ~= nil then
        ho:setChallengeItem('hid_'..self.mScene..'_'..mouse)
    end

    if self.mActionTimers == nil then
        self.mActionTimers = {}
    end

    self.mActionTimers[aName] = HOLevel.ACTION_IDLE_TIME
end

----------------------------------------------------------------------------------------------------
function HOLevel:addItemMix(aResult, aUnits)
    self.mMixes[aResult] = {}
    self.mHids[aResult].state.mix = true
    self:setHidsParams({aResult}, {inventory = true})
    ho:setChallengeItem('hid_'..self.mScene..'_'..aResult)
    table.foreach(aUnits,
        function(key)
            ho:setChallengeItem('hid_'..self.mScene..'_'..aUnits[key])
            self:setHidsParams({aUnits[key]}, {inventory = true})
            Inventory:addItem(aUnits[key])
            self.mMixes[aResult][aUnits[key]] = self.mHids[aUnits[key]].state.found
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:attachInteract(aName, aMouse)
    if self.mInteracts[aName] == nil then
        return
    end

    if self.mInteracts[aName].state.attached then
        return
    end

	self.mInteracts[aName].state.active = true
	self.mDisplay:get_element("int_"..self.mScene.."_"..aName):setActive(true)
        
    self.mInteracts[aName].state.attached = true
    self.mInteracts[aName].state.mouse = aMouse
    self:activateInteract(aName)
    
    if aMouse ~= nil then
        ho:setChallengeItem('hid_'..self.mScene..'_'..aMouse)
        Inventory:addItem(aMouse)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:deactivateInteract(aName)
    self.mDisplay:remove_roll("int_"..self.mScene.."_"..aName)
    self.mDisplay:set_element_eh("int_"..self.mScene.."_"..aName, nil)
    self.mDisplay:get_element("int_"..self.mScene.."_"..aName):setActive(false)
    Hint:removeElement(self.mDisplay:get_element("int_"..self.mScene.."_"..aName))

    if self.mActionTimers ~= nil and self.mActionTimers[aName] ~= nil then
        self.mActionTimers[aName] = nil
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:detachInteract(aName)
    if self.mInteracts[aName] == nil then
        return
    end

    if not self.mInteracts[aName].state.attached then
        return
    end

    self.mInteracts[aName].state.attached = false
    self:deactivateInteract(aName)
end

----------------------------------------------------------------------------------------------------
function HOLevel:setInteractParams(aName, aParams)
    if self.mInteracts[aName] == nil or aParams == nil then
        return
    end

    if aParams.visible ~= nil then
        self.mInteracts[aName].state.visible = aParams.visible
        self:showElement("int_"..self.mScene.."_"..aName, aParams.visible)
    end

    if aParams.active ~= nil then
        self.mInteracts[aName].state.active = aParams.active
        self.mDisplay:get_element("int_"..self.mScene.."_"..aName):setActive(aParams.active)
    end

    if aParams.twoWay ~= nil then
        self.mInteracts[aName].state.twoWay = aParams.twoWay
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:setExtraParams(aName, aParams)
    if self.mLocation.mExtras[aName] == nil or aParams == nil then
        return
    end

    if aParams.play ~= nil or aParams.play_once or aParams.play_loop then
        self.mLocation.mExtras[aName].state.frame = nil
        if aParams.loop ~= nil or aParams.play_loop ~= nil then
			local loop = false
			if aParams.loop then loop = aParams.loop end
			if aParams.play_loop then loop = aParams.play_loop end
            self.mLocation.mExtras[aName].state.play_once = nil
            self.mLocation.mExtras[aName].state.play_loop = true
            self.mDisplay:play_clip("extra_"..aName, {looped = loop})
        else
            self.mLocation.mExtras[aName].state.play_loop = nil
            self.mLocation.mExtras[aName].state.play_once = true
            self.mDisplay:play_clip("extra_"..aName)
        end
    end

    if aParams.frame ~= nil then
        self.mLocation.mExtras[aName].state.play_once = nil
        self.mLocation.mExtras[aName].state.play_loop = nil
        self.mLocation.mExtras[aName].state.frame = aParams.frame
        self.mDisplay:play_clip("extra_"..aName, {frame_begin = aParams.frame, frame_end = aParams.frame})
    end

    if aParams.visible ~= nil then
        if not aParams.visible then
            self.mLocation.mExtras[aName].state.play_once = nil
            self.mLocation.mExtras[aName].state.play_loop = nil
            self.mLocation.mExtras[aName].state.frame = nil
        end
        self.mLocation.mExtras[aName].state.visible = aParams.visible
        self:showElement("extra_"..aName, aParams.visible)
    end
    aParams = table.copy(self.mLocation.mExtras[aName].state)
end

----------------------------------------------------------------------------------------------------
function HOLevel:attachHids(aItems)

    for i = 1, #aItems do
        local tName = aItems[i]
        if self.mHids[tName] ~= nil and not self.mHids[tName].state.attached then
            self.mHids[tName].state.attached = true
            if not ho:has("hid_"..self.mScene.."_"..aItems[i]) then
                ho:add(self.mHids[tName].elem, self.mHids[tName].parent, self.mHids[tName].assist)
            end
            ho:setActive("hid_"..self.mScene.."_"..aItems[i], self.mHids[tName].state.active)
            
            table.foreach(self.mMixes,
            function(name)
                if tName == name then
                    ho:setChallengeItem('hid_'..self.mScene..'_'..name)
                end

                for k, v in pairs(self.mMixes[name]) do
                    if k == tName then
                        ho:setChallengeItem('hid_'..self.mScene..'_'..k)
                    end
                end
            end)

        end
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:setHidsParams(aItems, aParams)
    if aParams == nil then
        return
    end
    
    for i = 1, #aItems do
        local tName = aItems[i]
        if self.mHids[tName] ~= nil and not self.mHids[tName].state.found then
            if aParams.visible ~= nil then
                self.mHids[tName].state.visible = aParams.visible
                self:showElement("hid_"..self.mScene.."_"..tName, aParams.visible)
            end

            if aParams.inventory ~= nil then
                self.mHids[tName].state.inventory = aParams.inventory
            end

            if aParams.active ~= nil then
                self.mHids[tName].state.active = aParams.active
                if ho:has("hid_"..self.mScene.."_"..aItems[i]) then
                    ho:setActive("hid_"..self.mScene.."_"..aItems[i], aParams.active)
                end
            end

            if aParams.found ~= nil then
                self:onFind('hid_'..self.mScene..'_'..tName)
                self.mHids[tName].state.found = aParams.found
            end
        end
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:getHidList(aParams)
    result = {}
    local resultSize = 1
    
    table.foreach(self.mHids,
        function(aName)
            local filtered = false
            if aParams ~= nil and aParams.except ~= nil then
                for j = 1, #aParams.except do
                    filtered = filtered or (aName == aParams.except[j])
                end
            end

            if not filtered then
                result[resultSize] = aName
                resultSize = resultSize + 1
            end
        end)

    return result
end

----------------------------------------------------------------------------------------------------
function HOLevel:getFoundCount()

    local result = 0

    table.foreach(self.mHids,
        function(aName)
            if self.mHids[aName].state.found and self.mHids[aName].state.attached then
                result = result + 1
            end
        end)

    return result
end

----------------------------------------------------------------------------------------------------
function HOLevel:isAllFound()

    local result = true

    table.foreach(self.mHids,
        function(aName)
            result = result and self.mHids[aName].state.found
        end)

    return result
end

----------------------------------------------------------------------------------------------------
function HOLevel:onFind(aHidName)
    if HOLevel:isExtraLevel() then
        return self:onFindExtra()
    end

    local tSlot = 0
    local tBaseName = string.gsub(aHidName, "hid_"..self.mScene.."_", "")

    self.mHids[tBaseName].state.found = true
    if self.mHids[tBaseName].state.inventory then
        tSlot = Inventory:activateItem(tBaseName)
    end

    if self.mActionTimers ~= nil then
        table.foreach(self.mActionTimers,
            function(name)
                self.mActionTimers[name] = HOLevel.ACTION_IDLE_TIME
            end)
    end

    table.foreach(self.mMixes,
        function(mixKey)
            local tMixComplete = true
            local tUnits = {}

            trace('mix '..mixKey..': ')
            for key, val in pairs(self.mMixes[mixKey]) do
                table.insert(tUnits, key)

                if key == tBaseName then
                    self.mMixes[mixKey][key] = true
                    val = true
                end

                if val then
                    trace('\t'..key..': OK')
                else
                    tMixComplete = false
                    trace('\t'..key..': waiting...')
                end
            end

            if tMixComplete then
                ho:startMixing(mixKey, tUnits)
                self.mMixes[mixKey] = nil
            end
        end) 

    local level = Levels:getLevelFromScene(self.name,self.mScene)
    if level then
        level:setInfo(self.name, {collectedHids = self:getFoundCount()}) 
        level:checkPassed()
    end

    self:postEvent("found_"..tBaseName)

    --trace(self:getFoundCount().." of "..#self.mHids)
    if self:isAllFound() then
        self:postEvent("ho_collected")
    end

    table.foreach(self.mCloseUps,
        function(name)
            self.mCloseUps[name]:setFound(aHidName)
            if self.mCloseUps[name]:isVisible() and self.mCloseUps[name]:getHidCount() == 0 then
                timer_mgr:add_timer(function() self.mCloseUps[name]:hide() end, 2.0, 1);
                --self.mDisplay:set_element_eh('cul_'..name, nil)
                self.mDisplay:get_element('cul_'..name):setActive(false)
            end
        end)

    Tutorial:sendMessage('hid.found')
    return tSlot
end

----------------------------------------------------------------------------------------------------
function HOLevel:showElement(aElemName, aState)
    elem = self.mDisplay:get_element(aElemName)
    if elem ~= nil then
        elem:setVisible(aState)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:onInteractActivated(aInteract)
    self.mInteracts[aInteract].state.activated = not self.mInteracts[aInteract].state.activated

    if self.mInteracts[aInteract].state.activated then
        self:postEvent("activate_"..aInteract)
    else
        self:postEvent("deactivate_"..aInteract)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:onInteractClick(aInteract)

    if HODialogs:isVisible() then
        return
    end

    if self.mPenaltyTimer > 0 then
        return
    end

    local tMouse = self.mInteracts[aInteract].state.mouse

    if mouse:getConnectedName() == tMouse or tMouse == nil then

        if not self.mInteracts[aInteract].state.twoWay then
            mouse:setConnCharacter(nil)
            mouse:setCursorFrame("default")

            self:detachInteract(aInteract)

            if tMouse ~= nil then
                Inventory:removeItem(tMouse)
            end
        end

        elem = self.mDisplay:get_element("int_"..self.mScene.."_"..aInteract)

        if not self.mInteracts[aInteract].state.activated then
            if elem:getCharacter():get_frame_count() > 1 then
                HOLevel.locked = true

                if HOLevel.playing_interacts == nil then
                    HOLevel.playing_interacts = 1
                else
                    HOLevel.playing_interacts = HOLevel.playing_interacts + 1
                end

                set_frame_listener(elem, elem:getCharacter():get_frame_count() - 1,
                    function()
                        HOLevel.locked = false
                        HOLevel.playing_interacts = HOLevel.playing_interacts - 1
                        self:onInteractActivated(aInteract)
                    end)
                play_clip(elem:getCharacter(), {looped = false})
            else
                self:showElement("int_"..self.mScene.."_"..aInteract, false)
                self:onInteractActivated(aInteract)
            end

            if self.mInteracts[aInteract].linked_effect ~= nil then
                self.mDisplay:unlink_effect(self.mInteracts[aInteract].elem:getName())
                self.mInteracts[aInteract].linked_effect = nil
            end

            Hint:removeElement(elem)

            Media:soundEvent('int.on.'..self.mLocation.mName..'.'..aInteract)
            self:postEvent('activate_click_'..aInteract)
        else
            play_clip(elem:getCharacter(), {frame_begin = 0, frame_end = 0})
            self:onInteractActivated(aInteract)
            Media:soundEvent('int.off.'..aInteract)
        end
    end
end



----------------------------------------------------------------------------------------------------
function HOLevel:init()
	
    SceneTestInfo:start(self.mLocation.mName, self.mScene)
    self:loadCloseUps()
    self:loadHidList()
    self:loadInteractList()
    self:loadExtrasList()
    --self:loadCULocatorsList();
    self:loadAmbients();
    SceneTestInfo:stop()

    self.visited = false
    self.mTime = HOLevel.LEVEL_TIME

    --self.mLevel = Profile:getLevel()
    local collected_hids = 0
    table.foreach(self.mHids,
        function(key)
            if self.mHids[key].state.found and not self.mHids[key].state.mix then
                collected_hids = collected_hids + 1
            end
        end)

    local level = Levels:getLevelFromScene(self.name,self.mScene)
    if level then
        level:setInfo(self.name, {collectedHids = collected_hids}) 
    end

        self:postEvent('capture')
    if Profile:getSceneState(self.mLocation.mName, self.mScene) == 'new' then
        self:postEvent('generic_init')
        Profile:onSceneInit(self.mLocation.mName, self.mScene)
    else
        self:place(false)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:isOpened()
    return HOLevel.opened
end

----------------------------------------------------------------------------------------------------
function HOLevel:enter()

	--HOLevel.found_keys_now = Profile:getKeysFoundNow(self.mLocation.mName)
	--if HOLevel.found_keys_now == nil then HOLevel.found_keys_now = 0 end

    -- ExtraLevels -
    if not HOLevel:isExtraLevel() then
        self.mLevel = Profile:getLevel()
        Tutorial:enterChapter('HO')
    end

    -- ExtraLevels +
    HOLevel.current = self
    Panel:show(true)

    self:place()
    
    self.showWin = false
    HOLevel.locked = false
	self.mIsFinished = false

    self.mDisplay:set_element_eh("background", function() self:onBackgroundClick() end)
    addUpdateListener(self)

    table.foreach(self.mLocation.mAmbients,
        function(name)
            play_clip(self.mLocation.mAmbients[name].elem:getCharacter(), {looped = true})
        end)

    local closeup_message_sent = false
    table.foreach(self.mCloseUps,
        function(name)
            if not closeup_message_sent then
                Tutorial:sendMessage('closeup.show')
                closeup_message_sent = true
            end

            if self.mCloseUps[name]:getHidCount() > 0 then
                self:setHidsParams(self.mCloseUps[name]:getHidList(true), {active = false})
                --if self.mCloseUps[name].state.active then
                    self.mDisplay:set_element_eh('cul_'..name,
                        function()
                            self:onCloseUpOpen(self.mCloseUps[name])
                        end)
                --end
                self.mDisplay:get_element('cul_'..name):setActive(self.mCloseUps[name].state.active)
            end
        end)

    -- ExtraLevels +
    HOLevel.opened = true
--    Media:playBackground( 'level'..Profile:getLevel() )
    --Media:playBackground(self.mLocation.mName)
    Media:playBackground(self.mLocation.mName..'Amb')

    -- ExtraLevels -
    if not HOLevel:isExtraLevel() then
        if self.mRemark ~= nil and not self.visited then
            --Bubble:show(self.mRemark, 90, 630, 550, 80, Bubble.TYPE_RIGHT_UP, true, function() Tutorial:onEvent('scene_enter') end)
            Panel:showRobinMessage(self.mRemark, 15)
            Hint.mTimer = 0.1
        end

        Panel:setAvatarClickHandler(
            function()
                if self.mRemark ~= nil then
                    Panel:showRobinMessage(self.mRemark, 15)
                end
            end)

        self.visited = true
    end

    -- ExtraLevels +
    self:startCULEffects()
    self.mDisplay:start_amb_effects()

    -- ExtraLevels -
    if not HOLevel:isExtraLevel() then
        local sceneInvList = Profile:getInvList(self.mLocation.mName, self.mScene)
        for i = 1, #sceneInvList do
            Inventory:addItem(sceneInvList[i].elem)
            --if sceneInvList[i].active then
            Inventory:setItemState(sceneInvList[i].elem, sceneInvList[i].state)
            --end
        end

        local selection = clone_table(self.mLocation.mSharedHids)
        for i = 1, #self.mLocation.mSharedHids do
            if string.find(self.mLocation.mSharedHids[i].elem, 'hid_'..self.mScene..'_') == nil then
                local hid = self.mDisplay:get_element(self.mLocation.mSharedHids[i].elem)
                local visible = not self.mLocation.mSharedHids[i].capture --math.random() < 0.8
                if hid ~= nil then
                    hid:setVisible(visible)
                else
                    for key, cu in pairs(self.mCloseUps) do
                        hid = cu.mDisplay:get_element(self.mLocation.mSharedHids[i].elem)
                        if hid ~= nil then
                            hid:setVisible(visible)
                            break
                        end
                    end
                end
            end
        end
    end
    
    local func = function(elem)
            local name = string.gsub(elem:getName(), "extra_", "")
            state = Profile:getExtraState(self.mLocation.mName, name)
            if state == nil then
                state = {}
                state.visible = true
                state.play_once = nil
                state.play_loop = nil
                state.frame = 0
            end
            self:setExtraParams(name, state)
            Profile:setExtraState(self.mLocation.mName, name, state)
        end

    self:processChildren(self.mDisplay, "", "extra_", func)

    
     --self:loadExtrasList()
     --
end

----------------------------------------------------------------------------------------------------
function HOLevel:startCULEffects()
end

----------------------------------------------------------------------------------------------------
function HOLevel:startCULEffects()
    table.foreach(self.mCloseUps,
        function(name)
            if self.mCloseUps[name]:getHidCount() > 0 then
                self.mDisplay:link_effect("hint_place",'cul_'..name)
            end
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:setRemark(aText)
    self.mRemark = aText
end

----------------------------------------------------------------------------------------------------
function HOLevel:updateRemark(aText)
    self:setRemark(aText)
    if self.mRemark ~= nil then
        Panel:showRobinMessage(self.mRemark, 15)
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:place(enter)
    if enter == nil then
        enter = true
    end

    ho:setLevel(self)
    Hint:reset()

    Panel:set_task_text(self.mTask) -- для ExtraLevels collect all ojects

    table.foreach(self.mHids,
        function(aName)
            if not self.mHids[aName].state.found then
                self.mHids[aName].elem:setVisible(self.mHids[aName].state.visible)

                if self.mHids[aName].state.attached and enter then
                    ho:add(self.mHids[aName].elem, self.mHids[aName].parent, self.mHids[aName].assist)
                    ho:setActive("hid_"..self.mScene.."_"..aName, self.mHids[aName].state.active)
                end
            else
                self.mHids[aName].elem:setVisible(false)
                self.mHids[aName].elem:setActive(false)
            end
        end)

    table.foreach(self.mInteracts,
        function(aName)

            state = Profile:getInteractState(self.mLocation.mName, self.mScene, aName)
            if state == nil then
                state = {}
                state.visible = true
                state.twoWay = false
                state.mouse = nil
                state.activated = false
                state.attached = false
                state.active = false
                Profile:setInteractState(self.mLocation.mName, self.mScene, aName, state)
            end
            self.mInteracts[aName].state = state
            --self:setInteractParams(aName, state)

            local elem = self.mInteracts[aName].elem

            if self.mInteracts[aName].state.attached and enter then
                self:activateInteract(aName)
            end

            self:setInteractParams(aName, {active = self.mInteracts[aName].state.active})

            elem:setVisible(self.mInteracts[aName].state.visible)
            if self.mInteracts[aName].state.visible then
                if self.mInteracts[aName].state.activated then
                    if elem:getCharacter():get_frame_count() > 1 then
                        local frame = elem:getCharacter():get_frame_count() - 1
                        play_clip(elem:getCharacter(), {frame_begin = frame, frame_end = frame})
                    else
                        self:showElement("int_"..self.mScene.."_"..aName, false)
                    end
                else
                    play_clip(elem:getCharacter(), {frame_begin = 0, frame_end = 0})
                end
            end
        end)

    table.foreach(self.mLocation.mExtras,
        function(aName)
            local elem = self.mLocation.mExtras[aName].elem
            elem:setVisible(self.mLocation.mExtras[aName].state.visible)

            if self.mLocation.mExtras[aName].visible then
                if self.mLocation.mExtras[aName].state.frame ~= nil then
                    local frame = self.mLocation.mExtras[aName].state.frame
                    play_clip(elem:getCharacter(), {frame_begin = frame, frame_end = frame})
                end

                if self.mLocation.mExtras[aName].state.play_loop ~= nil then
                    local loop = self.mLocation.mExtras[aName].state.play_loop
                    play_clip(elem:getCharacter(), {looped = loop})
                end

                if self.mLocation.mExtras[aName].state.play_once ~= nil then
                    play_clip(elem:getCharacter())
                end
            end
        end)

    table.foreach(self.mMixes,
        function(name)
            ho:setChallengeItem('hid_'..self.mScene..'_'..name)
            for k, v in pairs(self.mMixes[name]) do
                ho:setChallengeItem('hid_'..self.mScene..'_'..k)
            end
        end)

    if enter then
        self.mIsStarted = (Profile:getSceneState(self.mLocation.mName, self.mScene) == 'started')
        if not self.mIsStarted then
            self:postEvent('start')
            Profile:onSceneStart(self.mLocation.mName, self.mScene)
            self.mIsStarted = true
        end
        self:postEvent('show')
    end

    HOLevel.found_keys_now = 0
    for i = 1, 15 do
        local key = self.mDisplay:get_element('key_'..i)
        --if i <= 5 then
            if key ~= nil then
                local idx_base = 3 * (self.mScene - 1) + 1
                if i == idx_base or i == idx_base + 1 or i == idx_base + 2 then
                    if not self.mLocation.mKeys[i] then
                        key:setVisible(true)

                        if self.keyparams == nil then
                            self.keyparams = {}
                        end

                        local key_idx = i - idx_base + 1
                        self.keyparams[key_idx] =
                        {
                            elem = key,
                            pos = Vec2(key:getPos().x, key:getPos().y),
                            scale = key:getScale(),
                            alpha = key:getAlpha(),
                            angle = key:getAngle(),
                            parent = key:getParent(),
                            depth = key:getDepth()
                        }
                        self.mDisplay:set_element_eh('key_'..i, function() self:onKeyClick(key_idx) end)
                    else
                        key:setVisible(false)
                        HOLevel.found_keys_now = HOLevel.found_keys_now + 1
                    end
                else
                    key:setVisible(false)
                end
            end
        --else
           -- key:setVisible(false)
        --end
    end

    local level = Levels:getCurrentLevel()
    local keycount = self:getKeysCount()
    for i = 1, 3 do
        local keyframe = 0
        if i <= keycount then
            keyframe = 1
        end
        Panel:play_clip('loc'..i, {frame_begin = keyframe, frame_end = keyframe})
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:getKeysCount()
    local count = 0

    local idx_base = 3 * (self.mScene - 1) + 1
    for i = idx_base, idx_base + 2 do
        if self.mLocation.mKeys[i] then
            count = count + 1
        end
    end

    return count
end

----------------------------------------------------------------------------------------------------
function HOLevel:onKeyClick(key_idx)
	
	if self.keyparams== nil then
        return
    end
    
    if self.keyparams[key_idx] == nil then
        return
    end

    if not self.keyparams[key_idx].elem:isActive() then
        return
    end

    local loc_key_idx = key_idx + 3 * (self.mScene - 1)
    trace(loc_key_idx)

    self.mLocation.mKeys[loc_key_idx] = true
    local level = Levels:getCurrentLevel()
    local keypos = self:getKeysCount()
    local params = self.keyparams[key_idx]
    local key = self.keyparams[key_idx].elem

	HOLevel.found_keys_now = HOLevel.found_keys_now + 1
	--Profile:getKeysFoundNow(self.mLocation.mName, HOLevel.found_keys_now)
    Profile.data.keysCollected = Profile.data.keysCollected + 1
    local level = Levels:getLevelFromScene(self.name, self.mScene)
    if level then
        level:addKey(self.name)
    end

    key:setParent(Panel:get_element('loc'..keypos):getCharacter(), -1)
    play_clip(key:getCharacter(), {frame_begin = 1, frame_end = 1})
    key:setActive(false)
    Media:soundEvent('hid.pickup')
    Tutorial:sendMessage('key.found')
    ho:addFly('key_'..loc_key_idx, key, key:getPos(), Vec2(0, 0),
        function()
            play_clip(key:getCharacter(), {frame_begin = 0, frame_end = 0})

            key:setParent(params.parent, params.depth)

            key:setVisible(false)

            key:setPos(params.pos)
            key:setScale(params.scale)
            key:setAngle(params.angle)
            key:setAlpha(params.alpha)


            Panel:play_clip('loc'..keypos, {frame_begin = 1, frame_end = 1})
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:leave()

    Tutorial:sendMessage('closeup.click')
    Tutorial:leaveChapter()

    self.mActionTimers = nil

    Media:stopBackground(self.mLocation.mName..'Amb')

    self.mDisplay:stop_amb_effects()

    table.foreach(self.mCloseUps, function(name) self.mCloseUps[name]:hide() end)

    stop_all_effects()
    removeUpdateListener(self)
    Inventory:dropElement()
    ho:clear()

    Panel:reset_pos()
    Panel:set_task_text(self.mTask)

    table.foreach(self.mInteracts,
        function(aName)
            if self.mInteracts[aName].linked_effect ~= nil then
                self.mDisplay:unlink_effect(self.mInteracts[aName].elem:getName())
                self.mInteracts[aName].linked_effect = nil
            end
            self:deactivateInteract(aName)
        end)

    self.mDisplay:set_element_eh("background", nil)

    ho:lock(false)
    Inventory:lock(false)
    mouse:disable(false)
    self.mPenaltyTimer = 0.0

    Panel:showTimer(false)

    HOLevel.opened = false

    Panel:closeRobinMessage()

    --[[local invList = Inventory:getList()
    local sceneInvList = Profile:getInvList(self.mLocation.mName, self.mScene)
    for i = #sceneInvList, 1, -1 do
        sceneInvList[i] = nil
    end
    for i = 1, #invList do
        table.insert(sceneInvList, {elem = invList[i].name, state = invList[i].state})
    end]]

    save_game()
    HOLevel.current = nil -- after save_game() !

    self:cleanHids()

    Inventory:clear()
    --Media:stopBackground( 'level'..HOLevel.current.mLevel )
    
    --HOLevel.found_keys_now = 0
end

----------------------------------------------------------------------------------------------------
function HOLevel:commitState()
    if HOLevel.current == nil then
        return
    end

    local invList = Inventory:getList()
    local sceneInvList = Profile:getInvList(HOLevel.current.mLocation.mName, HOLevel.current.mScene)
    for i = #sceneInvList, 1, -1 do
        sceneInvList[i] = nil
    end
    for i = 1, #invList do
        table.insert(sceneInvList, {elem = invList[i].name, state = invList[i].state})
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:setTask(aTask)
    Profile:setSceneTask(self.mLocation.mName, self.mScene, aTask)
    self.mTask = aTask
    Panel:set_task_text(aTask)
end

----------------------------------------------------------------------------------------------------

function HOLevel:getLevelActive(name)
    local count = Profile.data[name]['pass']
    if count ~= nil and count >= 5 then
        return true
    end
    return false
end

----------------------------------------------------------------------------------------------------
function HOLevel:updateAmbListeners()
    table.foreach(self.mAmbListeners,
        function(key)
            local amb = self.mLocation.mAmbients[self.mAmbListeners[key].name].elem:getCharacter()
            local frame = amb:get_current_frame()
            if frame ~= self.mAmbListeners[key].currentFrame then
                self.mAmbListeners[key].currentFrame = frame
                if frame == self.mAmbListeners[key].targetFrame then
                    Media:soundEvent(self.mAmbListeners[key].evt)
                end
            end
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:update(aElapsed)

    self:updateAmbListeners()

    if HODialogs:isVisible() or Cutscene:isVisible() then
        return
    end

    if self.showWin and HOLevel.playing_interacts == 0 and not ho:isFlying() and not Cutscene:isVisible() then
        HOLevel.locked = false
        self.showWin = false
        
        if self.mLevel == Profile:getLevel() then
            HODialogs:show(true)
            HODialogs:switchScreen("loc_win")
            HODialogs:get_element("loc_win"):findChild("lbl_keys"):setText(HOLevel.found_keys_now)
            HODialogs:get_element("loc_win"):findChild("lbl_keys_total"):setText(Profile.data.keysCollected)
            timer_mgr:add_timer(function() 
                level_mgr:switch_to_level("Map") 
                fade_panel:fade_out() 
                HODialogs:show(false) 
                end, 2.0, 1, "loc_win")
        else
            HODialogs:show(true)
            HODialogs:switchScreen("level_win")
            HODialogs:get_element("level_win"):findChild("lbl_keys"):setText(HOLevel.found_keys_now)
            HODialogs:get_element("level_win"):findChild("lbl_keys_total"):setText(Profile.data.keysCollected)
            start_effect_at("win", Vec2(512, 384))
            timer_mgr:add_timer(function() 
                Levels:getLevel(self.mLevel):onWin()
                HODialogs:show(false) 
                end, 2.0, 1,"level_win")
        end

        return
    end

--[[    if Profile:getDifficulty() == Profile.DIFFICULTY_HARD and not self:isWin() then
        self.mTime = self.mTime - aElapsed
        if self.mTime >= 0 then
            Panel:updateTimer(self.mTime)
        else
            HODialogs:show(true)
            HODialogs:switchScreen("out_time")
            start_effect_at("loose", Vec2(512, 384))
        end
    end]]

    if self.mPenaltyTimer > 0 then
        self.mPenaltyTimer = self.mPenaltyTimer - aElapsed
        if self.mPenaltyTimer > 0 then
            return
        end

        ho:lock(false)
        Inventory:lock(false)
        mouse:disable(false)
        trace('penalty: off')
    end

    if self.mClickTimer > 0 then
        self.mClickTimer = self.mClickTimer - aElapsed
        if self.mClickTimer > 0 then
            if self.mClicks >= HOLevel.PENALTY_CLICK_COUNT then
                self.mClicks = 0
                self.mClickTimer = 0.0
                self.mPenaltyTimer = HOLevel.PENALTY_TIME
                ho:lock(true)
                start_effect_at("police", Vec2(512, 384))
                Media:soundEvent('penalty')
                Inventory:lock(true)
                mouse:disable(true)
                trace('penalty: on')
            end
        else
            self.mClicks = 0
        end
    end

    if self.mActionTimers ~= nil then
        table.foreach(self.mActionTimers,
            function(name)
                self.mActionTimers[name] = self.mActionTimers[name] - aElapsed
                if self.mActionTimers[name] <= 0.0 then
                    self.mDisplay:link_effect('actionSpecular', self.mInteracts[name].elem:getName())
                    self.mInteracts[name].linked_effect = true
                    self.mActionTimers[name] = nil
                end
            end)
    end

	return 0
end

----------------------------------------------------------------------------------------------------
function HOLevel:onBackgroundClick()

    if HODialogs:isVisible() or HOLevel.locked then
        return
    end

    if self.mPenaltyTimer <= 0 then
        self.mClicks = self.mClicks + 1
        self.mClickTimer = HOLevel.PENALTY_CAP
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:hideCloseUps()
    if HOLevel.current == nil then
        return
    end

    table.foreach(HOLevel.current.mCloseUps,
        function(name)
            if HOLevel.current.mCloseUps[name]:isVisible() then
                HOLevel.current.mCloseUps[name]:hide()
            end
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:onCloseUpOpen(aCloseUp)

    if Closeup.active or HOLevel.locked then
        return
    end

    Tutorial:sendMessage('closeup.click')

    trace(mouse:getConnectedName())
    if aCloseUp.state.key ~= nil then
        if aCloseUp.state.key ~= mouse:getConnectedName() then
            Panel:showRobinMessage('ids_needs_'..aCloseUp.state.key, 6)
            return
        end

        mouse:setConnCharacter(nil)
        Inventory:removeItem(aCloseUp.state.key)
        aCloseUp.state.key = nil
    end

    self.mDisplay:stop_amb_effects()
    aCloseUp:show()
    aCloseUp:setCloseCB(function() self:onCloseUpClose(aCloseUp) end)

    self.safeHidsParams = {}
    table.foreach(self.mHids,
        function(name)
            self.safeHidsParams[name] = self.mHids[name].state.active
        end)

    self:setHidsParams(self:getHidList(), {active = false})
    self:setHidsParams(aCloseUp:getHidList(true), {active = true})

    self.safeIntParams = {}
    table.foreach(self.mInteracts,
        function(name)
            if self.mInteracts[name].linked_effect ~= nil then
                self.mDisplay:unlink_effect(self.mInteracts[name].elem:getName())
                self.mInteracts[name].linked_effect = nil
            end
            self.safeIntParams[name] = self.mInteracts[name].elem:isActive()
            self.mInteracts[name].elem:setActive(false)
            --self:setInteractParams(name, {active = false})
        end)

    stop_all_effects()
    Media:soundEvent('closeup.open')
    
end

----------------------------------------------------------------------------------------------------
function HOLevel:onCloseUpClose(aCloseUp)
    self:startCULEffects()

    for name, state in pairs(self.safeHidsParams) do
        self:setHidsParams({name}, {active = state})
    end
    self.safeHidsParams = {}

    table.foreach(self.safeIntParams,
        function(name)
            self.mInteracts[name].elem:setActive(self.safeIntParams[name])
            if self.safeIntParams[name] then
                self.mDisplay:link_effect('actionSpecular', self.mInteracts[name].elem:getName())
                self.mInteracts[name].linked_effect = true
            end
        end)
    self.safeIntParams = {}


    self:setHidsParams(aCloseUp:getHidList(true), {active = false})
    Media:soundEvent('closeup.close')
    
    self.mDisplay:start_amb_effects()
end

----------------------------------------------------------------------------------------------------
function HOLevel:cleanHids()
    table.foreach(self.mHids,
        function(name)
            local elem = self.mHids[name].elem
            elem:setParent(self.mHids[name].elem_parent, self.mHids[name].elem_depth)

            elem:setVisible(true)
            elem:setActive(false)

            elem:setPos(self.mHids[name].elem_pos)
            elem:setScale(self.mHids[name].elem_scale)
            elem:setAngle(self.mHids[name].elem_angle)
            elem:setAlpha(self.mHids[name].elem_alpha)

            play_clip(elem:getCharacter(), {frame_begin = 0, frame_end = 0})
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:cleanInteracts()
    table.foreach(self.mInteracts,
        function(name)
            local elem = self.mInteracts[name].elem

            elem:setVisible(true)
            play_clip(elem:getCharacter(), {frame_begin = 0, frame_end = 0})
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:cleanAll()
    table.foreach(HOLevel.list,
        function(i)
            local level = HOLevel.list[i]
            level:cleanHids()
            level:cleanInteracts()
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:pickAll()
    if HOLevel.current == nil then
        return
    end

    table.foreach(HOLevel.current.mHids,
        function(aName)
            local state = HOLevel.current.mHids[aName].state
            if not state.found and state.visible and state.attached and state.active then
                ho:click('hid_'..HOLevel.current.mScene..'_'..aName)
            end
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevel:pickKey(key)
    if HOLevel.current == nil then
        return
    end

    HOLevel.current:onKeyClick(key)
end

----------------------------------------------------------------------------------------------------
function HOLevel:setCloseUpKey(aCloseup, aItem)
    self.mCloseUps[aCloseup].state.key = aItem
end

----------------------------------------------------------------------------------------------------
function HOLevel:replaceHid(aOldHidName, aNewHidName)
    if self.mHids[aOldHidName] == nil or self.mHids[aNewHidName] == nil then
        return
    end

    local oldState = self.mHids[aOldHidName].state
    if oldState.attached and not oldState.found and not oldState.inventory then

        local newState = self.mHids[aNewHidName].state
        if not newState.attached and not newState.found and not newState.inventory then

            newState.active = oldState.active
            oldState.active = false
            --oldState.found = true
            oldState.attached = false
            newState.attached = true

            ho:replace(self.mHids[aOldHidName].elem, self.mHids[aNewHidName].elem,
                self.mHids[aNewHidName].parent, self.mHids[aNewHidName].assist)
        end
    end
end

----------------------------------------------------------------------------------------------------
function HOLevel:captureObjects(aHidList)
    for i = #self.mLocation.mSharedHids, 1, -1 do
        for j = 1, #aHidList do
            if 'hid_'..self.mScene..'_'..aHidList[j] == self.mLocation.mSharedHids[i].elem then
                --table.remove(self.mLocation.mSharedHids, i)
                --table.remove(aHidList, j)
                self.mLocation.mSharedHids[i].capture = true
                break
            end
        end
    end
end


----------------------------------------------------------------------------------------------------
function HOLevel:isExtraLevel()
    return (HOLevel.ExitTarget ~= '')
end

----------------------------------------------------------------------------------------------------
function HOLevel:addAmbFrameSoundEvent(name, frame, event)
    if self.mLocation.mAmbients[name] == nil then
        return
    end

    local amb = self.mLocation.mAmbients[name].elem:getCharacter()
    local current = amb:get_current_frame()

    self.mAmbListeners[name..frame] = {currentFrame = current, targetFrame = frame, name = name, evt = event}
end

----------------------------------------------------------------------------------------------------
function HOLevel:removeAmbFrameSoundEvent(name, frame)
    self.mAmbListeners[name..frame] = nil
end
