class 'HiddenObjectIndicator'

-------------------------------------------------------------------------------
function HiddenObjectIndicator:__init(game_scene)
	-- constants
	self.MAIN_TASKS_COUNT =  12
	
	self.TASKS_X  = 320
	self.TASKS_Y  = 710
	
	self.TASKS_DY = 24
	self.WIDTH    = 488
	
	self.ADDITIONAL_TASKS_X  = -500
	self.ADDITIONAL_TASKS_Y  = -700
	self.ADDITIONAL_TASKS_DY =  30
	
	self.TEXT_HEIGHT         = 25
	self.TEXT_TRACKING       = -9
	self.SIMPLE_OBJECT_COLOR = Colorf(1.0, 1.0, 1.0, 1.0)
	self.ACTIVE_OBJECT_COLOR = Colorf(0.86, 0.1, 0.12, 1.0)
	
	-- init
	self.game_scene = game_scene
	self.anchor  = self:_createAnchor()
	self.strings = {}
	self.visible = true
	
	self.cols = 4
	self.rows = math.ceil(self.MAIN_TASKS_COUNT / self.cols)
	
	-- flying animation consts
	self.pop_duration = 1.1
	self.flying_to_panel_duration = 0.7
	self.disappear_time = 0.3
	self.strike_out_duration = 1
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:destroy()
	self.anchor:destroy()
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:fill()
	local tasksOrder = self:_getSortedTasksMap()
	self:_calculateTasksPos(tasksOrder)
	
	if #tasksOrder == 1 then
		for _, taskInfo in pairs(tasksOrder) do
			local dx = 200
			local dy = 20

			local task  = taskInfo.task
			local field = self:_createTextField(task)
			field:setXY(taskInfo.x + dx, taskInfo.y + dy)
			
			local info = {}
			info.field = field
			info.x     = taskInfo.x + dx
			info.y     = taskInfo.y + dy
			
			local key = task:getName()
			self.strings[key] = info
			
			self:updateCaption(task, true)
			self:updateCaptionColor(task)
		end
	else
		for _, taskInfo in pairs(tasksOrder) do
			local task  = taskInfo.task
			local field = self:_createTextField(task)
			field:setXY(taskInfo.x, taskInfo.y)
			
			local info = {}
			info.field = field
			info.x     = taskInfo.x
			info.y     = taskInfo.y
			
			local key = task:getName()
			self.strings[key] = info
			
			self:updateCaption(task, true)
			self:updateCaptionColor(task)
		end
	end
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:getAnchor()
	return self.anchor
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:getField(task)
	local key = task:getName()
	
	if self.strings[key] then
		return self.strings[key].field
	end
	
	return nil
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:getTaskPosition(task)
	local key   = task:getName()
	local field = self.strings[key].field
	
	return Vector2f(field:getX(), field:getY())
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:updateCaption(task, save)
	local field   = self:getField(task)
	local caption = self:_getTaskCaption(task)
	
	field:setText(caption)
	
	local objectsCount = task:getNumberOfObjects() +
						 task:getNumberOfObjectsWithFindAnimationPlaying()
						 
	if objectsCount <= 0 then
		self:_strikeOutCaption(field, save)
		self:updateCaptionColor(task)
	end
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:updateCaptionColor(task)
	local field = self:getField(task)
	
	if field then
		if task:hasActionObject() then
			field:setColor(self.ACTIVE_OBJECT_COLOR)
		else
			field:setColor(self.SIMPLE_OBJECT_COLOR)
		end
	end
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:createFlyAnimation(object, task)
	local max_delta_pos   = 256
	local anchor = self:getAnchor()
	
	local scale = object:getScale()
	local num_keys =  40
	
	local start_pos  = Vector2f(object:getX(), object:getY())
	local finish_pos = self:getTaskPosition(task)

	local mover = CreateAnimationEffector()

	mover:setKey(_TRACK_SX, 0,				scale.x * 1)
	mover:setKey(_TRACK_SX, self.pop_duration * 0.25,	scale.x * 1.5)
	mover:setKey(_TRACK_SX, self.pop_duration * 0.5,	scale.x * 1)
	mover:setKey(_TRACK_SX, self.pop_duration * 0.75,	scale.x * 1.5)
	mover:setKey(_TRACK_SX, self.pop_duration,			scale.x * 1)
	mover:setKey(_TRACK_SX, self.pop_duration + self.flying_to_panel_duration,	scale.x * 0.3)

	mover:setKey(_TRACK_SY, 0,				scale.y * 1)
	mover:setKey(_TRACK_SY, self.pop_duration * 0.25,	scale.y * 1.5)
	mover:setKey(_TRACK_SY, self.pop_duration * 0.5,	scale.y * 1)
	mover:setKey(_TRACK_SY, self.pop_duration * 0.75,	scale.y * 1.5)
	mover:setKey(_TRACK_SY, self.pop_duration,			scale.y * 1)
	mover:setKey(_TRACK_SY, self.pop_duration + self.flying_to_panel_duration,	scale.y * 0.3)
	
	mover:setKey(_TRACK_O, self.pop_duration + self.flying_to_panel_duration, object:getColor():getA())
	mover:setKey(_TRACK_O, self.pop_duration + self.flying_to_panel_duration + self.disappear_time,	0)
	
	local keys = HelpersEffect.createSplineBezier(	start_pos,
													start_pos + Vector2f(RandomFloat(-max_delta_pos, max_delta_pos),
																		RandomFloat(-max_delta_pos, max_delta_pos)),
													finish_pos,
													finish_pos + Vector2f(RandomFloat(-max_delta_pos, max_delta_pos), -200),
													num_keys)
	
	local time_step = self.flying_to_panel_duration / num_keys
	for i, position in ipairs(keys) do
		mover:setKey(_TRACK_X, self.pop_duration + (i - 1) * time_step, position.x)
		mover:setKey(_TRACK_Y, self.pop_duration + (i - 1) * time_step, position.y)
	end
	
	return mover
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:getFindAnimationDuration()
	return self.pop_duration + self.flying_to_panel_duration + self.disappear_time
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:getStrikeOutDuration()
	return self.strike_out_duration
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_getTaskCaption(task)
	local objectsCount = task:getNumberOfObjects() + task:getNumberOfObjectsWithFindAnimationPlaying()
	local caption = StringManager:getString(task:getName())
	
	if objectsCount > 1 then
		caption = caption..' x'..tostring(objectsCount)
	end
	
	return caption
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_getTaskCaptionWidth(task)
	local width = 0
	local field = self:getField(task)
	if field then
		width = field:getBoundingBox():getWidth()
	else
		width = 50
	end
	return width
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_getSortedTasksMap()
	local map   = {}
	local tasks = self.game_scene:getPlayField():getHOLogic():getTasks()
			
	for task_name, task in pairs(tasks) do
		local info = {}
		info.task  = task
		info.width = self:_getTaskCaptionWidth(task)
		info.x     = 0
		info.y     = 0
		
		table.insert(map, info)
	end
	
	local mapSize = #map
	
	for i=1, mapSize-1 do
		for j = i+1, mapSize do
			if map[i].width < map[j].width then
				map[i], map[j] = map[j], map[i]
			end
		end
	end
	
	return map
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_getColumnWidths(sortedTasksMap)
	local tasksCount       = #sortedTasksMap
	local columnWidths     = {}
	local reserveColumns  = {}
	local sumWidth         = 0
	
	for col = 1, self.cols do
		local width = 0
		for row = 1, self.rows do
			local i = (col - 1) * self.rows + row
			
			if i <= tasksCount then
				width = math.max(width, sortedTasksMap[i].width+20)
				if width < self.WIDTH/4 then
					width = self.WIDTH/4 
					table.insert(reserveColumns, col)
				end
			else
				break
			end
		end
		
		table.insert(columnWidths, width)
		sumWidth = sumWidth + width
	end
	
	if #reserveColumns ~= 4 then -- not all columns has default width
		local missingLenght = (self.WIDTH - sumWidth) / #reserveColumns
		
		for index in each(reserveColumns) do
			columnWidths[index] = columnWidths[index] + missingLenght
		end
	end
		
	return columnWidths
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_calculateTasksPos(sortedTasksMap)
	local columnWidths  = self:_getColumnWidths(sortedTasksMap)
	local columnXoffset = {}
	
	for i, info in ipairs(sortedTasksMap) do
		if i > self.MAIN_TASKS_COUNT then
			local diff = i - self.MAIN_TASKS_COUNT
			
			info.x = self.ADDITIONAL_TASKS_X
			info.y = self.ADDITIONAL_TASKS_Y + self.ADDITIONAL_TASKS_DY * (diff - 1)
		else
			local zeroTypeId = i-1
			local col = math.floor(zeroTypeId / self.rows)
			local row = zeroTypeId - (col * self.rows)
			
			if not columnXoffset[col] then   
				columnXoffset[col] = 0
				
				for j=0, col-1 do
					columnXoffset[col] = columnXoffset[col] + columnWidths[j+1]
				end
			end
			
			info.x = columnXoffset[col]
			info.y = row * self.TASKS_DY
		end
	end
end

------------------------------------------------------------------------------
-- static var
local strike_id = 0 
function HiddenObjectIndicator:_strikeOutCaption(field, save)
	local crossing_sprite = CreateSpriteEntity('Data/Textures/GUI/HO/crossing.png')
	crossing_sprite:setName('strikeout_'..strike_id)
	crossing_sprite:attachTo(field)
	crossing_sprite:setRespondable(false)
	crossing_sprite:setXY(crossing_sprite:getX(), crossing_sprite:getY() + 2) -- small adjust
	crossing_sprite:setVisible(true)
	local scale = field:getBoundingBox():getWidth() / 140
	crossing_sprite:setScale(scale, scale + .4)
	
	crossing_sprite:setAnimationSize(162, 88)
	crossing_sprite:setFramesCount(20)
	crossing_sprite:setFPS(20)
	crossing_sprite:setMode(_ANIM_FWD)
	crossing_sprite:setHotSpot(81, 37)
	
	if save then
		crossing_sprite:setFrame(19)
	else
		--PlaySound('Strike_out')
		crossing_sprite:play()
	end
	strike_id = strike_id + 1
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_createTextField(task)
	local textKey = task:getName()
	local field   = CreateTextEntity()
	
	field:setText(textKey)
	field:setOrder(10)
	field:setTextAlignment(ETextHorizontalAlignmentCenter)
	field:attachTo(self.anchor)
	field:setFont('Data/Fonts/Options.fnt')
	field:setHeight(self.TEXT_HEIGHT)
	-- field:setFont('Data/Fonts/diary_white.fnt')
	field:setHotSpotType(ETextHotSpotTypeCenter)
	field:setRespondable(false)
	field:show()
	
	return field
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:_createAnchor()
	local anchor = CreateSpriteEntity('')
	local ho_panel = self.game_scene:getHOPanel()
	anchor:attachTo(ho_panel:getMainEntity())
	anchor:setName('HOPanelAnchor')
	anchor:setXY(self.TASKS_X, self.TASKS_Y)
	anchor:setOrder(11)
	
	return anchor
end

-------------------------------------------------------------------------------
function HiddenObjectIndicator:createFlyParticleSystem()
	local particle = CreateParticleEntity()
	particle:setParticle( 'Data/ParticleSystems/item_highlight.psi',
		'Data/Textures/Particles/particle_ho.png' )
	particle:setBlend( _EBlendModeColorAdd )
	particle:setHotSpot( 10, 10 )
	particle:setLifetime( 0.96 )

	return particle, -1
end