dofile('Data/Scripts/Common/Hint/HintLogicBase.lua')
dofile('Data/Scripts/Common/Hint/WayManager.lua')
dofile('Data/Scripts/Common/Hint/WayPoint.lua')
dofile('Data/Scripts/Common/Hint/WayHelpers.lua')
-------------------------------------------------------------------------------

class 'HintBase' (HintLogicBase)
-------------------------------------------------------------------------------

function HintBase:__init(playfield)
	HintLogicBase.__init(self, playfield)
	self.show_bbt_on_unvisited_zoom = false
end
-------------------------------------------------------------------------------

function HintBase:hint()
	local current_minimal_weight = 20000
	local current_minimal_layer = 100
	local available_nodes = {}
	local visited_scenes = {}
	visited_scenes[path_manager.current_node] = true
	
	local function check_branch(entry_area, current_node, weight, layer)	-- entry area - area in current scene for this branch
		if layer - current_minimal_layer > 1 then							-- we should check 1 scene deeper because we can have weights below zero
			return
		else
			if current_node:isAccessible(layer > 0) then
				if current_node.state == NodeState.PENDING and current_node:isConditionsSatisfied() then
					current_node:setState(NodeState.ENABLED)
			    end
				if weight <= current_minimal_weight and current_node.state == NodeState.ENABLED and current_node.type ~= NodeType.LINK and current_node.type ~= NodeType.ZOOM then -- add current node to node list or set new minimal weight
					if weight < current_minimal_weight then
						available_nodes = {}
					end

					--Console:pushText('Addidng new node '..tostring(current_node)..' with weight '..weight)
					table.insert(available_nodes, entry_area)
					current_minimal_weight = weight
					current_minimal_layer = layer
				end

				local next_layer = layer 
				if current_node.type == NodeType.SCENE then 
					next_layer = layer + 1 
					if not visited_scenes[current_node] then
						visited_scenes[current_node] = true
					else
						return
					end
				end
				
				for next_node, next_weight in pairs(current_node.connected_nodes) do
					check_branch(entry_area, next_node, weight+next_weight, next_layer)
				end
			end
		end
	end

	local toolFoundScreen = self.playfield:getGameScene():getToolFoundScreen()
	if not toolFoundScreen then
		local active_node = (#self.playfield.active_zones > 0 and self.playfield.active_zones:GetTop().node) or path_manager.current_node -- if zoom is opened, it will be our root node, otherwise it will be scene node
		for node, weight in pairs(active_node.connected_nodes) do
			check_branch(node, node, weight, 0)
		end
	end
	
	if #available_nodes ~= 0 then
		local enter_node = table.random_value(available_nodes)
		local obj = self.playfield:getEntityNamed(enter_node.target_area)
		self.last_hinted_object = obj
		--Console:pushText('Hint to '..obj:getName() .. ' of ' .. tostring(enter_node))
		if enter_node.type == NodeType.ZOOM and self.show_bbt_on_unvisited_zoom and current_minimal_weight == 3 then
			self.playfield:showBlackBar('C_UNVISITED_ZOOM_ZONE')
			return HintResult.KEEP
		elseif enter_node.type == NodeType.LINK then
			self:hintLinkZone( obj )
		else
			self:playHintAnimation( obj )
		end
		if enter_node.type == NodeType.DRAG_N_DROP and enter_node.target_area ~= enter_node.info then
			if self.playfield:hasEntityNamed(enter_node.info) then
				local add_hint_object = self.playfield:getEntityNamed(enter_node.info)
				self:playHintAnimation( add_hint_object)
			end
		end
		-- PlaySound("hint")
		
		if enter_node.type == NodeType.LINK or (enter_node.type == NodeType.ZOOM and enter_node.state == NodeState.ENABLED) then
			return self:returnHintResult(HintResult.KEEP, obj)
		else
			return self:returnHintResult(HintResult.RESET, obj)
		end
	else 
		return HintResult.NO_OBJECTS
	end
end
----------------------------------------------------------------------------------
function HintBase:returnHintResult(result, object)
	Console:pushText(object:getName())
	if self.playfield.onHint then
		self.playfield:onHint(object, result)
	end
	return result
end
----------------------------------------------------------------------------------

function HintBase:hintLinkZone(target_object)
	local target_name = target_object:getName()
	local cursor_name = self.playfield.linked_scenes[target_name].cursor_name

	if cursor_name == 'CursorGlass' then
		self:playHintAnimation(target_object)
		return
	end

	local function GetArrowAngle(cursor_name)
		local angle = 0
		if cursor_name == "CursorLeftUp" then
			angle = -135
		elseif cursor_name == "CursorLeft" then
			angle = -180
		elseif cursor_name == "CursorLeftDown" then
			angle = 135
		elseif cursor_name == "CursorRight" then
			angle = 0
		elseif cursor_name == "CursorRightUp" then
			angle = -45
		elseif cursor_name == "CursorRightDown" then
			angle = 45
		elseif cursor_name == "CursorUp" then
			angle = -90
		elseif cursor_name == "CursorDown" then
			angle = 90
		end
		
		return angle
	end

    
    self:createLinkZonePointer(target_object, cursor_name, GetArrowAngle(cursor_name))
    self:createLinkZonePointerEffector()	
end
----------------------------------------------------------------------------------
function HintBase:createLinkZonePointer(target_object, cursor_name, angle)
	if not self.arrow then
		self.arrow = CreateSpriteEntity('Data/Textures/Screens/InteractiveHelp/TutorialArrow.png')
	end
	
	local y_offset = cursor_name == 'CursorDown' and -100 or 0
	self.arrow:setName('arrow_to_'..target_object:getName())
	self.arrow:setColor(1, 1, 1, 1)
	self.arrow:setRespondable(false)
	self.arrow:attachTo(self.playfield:getMainEntity())
	self.arrow:setOrder(self.playfield:getMaxOrder())
	self.arrow:setHotSpot(185, 39)
	self.arrow:setScrXY(target_object:getScrX(), target_object:getScrY() + y_offset)
	self.arrow:setRotationDeg(angle)	
	self.arrow:setVisible(true)
end
----------------------------------------------------------------------------------
function HintBase:createLinkZonePointerEffector()
	self.arrow:destroyEffectors()
	
	local op_time = 3
	local eff = CreateAnimationEffector()
	eff:setDestroysOnEnd(true)
	eff:attachTo(self.arrow)
	eff:setKey(_TRACK_SX, 0.0, 0.3)
	eff:setKey(_TRACK_SX, 1.0, 0.3 + 0.2)
	eff:setKey(_TRACK_SX, 2.0, 0.3)
	eff:setMode(_ANIM_PINGPONG)
	eff:play()
		
	self.arrow:ChangeOpacity(1, 0, op_time)
end
----------------------------------------------------------------------------------

function HintBase:IsAccessible(object)
	if  object and
		self.playfield.forced_object_data and
		self.playfield.forced_object_data.object:getName() ~= object:getName()
	then
		return false
	end

	if  object and
		-- object:getOpacity() > 0. and
		-- object:isVisible() and
		object:isRespondable()
	then
		return true
	end

	return false
end
----------------------------------------------------------------------------------

function HintBase:setAdditionalHintObject(object_name, weight, root_node)
	local node = path_manager:getConnectedNode(NodeType.ADDITIONAL, object_name) or path_manager:addAdditionalNode(object_name, root_node, weight)
	if node then
		node:setState(NodeState.ENABLED)
	end
end
-------------------------------------------------------------------------------

function HintBase:removeAdditionalHintObject(object_name)
	local node = path_manager:getConnectedNode(NodeType.ADDITIONAL, object_name)
	if node then
		path_manager:removeNode(node)
	end
end
-------------------------------------------------------------------------------

function HintBase:setIgnoreOnHint(object_name)
	local function check_branch(entry_area, current_node) -- entry area - area in current scene for this branch
		if current_node.type == NodeType.SCENE then
			return
		end

		if current_node.target_area == object_name then
			current_node:setState(NodeState.IGNORED)
		end
					
		for next_node, _ in pairs(current_node.connected_nodes) do
			check_branch(entry_area, next_node)
		end
	end

	local active_node = (#self.playfield.active_zones > 0 and self.playfield.active_zones:GetTop().node) or path_manager.current_node -- if zoom is opened, it will be our root node, otherwise it will be scene node
	for node, _ in pairs(active_node.connected_nodes) do
		check_branch(node, node)
	end
end
-------------------------------------------------------------------------------

function HintBase:removeIgnoreOnHint(object_name)
	local function check_branch(entry_area, current_node) -- entry area - area in current scene for this branch
		if current_node.type == NodeType.SCENE then
			return
		end

		if current_node.target_area == object_name then
			if current_node.state == NodeState.IGNORED then
				current_node:setState(NodeState.ENABLED)
			end
		end
					
		for next_node, _ in pairs(current_node.connected_nodes) do
			check_branch(entry_area, next_node)
		end
	end

	local active_node = (#self.playfield.active_zones > 0 and self.playfield.active_zones:GetTop().node) or path_manager.current_node -- if zoom is opened, it will be our root node, otherwise it will be scene node
	for node, _ in pairs(active_node.connected_nodes) do
		check_branch(node, node)
	end
end
-------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------
function HintBase:getLastHintedObject()
	return self.last_hinted_object
end
----------------------------------------------------------------------------------------------------------------------------
function HintBase:setLastHintedObject(object)
	self.last_hinted_object = object
end
----------------------------------------------------------------------------------------------------------------------------
function HintBase:clearLastHintedObject()
	self:setLastHintedObject(nil)
end
----------------------------------------------------------------------------------------------------------------------------
function HintBase:setAnimationDisabled(bAnimationDisabled)
	self.bAnimationDisabled = bAnimationDisabled
end
----------------------------------------------------------------------------------------------------------------------------
function HintBase:getAnimationDisabled()
	return self.bAnimationDisabled
end
----------------------------------------------------------------------------------------------------------------------------