-- hidden object functions (main panel, elements flying, click handling)

ho = {}
ho.max_count = 12
ho.hide_frame_count = 20

ho.objects = {}

ho.level = nil;

ho.fly = {}

ho.mix = nil -- может быть только один в любой момент времени

ho.mIsLocked = false

--ho.mMixing = false

----------------------------------------------------------------------------------------------------
function ho:getCountLeft()
	return #ho.objects	
end

----------------------------------------------------------------------------------------------------
function ho:add(el, parent, assist)
    --trace(el:getName())

	if #ho.objects >= ho.max_count then
		trace("Too many HO! ")
		return
	end

    Hint:addElement(el, parent, assist)

	local name_base, name_suffix = split_name(el:getName())
	local index = ho:get(name_base)
	
	if index == 0 then
		table.insert(ho.objects, {name = name_base, mp_index = #ho.objects + 1, elems = {el} } )
		Panel:set_ho_text(#ho.objects, "ids_"..name_base)
	else
		table.insert(ho.objects[index].elems, el)
		Panel:set_ho_text(ho.objects[index].mp_index, "ids_"..name_base.."_"..#ho.objects[index].elems)
	end
	
	el:setActive(true)
	el:setEventHandler(eiLeftClick, "ho:click(\""..el:getName().."\")")

end

-----------------------------------------------------------------------------------------------------
--[[
function ho:remove(name)

    local id =  ho:get(name)
    if id == 0 then return end
    
    if ho.fly[name] ~= nil then
        ho.fly[name]:term()
        table.remove(ho.fly,ho.fly[name])
    end

    for j = 1, #ho.objects[id].elems do
        if ho.objects[id].elems[j] ~= nil then
            ho.objects[id].elems[j]:setEventHandler(eiLeftClick, "")
        end
    end
    
    table.remove(ho.objects,id)

	Panel:play_clip("hoLine"..id, {frame_begin = 0, frame_end = 0})
	Panel:set_ho_text(id, "")

end
]]

function ho:replace(old, new, newparent, newassist)

    local id =  ho:get(old:getName())
    if id == 0 then
        return
    end

    Hint:removeElement(old)
    Hint:addElement(new, newparent, newassist)

    ho.objects[id].name = new:getName()
    ho.objects[id].elems = {new}
	Panel:set_ho_text(id, "ids_"..new:getName())
	
	old:setActive(false)
	old:setEventHandler(eiLeftClick, "")

    new:setActive(true)
	new:setEventHandler(eiLeftClick, "ho:click(\""..new:getName().."\")")

end

----------------------------------------------------------------------------------------------------
function ho:playLine(index)
    local rand = get_random(1, 4)
    trace("line index "..rand)
    local line = Panel:get_element("hoLine"..index)
    play_clip(line:getCharacter(), {label_begin = "line"..rand.."_begin", label_end = "line"..rand.."_end"})
end

----------------------------------------------------------------------------------------------------
function ho:set_found(index, subInd)
    local ind = 0

	for i = 1, #ho.objects do
		if index == ho.objects[i].mp_index then
			ind = i
		end	
	end

    if ind == 0 then
        return
    end

	if #ho.objects[ind].elems == 1 then
	    ho:playLine(ho.objects[ind].mp_index)
		--Panel:set_ho_text(ho.objects[ind].mp_index, "")	
		ho:setActive(ho.objects[ind].name, false, true)
		--table.remove(ho.objects, ind)
	else
		table.remove(ho.objects[ind].elems, subInd)
		
		if #ho.objects[ind].elems > 1 then
			Panel:set_ho_text(ho.objects[ind].mp_index, "ids_"..ho.objects[ind].name.."_"..#ho.objects[ind].elems)
		else
			Panel:set_ho_text(ho.objects[ind].mp_index, "ids_"..ho.objects[ind].name)
		end
		
	end

end

----------------------------------------------------------------------------------------------------
function ho:get(name)

	for i = 1, #ho.objects do
		if name == ho.objects[i].name then
			return i
		end	
	end
	
	return 0
	
end

----------------------------------------------------------------------------------------------------
function ho:has(name)
    return ho:get(name) > 0
end

----------------------------------------------------------------------------------------------------
function ho:setChallengeItem(name)
    index = ho:get(name)
    if index > 0 then
          Panel:get_element("ho"..ho.objects[index].mp_index):setTextColor(100, 187, 53, 255)
    end
end

----------------------------------------------------------------------------------------------------
function ho:setActive(name, state, found)
    index = ho:get(name)
    
    if index <= 0 then
        return
    end

    if state == false then
        if found ~= nil and found then
            Panel:get_element("ho"..ho.objects[index].mp_index):setTextColor(100, 100, 100, 255)
        else
            Panel:get_element("ho"..ho.objects[index].mp_index):setTextColor(255, 20, 20, 255)
        end
    else
        Panel:get_element("ho"..ho.objects[index].mp_index):setTextColor(255, 255, 255, 255)
    end

    for i = 1, #ho.objects[index].elems do
        ho.objects[index].elems[i]:setActive(state)
    end

end

----------------------------------------------------------------------------------------------------
function ho:click(name)
    
    if HODialogs:isVisible() then
        return
    end

    if ho.mIsLocked then
        return
    end

    if mouse:getConnectedName() ~= '' then
        return
    end

	local name_base, name_suffix = split_name(name)
	local ind = ho:get(name_base)
	
	local elInd = 0
	local elem = nil
	
	if ind > 0 then
        for i = 1, #ho.objects[ind].elems do
            if ho.objects[ind].elems[i]:getName() == name then
                elInd = i
                break
            end
        end

        elem = ho.objects[ind].elems[elInd]
    else
        local hidKey = string.gsub(name, 'hid_'..ho.level.mScene..'_', '')
        elem = ho.level.mHids[hidKey].elem
	end

	start_effect_at("Item_onPick_up", elem:getPos(true))
	Media:soundEvent('hid.pickup')
	play_clip(elem:getCharacter(), {looped = false})

    elem:setActive(false)
    Hint:removeElement(elem)

    local tSlot = -1
    if ho.level ~= nil then
        tSlot = ho.level:onFind(elem:getName())
    end

    if tSlot >= 0 then
        local init_pos = elem:getPos(true)
        local source = {}
        local target = {}

        local callback = nil
        local index = nil
        if ind > 0 then
            index = ho.objects[ind].mp_index
        end

        if tSlot >= 1 and tSlot <= 3 then
            -- предмет летит в инвентарь, пусть летит к соответствующему слоту
            Inventory:activateSlot(tSlot, false)
            Inventory:showSlotItem(tSlot, false)

            local slot_pos = Panel:getInventorySlot(tSlot):getPos(true)
            source = {x = init_pos.x - slot_pos.x, y = init_pos.y - slot_pos.y}
            target = {x = 0, y = 0}

            elem:setParent(Panel:getInventorySlot(tSlot):getCharacter())
            elem:setPos(Vec2(source.x, source.y))

            callback = function()
                Inventory:activateSlot(tSlot, true)
                Inventory:showSlotItem(tSlot, true)
                elem:setVisible(false)
                elem:setPos(Vec2(-2000, -2000))
                trace('hid landed: '..elem:getName())
                if index ~= nil then
                    ho:set_found(index, elInd)
                end
                stop_effect('roundedSquare'..tSlot)
                start_effect_at('SparksInside', slot_pos)
            end
            
            start_effect_at('roundedSquare'..tSlot, slot_pos)
        else
            -- в инвентарь предмет не летит, посылаем его к своей записи
            local rec_pos = Panel:getHOListRecord(index):getPos(true)
            local panel_pos = Panel:get_element("panel"):getPos(true)
            
            source = {x = init_pos.x - panel_pos.x, y = init_pos.y - panel_pos.y}
            target = {x = rec_pos.x - panel_pos.x, y = rec_pos.y - panel_pos.y}

            elem:setParent(Panel:get_element("panel"):getCharacter(), -1)
            elem:setPos(Vec2(source.x, source.y))

            callback = function()
                elem:setVisible(false)
                ho:set_found(index, elInd)
            end
            target.x = target.x + 73.0
        end

        
        ho:addFly(name, elem, source, target, callback)
    end

--	timer_mgr:add_timer(function() elem:setAlpha(elem:getAlpha() - 1 / ho.hide_frame_count) end, 3, ho.hide_frame_count)
--	timer_mgr:add_timer(function() elem:setVisible(false) end, 3, 1)
end

function ho:addFly(name, elem, source, target, callback)
    ho.fly[name] = FlyPath:new(elem, source, target, callback)
end

-----------------------------------------------------------------------------------------------------
function ho:setLevel(level)
    for i = 1, 12 do
		Panel:set_ho_text(i, "")
	end

    ho.level = level
end

-----------------------------------------------------------------------------------------------------
function ho:clear()
    table.foreach(ho.fly,
        function(aName)
            if ho.fly[aName] ~= nil then
                ho.fly[aName]:term()
            end
        end)
    ho.fly = {}

    for i = 1, #ho.objects do
        for j = 1, #ho.objects[i].elems do
            ho.objects[i].elems[j]:setEventHandler(eiLeftClick, "")
        end
	end

	for i = 1, 12 do
	    Panel:play_clip("hoLine"..i, {frame_begin = 0, frame_end = 0})
	    Panel:set_ho_text(i, "")
	end

    ho.objects = {}
end

-----------------------------------------------------------------------------------------------------
function ho:update(aElapsed)

    table.foreach(ho.fly,
        function(aName)
            if ho.fly[aName] ~= nil then
                local isFlyEnds = ho.fly[aName]:update(aElapsed)
                if isFlyEnds then
                    ho.fly[aName] = nil
                end
            end
        end)

    ho:checkMix()
end

-----------------------------------------------------------------------------------------------------
function ho:isFlying()
    for key, value in pairs(ho.fly) do
        return true
    end

    return false
end

-----------------------------------------------------------------------------------------------------
function ho:lock(aState)
    ho.mIsLocked = aState
end

-----------------------------------------------------------------------------------------------------
function ho:startMixing(aResult, aUnits)

    HOLevel.locked = true
    ho.mix = {}

    ho.mix.result = aResult
    ho.mix.units = aUnits

end

-----------------------------------------------------------------------------------------------------
function ho:checkMix()
    if ho.mix == nil then
        return
    end

    local unitElems = {}
    table.foreach(ho.mix.units,
        function(aIdx)
            if Inventory:isPlaced(ho.mix.units[aIdx]) then
                tElem = Inventory:get(ho.mix.units[aIdx])
                if tElem ~= nil and ho.fly[tElem:getName()] == nil then
                    table.insert(unitElems, {elem = tElem, idx = aIdx})
                end
            end
        end)

    if #unitElems ~= #ho.mix.units then
        return
    end

    local tLocPos = Panel:getMixAnchorPos()

    local count = #ho.mix.units
    local hidElem = nil
    local fly_callback = function()
            count = count - 1
            if count == 0 then
                table.foreach(ho.mix.units,
                    function(aIdx)
                        Inventory:removeItem(ho.mix.units[aIdx])
                    end)

                Inventory:addItem(ho.mix.result)
                hidElem = ho.level.mHids[ho.mix.result].elem

                hidElem:setPos(tLocPos)
                hidElem:setParent(Panel:getMixAnchor():getCharacter())
                Panel:showRobinMessage('ids_mix_'..ho.mix.result, 15)
                
                Media:soundEvent('mix')

                ho.mix = nil
            end
        end

    local mix_callback = function()
            if hidElem ~= nil then
                Panel:closeRobinMessage()
                ho:click(hidElem:getName())
                Panel:showMix(false, 0.5)
                HOLevel.locked = false
            end
        end

    local tCoeff = -0.5

    local min_time = 0.0
    table.foreach(unitElems,
        function(key)
            local localPos = unitElems[key].elem:getPos()
            local pos = unitElems[key].elem:getPos(true)

            local target = Vec2(localPos.x + tLocPos.x - pos.x, localPos.y + tLocPos.y - pos.y)

            ho.fly[ho.mix.units[unitElems[key].idx]] = MixFlyPath:new(unitElems[key].elem, localPos, target, fly_callback, tCoeff)
            if min_time < ho.fly[ho.mix.units[unitElems[key].idx]].mFlyTime then
                min_time = ho.fly[ho.mix.units[unitElems[key].idx]].mFlyTime
            end
            tCoeff = tCoeff + 1.2
        end)

    Panel:showMix(true, min_time)
    Panel:setMixCallback(mix_callback)
    Panel:setMixItemName('ids_'..ho.level.mHids[ho.mix.result].elem:getName())
    HOLevel:hideCloseUps()
end