dofile ('Data/Scripts/Common/HOLogic/HiddenObjectLogic.lua')

class 'HiddenObjectLogicED' (HiddenObjectLogic)

-------------------------------------------------------------------------------
HiddenObjectLogic.DEFAULT_INTERACTIVE_TIME = 1
-------------------------------------------------------------------------------

function HiddenObjectLogicED:__init(game_scene)
	HiddenObjectLogic.__init(self, game_scene)

	self.eventDispatcher = EventDispatcher(self)
	self.bMatch3Mode = false
	self.interactiveItems = {}	
end

function HiddenObjectLogicED:onLastItemFound() 
	local scene_name = self.game_scene:getPlayField():getName()
	
	for task_name, task in pairs(self.tasks) do
		RemoveActiveTaskState(scene_name, task)
	end
	
	if self:isLastDeal() then
		for i, object_name in ipairs(self.createdTaskObjects) do
			RemoveTaskObjectsFound(scene_name, object_name)
		end
	end
	
	local playfield = self.game_scene:getPlayField()
	local level_name = playfield.parent_level
  
    AddGameState(SCENE_CLOSED, scene_name)
	SetGameState(LAST_VISITED_SCENE, level_name)
    SetGameState(LAST_VISITED_SCENE, level_name, EGameStateTag.GENERAL)
		
	if playfield.match3 then     
        playfield.match3:complete()
    end
	    
	if getPrimaryGameStateTag() == EGameStateTag.EXTRA then
        if playfield.match3 then
            playfield.match3:clearSave()
        end		
		playfield:close()
	else
		if self.searchingTool then
			local function onAllItemsFound()
				playfield.timer:add(function()	
                                    if playfield.match3 then
                                        playfield.match3:clearSave()
                                    end 
									playfield:close()
								end, 1.5)
			end

			local function trigger_achievement_event()
				self.game_scene:getAchievmentsManager():handleEvent('on_ho_completed', 
					{['callback'] = onAllItemsFound, ['deal'] = self.dealIndex, ['scene_name'] = playfield:getName()})
			end
			playfield:getPanel():setMode(EPanelMode.QUEST)
			playfield:findTool(self.searchingTool, false, trigger_achievement_event)
		end
	end
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:setMatch3Mode(bMatch3Mode)
    self.bMatch3Mode = bMatch3Mode
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:isMatch3Mode()
    return self.bMatch3Mode
end
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
function HiddenObjectLogicED:autoFindObject(objectName)
    if current_scene:getPlayField().ho_logic:isTaskObject(objectName) then
        local level    = current_scene:getPlayField()
        local bindInfo = self:getInteractiveItemBind(objectName, 'itemName')
        local time = 0
        local bFindAvailable = true
        
        if bindInfo then
            if bindInfo.type == 'activeObject' then
              --  bFindAvailable, time = level:checkActiveObjectMouseDown(bindInfo.objectName, true)
            elseif bindInfo.type == 'dragObject' then
                local dragManager = current_scene:getPlayField():getDragManager()
                local dragObject  = dragManager:get( bindInfo.objectName )
                
                local object = dragObject:getDropTarget()
                for i = 1, #object do
                    dragObject:setDropOnTarget(object[i]:getName())                    
                end
                dragObject:setDropTargetsRespondable(false)               
            end
        end
        
        if bFindAvailable then
            SetTaskObjectFound(current_scene:getName(), objectName)
            
            local object = level:getEntityNamed(objectName)
            object:setRespondable(false)
            
            if time == 0 then
                level.ho_logic:onObjectFound(object:getName())
            else
                level.timer:add(function()
                                    level.ho_logic:onObjectFound(object:getName())
                                end,
                                time)
            end
        end
    end
end

--------------------------------------------------------------------------------
function HiddenObjectLogicED:getInteractiveItemBind(value, key)
    key = key or 'objectName'
    
    for i, bindInfo in ipairs(self.interactiveItems) do
        if type(bindInfo[key]) == 'table' then
            for i,v in ipairs(bindInfo[key]) do
                if v == value then
                    return bindInfo
                end
            end
        elseif bindInfo[key] == value then
            return bindInfo
        end
    end
    
    return nil
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:addInteractiveItemBind(bindInfo)
    table.insert(self.interactiveItems, bindInfo)
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:removeInteractiveItemBind(objectName)
    for i, bindInfo in ipairs(self.interactiveItems) do
        if bindInfo.objectName == objectName  then
            table.remove(self.interactiveItems, i)
            return
        end
    end
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:onInteract(objectName, time)
    local bindInfo = self:getInteractiveItemBind(objectName)
    local level = current_scene:getPlayField()
    
    local function updateTask(itemName)
        if level.ho_logic:isTaskObject( itemName ) then
            local task = GetTask(itemName)
            task:setActionObject(itemName, false)
            
        --     if time == 0 then
        --        -- self.indicator:UpdateCaptionFont(task)  
        --     else
        --         GetCurrentLevel().timer:Add(function()
        --                                         self.indicator:UpdateCaptionFont(task)  
        --                                     end,
        --                                     time)
        --     end
        -- end 
        end           
    end
    if type(bindInfo.itemName) == 'string' then
        updateTask(bindInfo.itemName)
    elseif type(bindInfo.itemName) == 'table' then
        
        for i,v in ipairs(bindInfo.itemName) do
            if type(v) == 'string' then
                updateTask(v)
            end
        end                
    end
    
    self:removeInteractiveItemBind(objectName)
end
--------------------------------------------------------------------------------
function HiddenObjectLogicED:onObjectFound(object_name)
    local playfield = self.game_scene:getPlayField()
    
    if playfield:hasEntityNamed(object_name) then
        local node = path_manager:getConnectedNode(NodeType.TASK, object_name)
        assert(node and 'No node for task')
        node:trigger()
        
        self.game_scene:getAchievmentsManager():handleEvent('on_object_found', {['scene_name'] = playfield:getName(), ['object_name'] = object_name})

        if self.bMatch3Mode then
            return self:createFadeAnimation(object_name, playfield)
        else
            return self:createFlyingAnimation(object_name, playfield)
        end
    end
end

function HiddenObjectLogicED:createFadeAnimation(object_name, playfield)
   local playfield_timer = playfield:getTimer()

    local found_object = self.game_scene:getPlayField():getEntityNamed(object_name)  
    found_object:setRespondable(false)

    local task = self:getTaskByObjectName(object_name)

    local time = 1.1
    local desappearTime = 0.3

    do
        local scaleX = found_object:getScale().x
        local scaleY = found_object:getScale().y
        
        local mover = CreateAnimationEffector()
        mover:attachTo(found_object)

        mover:setKey(_TRACK_SX, 0,           scaleX * 1)
        mover:setKey(_TRACK_SX, time * 0.25, scaleX * 1.5)
        mover:setKey(_TRACK_SX, time * 0.5,  scaleX * 1)
        mover:setKey(_TRACK_SX, time * 0.75, scaleX * 1.5)
        mover:setKey(_TRACK_SX, time,        scaleX * 1)

        mover:setKey(_TRACK_SY, 0,           scaleY * 1)
        mover:setKey(_TRACK_SY, time * 0.25, scaleY * 1.5)
        mover:setKey(_TRACK_SY, time * 0.5,  scaleY * 1)
        mover:setKey(_TRACK_SY, time * 0.75, scaleY * 1.5)
        mover:setKey(_TRACK_SY, time,        scaleY * 1)
        
        mover:setKey(_TRACK_O, time - desappearTime, found_object:getOpacity())
        mover:setKey(_TRACK_O, time, 0)
        
        mover:play()
    end
    
    if playfield.onObjectFound then
        playfield:onObjectFound(found_object)
    end

    self:playFlyingSound()

    self.task_objects_count = self.task_objects_count - 1
    if self.task_objects_count == 0 then
        playfield:getMouseBlocker():push()
    end
    
    playfield_timer:add(function() 
                            self:onObjectReachPanel(object_name) 
                            
                            if self:isAllTaskObjectsFound() then
                                playfield_timer:add(function()
                                                        self:onLastItemFound()
                                                    end, self.indicator:getStrikeOutDuration())
                            end
                        end, time)
end

function HiddenObjectLogicED:createFlyingAnimation(object_name, playfield)
    local playfield_timer = playfield:getTimer()

    local found_object = self.game_scene:getPlayField():getEntityNamed(object_name) 
    found_object:setRespondable(false)
    Helpers.attachInPlace(found_object, self.indicator:getAnchor())

    local task = self:getTaskByObjectName(object_name)
    local mover = self.indicator:createFlyAnimation(found_object, task)
    mover:attachTo(found_object)

    if self.indicator.createFlyParticleSystem then
        local particles, time = self.indicator:createFlyParticleSystem()
        time = time or 0
        particles:attachTo(found_object:getParent())
        particles:setOrder(found_object:getOrder()-0.1)
        particles.onUpdate:add(
            function(entity)
                particles:setPosition(found_object:getPosition())
                if found_object:getOpacity() == 0 and particles:getParticleAlive() == 0 then
                    particles:destroy()
                    particles = nil
                end
            end
        )
        playfield_timer:add(
            function()
                if particles then
                    particles:fire()
                else
                    WriteInfo("Particles destroyed before fire()")
                end
            end,  time >= 0 and time or (self.indicator:getFindAnimationDuration() + time) )
    end

    if playfield.onObjectFound then
        playfield:onObjectFound(found_object)
    end

    self:playFlyingSound()

    self.task_objects_count = self.task_objects_count - 1
    if self.task_objects_count == 0 then
        playfield:getMouseBlocker():push()
    end
    
    playfield_timer:add(function() 
                            self:onObjectReachPanel(object_name) 
                            
                            if self:isAllTaskObjectsFound() then
                                playfield_timer:add(function()
                                                        self:onLastItemFound()
                                                    end, self.indicator:getStrikeOutDuration())
                            end
                        end, self.indicator:getFindAnimationDuration())
end
--------------------------------------------------------------------------------

-------------------------------------------------------------------------------
function HiddenObjectLogicED:playFlyingSound()
    local playfield = self.game_scene:getPlayField()
    playfield.timer:add(function () 
                            playCommonSound('ObjectFly')
                        end, 1)
end
--------------------------------------------------------------------------------

function HiddenObjectLogicED:createPunishEntity()
    local playfield = self.game_scene:getPlayField()
    local entity    = CreateSpriteEntity('Data/Textures/Cursors/punish.png')

    entity:setName          ('cursor_punishment')
    entity:attachTo         (playfield:getMainEntity())
    entity:setOrder         (playfield:getMaxOrder() + 1)
    entity:setAnimationSize (128, 128)
    entity:setHotSpot       (54, 42)
    entity:setFramesCount   (28)
    entity:setFPS           (56 / self.punish_time)
    entity:setMode          (_ANIM_PINGPONG)
    entity:setRespondable   (false)
    entity:setVisible       (false)

    return entity
end

--------------------------------------------------------------------------------
function HiddenObjectLogicED:onClickObject(object_name)
    self.num_wrong_clicks = self.num_wrong_clicks - 1
    if not self:isPunishing() and self:isTaskObject(object_name) then
        SetTaskObjectFound(self.game_scene:getPlayField():getName(), object_name)
        self:onObjectFound(object_name)
    end   
end
--------------------------------------------------------------------------------