
----------------------------------------------------------------------------------------------------
HOLevelExtra = {}

HOLevelExtra.list = {}


function HOLevelExtra:isEmpty()
    for i, v in pairs(HOLevelExtra.list) do
        return false
    end

    return true
end

function HOLevelExtra:new(location)
    obj = {}
    setmetatable(obj, self)
    self.__index = self

    obj.mLocation = location

    HOLevelExtra.list[location] = obj

    return obj
end

function string:split(sep)
    local sep, fields = sep or ":", {}
    local pattern = string.format("([^%s]+)", sep)
    self:gsub(pattern, function(c) table.insert(fields, c) end)
    return fields
end


----------------------------------------------------------------------------------------------------
function HOLevelExtra: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 HOLevelExtra:loadCloseUps()
    self.mCloseUps = {}
    local func = function(elem)
        local name = string.gsub(elem:getName(), "cul_", "")
        for i = 1,5 do
            self.mCloseUps[name..i] = Closeup:new(name, i)
            self.mCloseUps[name..i].state = true
            self:activateCloseUp(name,i,true, 1 == i)
            self.mCloseUps[name..i]:setAllFound()
        end
    end
    self:processChildren(self.mDisplay, "", "cul_", func)
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:activateCloseUp(name,scene, state, effect)

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

    self.mCloseUps[name..scene].state = 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..scene])
            end)

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

----------------------------------------------------------------------------------------------------
function HOLevelExtra:onCloseUpOpen(aCloseUp)

    trace(mouse:getConnectedName())

    self.mDisplay:stop_amb_effects()
    stop_all_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.mHids, {active = false})
    --self:setHidsParams(aCloseUp:getHidList(false), {active = true},true)
	--all
	table.foreach(self.mCloseUps,
                    function(cu_name)
                        self:setHidsParams(self.mCloseUps[cu_name]:getHidList(false), {active = true, visible = true},true)
                    end)
	
    Media:soundEvent('closeup.open')
    
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:onCloseUpClose(aCloseUp)

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

    --self:setHidsParams(aCloseUp:getHidList(false), {active = false},true)
    --all
    table.foreach(self.mCloseUps,
                    function(cu_name)
                        self:setHidsParams(self.mCloseUps[cu_name]:getHidList(false), {active = false, visible = false},true)
                    end)
                    
    Media:soundEvent('closeup.close')
    
    self.mDisplay:start_amb_effects()
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:closeCloseups()
		if not self.mCloseUps then return end
		table.foreach(self.mCloseUps,
        function(name)
			self.mCloseUps[name]:hide()
        end)
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:leave()
	self:closeCloseups()
	Panel.map_button_callback = nil
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:onFind(aHidName)

    self.mHids[aHidName].state.found = true

	local close_closeup = false
	local closeup_name = nil
    table.foreach(self.mCloseUps,
        function(name)
            self.mCloseUps[name]:setFound(aHidName)
            if self.mCloseUps[name]:isVisible() and self.mCloseUps[name]:getHidCount() == 0 then
                --self.mDisplay:set_element_eh('cul_'..name, nil)
				close_closeup = true
                closeup_name = name
                local base_name = nil
                for i = 1, 5 do
					base_name = string.gsub(name, i,"")
                end
                self.mDisplay:get_element('cul_'..base_name):setActive(false)
            end
        end)
        
        if self:isAllFound() then
			HOLevel.locked = true
			timer_mgr:add_timer(function() 
			if closeup_name ~= nil then
				self.mCloseUps[closeup_name]:hide()
			end
			HOLevel.locked = false
			HOLevel.ExitTarget = ""
			level_mgr:switch_to_level("LockLevels") 
			fade_panel:fade_out()
			end, 2.0, 1);
		elseif close_closeup then
			timer_mgr:add_timer(function() self.mCloseUps[closeup_name]:hide() end, 2.0, 1);
        end
        return 0
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:setHidsParams(aItems, aParams, nokey)
    if aParams == nil then
        return
    end
    
    if nokey == nil then nokey = false end
    
    table.foreach(aItems,
                    function(tName)
                        if nokey then   
                            tName = aItems[tName]
                        end
                       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.mHids[tName].elem:setVisible(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
                                self.mHids[tName].elem:setActive(aParams.active)
                                if ho:has(tName) then
                                    ho:setActive(tName, aParams.active)
                                end
                            end

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

----------------------------------------------------------------------------------------------------
function HOLevelExtra:isAllFound()

    local result = true

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

    return result
end

----------------------------------------------------------------------------------------------------
function HOLevelExtra:start()
	HOLevelExtra.mName = self.mLocation
    self.mDisplay = level_mgr:load_level(self.mLocation)
    
    self:loadCloseUps()
    
     ho:setLevel(self)

    level_mgr:switch_to_level(self.mLocation)
    fade_panel:fade_out()
    Panel:show(true)
    Panel:set_task_text('ids_collect_ho')

    local hidList = {}
    local intList = {}
    local extraList = {}
    local keyList = {}

    if Profile.data[self.mLocation] ~= nil then
        keyList = Profile:getKeys(self.mLocation)

        for key, val in pairs(Profile.data[self.mLocation]) do
            local arr = key:split('_')
            local pref = arr[1]
            
            local tElem = self.mDisplay:get_element(key)
            if tElem then
				local is_mix = tElem:getMember("mix")
				tElem:setVisible(true)
				if is_mix == 'true' then
					tElem:setVisible(false)
					tElem = nil
				end
			end

            if pref == 'hid' and tElem then
                table.insert(hidList, {name = key, state = val})
            elseif pref == 'int' then
                self.mDisplay:get_element(key):setActive(false)
                table.insert(intList, {name = key, state = val})
            elseif pref == 'extra' then
                table.insert(extraList, {name = key, state = val})
            end
        end
    end
    
    table.foreach(self.mCloseUps,
                    function(cu_name)
                        table.foreach(self.mCloseUps[cu_name].mHids,
							function(key)
								local tElem = self.mCloseUps[cu_name].mDisplay:get_element(key)
								if tElem then
									local is_mix = tElem:getMember("mix")
									if is_mix ~= 'true' then
										tElem:setVisible(true)
										table.insert(hidList, {name = key})
									end
								end
								
							end)
                    end)

    self.mHids = {}
    local count = 0
    while count < 12 do
        local idx = get_random(1, #hidList + 1)
        local tElem = self.mDisplay:get_element(hidList[idx].name)
        local is_in_closup = false
        if not tElem then
            table.foreach(self.mCloseUps,
                    function(cu_name)
                        local hid = self.mCloseUps[cu_name].mDisplay:get_element(hidList[idx].name)
                        if hid ~= nil then
							self.mCloseUps[cu_name]:setNotFound(hidList[idx].name)
                            tElem = hid
                            is_in_closup = true
                        end
                    end)
        end
        
        --exclude interact and mix
        for i = 1, #intList do
			local name = tElem:getName()
			local int_name = intList[i].name
			local arr = name:split('_')
            local name = arr[3]
            arr = int_name:split('_')
            int_name = arr[3]
			if int_name == name then
				tElem = nil
				break
			end
		end
		if tElem then
			local el_pos = tElem:getPos(true)
			if el_pos.x < 0 or el_pos.y < 0 or el_pos.x > 1024 or el_pos.y > 768 then
				tElem = nil
			end
		end
        
        if tElem then
			if is_in_closup then
				tElem:setVisible(false)
				tElem:setActive(false)
			else 
				tElem:setVisible(true)
				tElem:setActive(true)
			end
			
			local rec =
			{
				elem = tElem,
				parent = tElem:getParent(),
				pos = Vec2(tElem:getPos().x, tElem:getPos().y),
				scale = tElem:getScale(),
				alpha = tElem:getAlpha(),
				angle = tElem:getAngle(),
				parent = tElem:getParent(),
				depth = tElem:getDepth(),
				state =
				{
					visible = true,
					attached = false,
					found = false,
					active = true,
					inventory = false,
				}
			}
			self.mHids[hidList[idx].name] = rec
			ho:add(rec.elem, rec.parent, nil)
			if is_in_closup then
				self.mHids[hidList[idx].name].state.active = false
				ho:setActive(hidList[idx].name, false, false)
			else 
				ho:setActive(hidList[idx].name, true, false)
			end
			
			table.remove(hidList, idx)
			count = count + 1
		end
	end

		self.mKeys = {}
		for i = 1, #keyList do
			local key = self.mDisplay:get_element('key_'..i)
			key:setVisible(not keyList[i])
			if not keyList[i] then
				if #self.mKeys < 3 then
					table.insert(self.mKeys, {elem = key, idx = i})
					local x = #self.mKeys
					self.mDisplay:set_element_eh('key_'..i, function() self:onKeyClick(x) end)
				else
					key:setVisible(false)
				end
			end
		end

		for i = 1, 3 do
			Panel:play_clip('loc'..i, {frame_begin = 0, frame_end = 0})
		end

		addUpdateListener(self)

		--Media:playBackground(self.mLocation)
		Media:playBackground(self.mLocation..'Amb')
		
		self.mDisplay:start_amb_effects()
		

		local size = self.mDisplay:get_element_count()
		for i = 0, size - 1 do
			elem = self.mDisplay:get_element_at(i)
			local elemName = elem:getName()
			local pref = elemName:split('_')
			if pref == 'amb' then
				play_clip(elem:getCharacter(), {looped = true})
			end
		end
	--end
end

function HOLevelExtra:update()
    
end

function HOLevelExtra:exit()
    ho:clear()
    self:cleanHids()
    self.mDisplay:stop_amb_effects()
    stop_all_effects()
    removeUpdateListener(self)
    
    --Media:stopBackground(self.mLocation)
    Media:stopBackground(self.mLocation..'Amb')
    save_game()
    HOLevelExtra.mName = nil
end

function HOLevelExtra:onKeyClick(key_idx)
    if self.mKeys[key_idx] == nil then
        return
    end

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

    local idx = self.mKeys[key_idx].idx
    Profile.data[self.mLocation]['keys'][idx] = true

    local keypos = 0
    for i = 1, 3 do
        if self.mKeys[i] ~= nil then
            keypos = keypos + 1
        end
    end

    local key = self.mKeys[key_idx].elem
    local s = key:getName()
    
    local parent = key:getParent()
    local depth = key:getDepth()
    local pos = Vec2(key:getPos(true).x, key:getPos(true).y)
    local scale = key:getScale()
    local angle = key:getAngle()
    local alpha = key:getAlpha()

    Profile.data.keysCollected = Profile.data.keysCollected + 1

    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')

    ho:addFly(key:getName(), key, key:getPos(), Vec2(0, 0),
        function()
            play_clip(key:getCharacter(), {frame_begin = 0, frame_end = 0})

            key:setParent(parent, depth)
            key:setVisible(false)

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

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

    self.mKeys[key_idx] = nil
end

function HOLevelExtra:cleanHids()
    table.foreach(self.mHids,
        function(name)
            local elem = self.mHids[name].elem
            elem:setParent(self.mHids[name].parent, self.mHids[name].depth)

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

            elem:setPos(self.mHids[name].pos)
            elem:setScale(self.mHids[name].scale)
            elem:setAngle(self.mHids[name].angle)
            elem:setAlpha(self.mHids[name].alpha)

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