dofile('data/Scripts/ho/HiddenPictureIndicator.lua')
-------------------------------------------------------------------------------
class 'HiddenPictureLogic' (HiddenBaseLogic)
-------------------------------------------------------------------------------

function HiddenPictureLogic:__init()
    HiddenBaseLogic.__init(self)
    
    self.indicator = HiddenPictureIndicator()
    self.tasksInfo = {}
    
    self.ETaskState = {TS_NONE      = -1,
                       TS_RESERVED  = 0,
                       TS_SHOWED    = 1,
                       TS_DRAGGABLE = 2,
                       TS_HIDED     = 3}
    
    self.reservedTasks      = {}
    self.createdTaskObjects = {}
    self.itemTargets        = {}
    self.currHintKey        = nil
end
-------------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- INTERFACE METHODS -----------------------------------------------------------
--------------------------------------------------------------------------------

function HiddenPictureLogic:RegisterTask(dealId, objectName, getObjectName, targetObjectName, onDropTarget, onFind, bCustomObjectPos, targetTextAlias)
    local task = self:_createTask(objectName) 
    
    local info            = {}
    info.taskName         = task:GetTextSingular()
    info.dealId           = dealId
    info.objectName       = objectName
    info.getObjectName    = getObjectName
    info.targetObjectName = targetObjectName
    info.onDropTarget     = onDropTarget
    info.onFind           = onFind
    info.hintKey          = self:_getHintText(objectName)
    info.targetTextAlias  = targetTextAlias or self:_getTargetAlias(objectName)
    info.state            = self.ETaskState.TS_NONE
    info.inv_scale 		  = 1
    
    table.insert(self.tasksInfo, info)
    
    do
        Object(objectName):SetOpacity(0)
        play_field:IgnoreOnTestPoint(objectName)
    end
    
    if targetObjectName and dealId == self.dealIndex then
        RegisterMonologObject(info.targetObjectName, info.targetTextAlias, EMonologAliasOrder.RANDOM)
    end
    
    if IsTaskObjectFound(objectName) then
        self:_hideGetObject(info.getObjectName, 0)
        
        if not IsObjectDropTarget(info.objectName) and (self.dealIndex == dealId) then
            self:_showTask(task)
            self:_activateTask(task)
           
           -- подгонка слоя и позици объекта для реализации сохранки
            do 
                local object = Object(objectName)
                local anchor = self.indicator:GetAnchor()
                local pos    = self.indicator:GetTaskPos(task)
                
                object:SetScrXY(pos.x, pos.y)
                object:SetLayer(anchor:GetLayer())
                object:SetScrZ (anchor:GetScrZ() + 3)
            end
        end
        
        if info.onFind then
            local event = {}
            event.save = true
            event.info = info
            
            info.onFind(event)
        end
        
        self:_registerDrag(task)
    else
        -- объект ставится в позицию предмета для нахождения
        if not bCustomObjectPos then
            Object(info.objectName):SetScrXY(Object(info.getObjectName):GetScrX(),
                                             Object(info.getObjectName):GetScrY())
        end
    
        if self.dealIndex == dealId then
            if self.indicator:FreeSlotsExist() then
                self:_showTask(task)
            else
                self:_reserveTask(task)
            end
        end
    end
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:CreateFlyAnim(object)
    local delay  = 1.1
    local time   = 0.7
    local info   = self:GetTaskInfo(object:GetName(), 'objectName')
    
    self:_hideGetObject(info.getObjectName, delay * 0.25)
    
    local anchor = self.indicator:GetAnchor()
	object:SetLayer(anchor:GetLayer())
	object:SetScrZ (anchor:GetScrZ() + 3)

    do
        local scaleX = object:GetScaleX()
        local scaleY = object:GetScaleY()
        
        local inv_scale = math.min(INVENTORY_TOOL_SIZE/object:GetAnimation():GetWidth(), INVENTORY_TOOL_SIZE/object:GetAnimation():GetHeight())
        
        local task      = GetTask(object:GetName())
        local startPos  = Vector(object:GetScrX(), object:GetScrY())
        local finishPos = self.indicator:GetTaskPos(task)
        
	    local maxDeltaPos = 256
        
        local mover = CreateAnimationEffector()
        mover:AttachTo(object)

        mover:SetKey(_TRACK_SX, 0,				scaleX * 1)
        mover:SetKey(_TRACK_SX, delay * 0.25,	scaleX * 1.5)
        mover:SetKey(_TRACK_SX, delay * 0.5,	scaleX * 1)
        mover:SetKey(_TRACK_SX, delay * 0.75,	scaleX * 1.5)
        mover:SetKey(_TRACK_SX, delay,			scaleX * 1)
        mover:SetKey(_TRACK_SX, delay + time,	scaleX * inv_scale)

        mover:SetKey(_TRACK_SY, 0,				scaleY * 1)
        mover:SetKey(_TRACK_SY, delay * 0.25,	scaleY * 1.5)
        mover:SetKey(_TRACK_SY, delay * 0.5,	scaleY * 1)
        mover:SetKey(_TRACK_SY, delay * 0.75,	scaleY * 1.5)
        mover:SetKey(_TRACK_SY, delay,			scaleY * 1)
        mover:SetKey(_TRACK_SY, delay + time,	scaleY * inv_scale)
        
        mover:SetKey(_TRACK_O, 0,               0)
        mover:SetKey(_TRACK_O, delay * 0.25,    1)
        mover:SetKey(_TRACK_O, delay + time,    1)
        
	    MakePositionKeysBySpline(mover,
                                 startPos,
                                 startPos + Vector(RandomFloat(-maxDeltaPos, maxDeltaPos),
                                                   RandomFloat(-maxDeltaPos, maxDeltaPos)),
                                 finishPos,
                                 finishPos + Vector(RandomFloat(-maxDeltaPos, maxDeltaPos), -200),
                                 20,
                                 time,
                                 delay)
    
	    mover:Play()
    end
    
    self:InitSounds()
    self:PlayFoundSound()

    GetCurrentLevel().timer:Add(function()
                                    self:PlayFlyingSound()
                                    object:AddParticleSystem('data/ParticleSystem/ObjectMoveTail.psi',
                                                             'ZoneHighlightParticle',
                                                             true)
                                end, delay)
    
    return (delay + time)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:CheckTaskObjectMouseDown(objectName)
    local info = self:GetTaskInfo(objectName, 'getObjectName')
    
    if info and info.state == self.ETaskState.TS_SHOWED then
        local object = Object(info.objectName)
        
        SetTaskObjectFound(info.objectName)
        play_field:OnObjectFound(object)
        
        if info.onFind then
            local event = {}
            event.save = false
            event.info = info
            
            info.onFind(event)
        end
        
        return true
    end
    
    return false
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:IsAllTaskObjectsFound()
    if #self.reservedTasks == 0 then
        return HiddenBaseLogic.IsAllTaskObjectsFound(self)
    end
    
    return false
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:OnLastItemFound()
    HiddenBaseLogic.OnLastItemFound(self)
    
    self.indicator:ClearSlotStates()
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:OnObjectReachPanel(object)
    HiddenBaseLogic.OnObjectReachPanel(self, object)
    
    local task = GetTask(object:GetName())
    
    object:SetOpacity(0)
    
    self:_activateTask(task)
    self:_registerDrag(task)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:OnPanelObjectMouseDown(object)
    local taskName = self.indicator:GetTaskName(object:GetName())
    
    if taskName then
        local info = self:GetTaskInfo(taskName)
        
        if info.state == self.ETaskState.TS_DRAGGABLE then
            StartDragObjectRequest(info.objectName, true)
        end
    end
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:OnPanelObjectMouseEnter(object)
    local taskName = self.indicator:GetTaskName(object:GetName())
    
    if taskName then
        local info = self:GetTaskInfo(taskName)
        
        if not IsDragging() then
            self.currHintKey = info.hintKey
        
            if info.state == self.ETaskState.TS_DRAGGABLE then
                SetCursor('CursorActive')
            end
        end
    end
end
-------------------------------------------------------------------------------

function HiddenPictureLogic:OnPanelObjectMouseLeave(object)
    local taskName = self.indicator:GetTaskName(object:GetName())
    self.currHintKey = nil
    
    if taskName and not IsDragging() then
        SetCursor('CursorDefault')
    end
end
-------------------------------------------------------------------------------

function HiddenPictureLogic:OnPanelUpdate(dt)
    self:GetIndicator():UpdateHintText(self.currHintKey)
end
-------------------------------------------------------------------------------

function HiddenPictureLogic:GetTaskInfo(searchingValue, key)
    key = key or 'taskName'
    
    for i, info in ipairs(self.tasksInfo) do
        if info[key] == searchingValue then
            return info
        end
    end
    
    return nil
end
--------------------------------------------------------------------------------



--------------------------------------------------------------------------------
-- PRIVATE METHODS -------------------------------------------------------------
--------------------------------------------------------------------------------

function HiddenPictureLogic:_getTaskName(objectName)
    local level  = GetCurrentLevel()
    local prefix = 'HP_'..string.sub(level.name, 3, 4)..'_'
    
    return prefix..string.upper(objectName)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_getTargetAlias(objectName)
    local level  = GetCurrentLevel()
    local prefix = 'BBT_'..string.sub(level.name, 3, 4)..'_HP_NEED_DROP_'
    
    return prefix..string.upper(objectName)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_getHintText(objectName)
    local level  = GetCurrentLevel()
    local prefix = 'HP_'..string.sub(level.name, 3, 4)..'_'
    
    return prefix..string.upper(objectName)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_createTask(objectName)
    local textName = self:_getTaskName(objectName)
   	local task     = CTask(textName)
   	
   	if not IsTaskObjectFound(objectName) then
        task:AddObject(objectName)
    end
    
    table.insert(self.createdTaskObjects, objectName)
    
    return task
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_showTask(task)
    play_field:GetLevelScreen():AddTask(task)
    SetActiveTaskState(task)
    
    local taskName = task:GetTextSingular()
    local info     = self:GetTaskInfo(taskName)
    
    info.state = self.ETaskState.TS_SHOWED
    
    self.indicator:CreateIndicator(taskName, Object(info.objectName))
    self.indicator:SetIndicatorColor(taskName, self.indicator.COLOR_SHADOW)
    self.indicator:ShowIndicator(taskName)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_showNextTask()
    if #self.reservedTasks > 0 then
        local task = table.remove(self.reservedTasks, 1)
        
        self:_showTask(task)
    end
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_activateTask(task)
    local taskName = task:GetTextSingular()
    local info     = self:GetTaskInfo(taskName)
    
    self.indicator:SetIndicatorColor(taskName, self.indicator.COLOR_DEFAULT)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_hideTask(task)
    local taskName = task:GetTextSingular()
    local info     = self:GetTaskInfo(taskName)
    
    info.state = self.ETaskState.TS_HIDED
    
    self.indicator:HideIndicator(taskName)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_reserveTask(task)
    local taskName = task:GetTextSingular()
    local info     = self:GetTaskInfo(taskName)
    
    info.state = self.ETaskState.TS_RESERVED
    
    table.insert(self.reservedTasks, task)
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_registerDrag(task)
    local taskName = task:GetTextSingular()
    local info     = self:GetTaskInfo(taskName)
    
    if info.targetObjectName then
        
        local function on_get(e)
            Object(info.objectName):SetScale(1)
            Object(info.objectName):SetOpacity(1)
            self.indicator:SetIndicatorColor(taskName, self.indicator.COLOR_DRAGGING)
            self.indicator:SetIndicatorIgnoreTestPoint(taskName, true)
        end
        
        local function on_drop(e)
			Object(info.objectName):ChangeScale(1, self.indicator:GetIconScale(taskName), e.time)
            GetCurrentLevel().timer:Add(function()
                                            Object(info.objectName):SetOpacity(0)
                                            self.indicator:SetIndicatorColor(taskName, self.indicator.COLOR_DEFAULT)
                                            self.indicator:SetIndicatorIgnoreTestPoint(taskName, false)
                                        end, e.time)
        end
        
        local function on_drop_target(e)
            if not e.save then
                Object(info.objectName):SetOpacity(0)
                self.indicator:SetIndicatorColor(taskName, self.indicator.COLOR_DEFAULT)
                
                self:_hideTask(task)
                self:_showNextTask()
            end
            
            if info.onDropTarget then
                local event = {}
                event.save  = e.save
                event.info  = info
            
                info.onDropTarget(event)
            end
        end
        
        info.state = self.ETaskState.TS_DRAGGABLE
        RegisterDragObject(info.objectName, nil, info.targetObjectName, on_get, on_drop, on_drop_target, nil, true)
        GetCurrentLevel():SetAdditionalHintObject(info.targetObjectName)
    end
end
--------------------------------------------------------------------------------

function HiddenPictureLogic:_hideGetObject(objectName, time)
    if objectName ~= nil then
        time = time or 0
        
        play_field:IgnoreOnTestPoint(objectName)
        local object = Object(objectName)
        
        if time == 0 then
            object:SetOpacity(0)
        else
            object:ChangeOpacity(object:GetOpacity(), 0, time)
        end
    end
end
--------------------------------------------------------------------------------