class 'HiddenBaseLogic'
-------------------------------------------------------------------------------
function HiddenBaseLogic:__init(game_scene)
	self.game_scene = game_scene    -- поинтер на сцену
	
	self.indicator     = nil        -- отвечает за отображение тасков на панеле
	
	self.searchingTool = nil        -- имя тулзы, добавляемой после выполнения всех тасков
	self.dealIndex     = 0          -- порядковый номер прохождения
	self.lastDeal      = false      -- свойство, показывающеее, является ли даное прохождение последним.
									--   Используется для определения, нужна ли очистка стейтов найденых объектов.
	
	self.flyingSounds = nil         -- таблица звуков полета итемов. Инициализируется при первом создании эффект полета.
	self.findSound    = nil         -- звук клика по итему при находжении. Инициализируется при первом создании эффект полета.
	
	self.createdTaskObjects = {}    -- обьекты, принадлежащие таскам. Необходимы для очисткистейтов найденых обьектов после всех прохождений.
	
	self.tasks = {}					-- таблица тасков, перенесена сюда с кабестановского LevelScreen'a
	
	self.click_time_to_punish = 1.2
	self.num_clicks_to_punish = 4
	
	self.num_wrong_clicks = 0
	self.is_punishing = false
	self.punish_time = 3

	--signals
	self.onTaskObjectFound = LuaSignal('onTaskObjectFound')
	
	self.game_scene:getPlayField():getTimer():add(
		function()
			self.num_wrong_clicks = 0
		end, self.click_time_to_punish, true)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:update(dt)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:getIndicator()
	return self.indicator
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:getSearchingTool()
	return self.searchingTool
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:getDealIndex()
	return self.dealIndex
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:isLastDeal()
	return self.lastDeal
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:defineToolFindOrder(...)
	local tools = {...}

	for dealIndex, toolName in ipairs(tools) do
		if not IsToolFound(toolName) then
			self.searchingTool = toolName
			self.dealIndex     = dealIndex
			self.lastDeal      = (dealIndex == #tools)
			return
		end
	end
	
	-- without tool finding or all tools already found
	-- assert(false)
	self.game_scene:loadPlayField(self.game_scene:getPlayField().parent_level)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:isAllTaskObjectsFound()
	for task_name, task in pairs(self.tasks) do
		if task:getNumberOfObjects() > 0 then
			return false
		end
	end
	
	return true
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:getTaskObjectsCount()
	local num_tasks = 0
	for task_name, task in pairs(self.tasks) do
		num_tasks = num_tasks + task:getNumberOfObjects()
	end
	return num_tasks
end
-------------------------------------------------------------------------------

function HiddenBaseLogic: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

		AddUniqueGameState(HO_FULLY_COMPLETED, scene_name)
	end
	
	local playfield = self.game_scene:getPlayField()
	SetGameState(LAST_VISITED_SCENE, playfield.parent_level)
	SetGameState(LAST_VISITED_SCENE, playfield.parent_level, EGameStateTag.GENERAL)
	AddGameState(SCENE_CLOSED, scene_name)
	
	if getPrimaryGameStateTag() == EGameStateTag.EXTRA then
		playfield:close()
	else
		if self.searchingTool then
			local function onAllItemsFound()
				playfield.timer:add(function()
									playfield:close()
								end, .4)
			end

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

function HiddenBaseLogic:playFlyingSound()
	local playfield = self.game_scene:getPlayField()
	playfield.timer:add(function () 
							playCommonSound('ObjectFly_'..tostring(math.random(1,2)))
						end, 1)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:onMouseDown(target, screenFocus)
	if self:isWrongClicksCounting() then
		playCommonSound('WrongClick')

		self.num_wrong_clicks = self.num_wrong_clicks + 1
		if self.num_wrong_clicks >= self.num_clicks_to_punish then
			if getPlayModeParameters().cursorPunishmentEnabled then -- getPlayMode() ~= EPlayMode.CASUAL
				self:punishCursor(screenFocus)
			end
		end
	end
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:isWrongClicksCounting()
	if self:isPunishing() then
		return false
	end

	do
		local alternativeHOZoom	= self.game_scene:getPlayField():getAlternativeHOZoom()
		if alternativeHOZoom and alternativeHOZoom:isVisible() then
			return false
		end
	end

	return true
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:onObjectReachPanel(object_name)
end
-------------------------------------------------------------------------------


-------------------------------------------------------------------------------
-- PUNISH CURSOR METHODS ------------------------------------------------------
-------------------------------------------------------------------------------

function HiddenBaseLogic:isPunishing()
	return self.is_punishing
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:punishCursor(screenFocus)
	if true then -- TODO: if we're using custom cursor check here
		self:punishCustomCursor(screenFocus)
	else
		self:punishRegularCursor(screenFocus)
	end

	playCommonSound('CursorPunish')
	
	self.is_punishing = true
	self.game_scene:getPlayField():getTimer():add(
		function()
			self.is_punishing = false
		end, self.punish_time)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:punishCustomCursor(screenFocus)
	local playfield = self.game_scene:getPlayField()

	if not self.obj_punish then
		self.obj_punish = self:createPunishEntity()
	end

	local cursor = screenFocus:getCursor()
	cursor:setState('CursorEmpty')
	cursor:lockState()

	self.obj_punish:setScrPosition(cursor:getScrPosition())
	self.obj_punish:setVisible(true)
	self.obj_punish:play()

	local function changeActivityCallback(bActive)
		if bActive then
			cursor:setState('CursorEmpty')
			cursor:lockState()
		else
			cursor:unlockState()
			cursor:setState('CursorDefault')
		end
	end

	local function updateCallback(target, dt)
		self.obj_punish:setScrPosition(cursor:getScrPosition())
	end

	local connections = {}
	table.insert(connections, self.obj_punish.onChangeActivity:add(changeActivityCallback))
	table.insert(connections, self.obj_punish.onUpdate:add(updateCallback))

	playfield:getTimer():add(	function()
									cursor:unlockState()
									cursor:setState('CursorDefault')

									self.obj_punish:stop()
									self.obj_punish:setVisible(false)

									for _, connection in ipairs(connections) do
										connection:remove()
									end
								end, self.punish_time)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic: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	(196, 174)
	entity:setHotSpot		(78, 65)
	entity:setFramesCount	(45)
	entity:setFPS			(90 / self.punish_time)
	entity:setMode			(_ANIM_PINGPONG)
	entity:setRespondable	(false)
	entity:setVisible		(false)

	return entity
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:punishRegularCursor(screenFocus)
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:getTasks()
	return self.tasks
end
-------------------------------------------------------------------------------

function HiddenBaseLogic:start()
end
-------------------------------------------------------------------------------