local modpath = minetest.get_modpath("markov_macaws")
local settings = Settings(modpath .. "/markov_macaws.conf")
local S = minetest.get_translator("markov_macaws")
local function parse_num(str)
	return 0 + str
end

local HEAR_DISTANCE = parse_num(settings:get("hear_distance"))
local PARROT_TALK_CHANCE = parse_num(settings:get("talk_chance"))
local PARROT_TALK_CHANCE_FRIEND = parse_num(settings:get("talk_chance_friend"))

local function get_players_inside_radius(pos, radius)
	local inrad = {}
	
	local connected = minetest.get_connected_players()
	for i, player in ipairs(connected)
	do
		local ppos = player:get_pos()
		if vector.distance(pos, ppos) < radius
		then
			table.insert(inrad, player)
		end
	end
	return inrad
end





local prefix = "<" .. S("Parrot") .. "> "

local function set_nametag(self, str)
	local objprops = self.object:get_properties()
	objprops.nametag = str
	self.object:set_properties(objprops)
end


local function talk(self)

end

local function sign(x)
	return x < 0 and -1 or (x == 0 and 0 or 1)
end

local function lq_emote(self)
	local start_time = 0
	local func = function(self)
		start_time = start_time + self.dtime
		mobkit.animate(self, "emote")
		if start_time > 0.5
		then
			return true
		end
	end
	mobkit.queue_low(self, func)
end

local function hq_interact_with_friend(self, prty, friend)
	local friend_yvel_history = {}
	local hpointer = 0
	local track_count = 4
	local iterations = 0
	
	local hopping = false
	
	--if close, watch friend
	local func = function(self)
		--track player
		if mobkit.timer(self, 0.1)
		then
			iterations = iterations + 1
			hpointer = (hpointer + 1) % track_count
			friend_yvel_history[hpointer + 1] = sign(friend:get_player_velocity().y)
			hopping = false
			for i = 1, track_count
			do
				local index1 = (hpointer + i) % track_count + 1
				local index2 = (hpointer + i - 1) % track_count + 1
				local vel1 = friend_yvel_history[index1]
				local vel2 = friend_yvel_history[index2]
				
				hopping = hopping or
					(vel1 ~= vel2 and
					vel1 ~= 0 and
					vel2 ~= 0)
			end
		end
		--animate if player is hopping
		if mobkit.is_queue_empty_low(self) and self.isonground
		then
			if hopping
			then
				lq_emote(self)
			else
				mobkit.lq_idle(self, 0.5)
				
				if math.random() < 0.1 and iterations > track_count
				then
					return true
				end
			end
		end
	end
	mobkit.queue_high(self, func, prty)
end
--TODO: use low level queue properly
local function choose_action(self)
	local pos = self.object:get_pos()
	local in_rad = get_players_inside_radius(pos, HEAR_DISTANCE)
	
	local fav = nil
	local fav_rel = -math.huge
	for i, player in ipairs(in_rad)
	do
		local name = player:get_player_name()
		
		if self.player_relations[name] > fav_rel
		then
			fav_rel = self.player_relations[name]
			fav = player
		end
	end
	if fav
	then
		local favpos = fav:get_pos()
		--run if best player is bad and close
		local dist = vector.distance(favpos, pos)
		if fav_rel / dist < -0.5
		then
			mobkit.hq_runfrom(self, 20, fav)
			return true
		end
		if fav_rel > 7
		then
			if dist > 5
			then
				mobkit.hq_goto(self, 10, favpos)
			else
				if math.random(2) < 1
				then
					mobkit.hq_roam(self,0)
				else
					hq_interact_with_friend(self, 10, fav)
				end
			end
			return true, true
		end
	end
end

local function lq_make_sound(self, sound)
	local timer = 0
	mobkit.make_sound(self, sound)
	
	local func = function()
		timer = timer + self.dtime
		if timer > 0.5
		then
			return true
		end
	end
	mobkit.queue_low(self, func)
end

local function lq_talk(self)
	local sentence = self.talker:get_sentence()
	
	--if the parrot knows no words it doesn't talk
	if sentence == ""
	then
		return
	end
	
	set_nametag(self, sentence)
	
	--add '<Parrot>' in front of sentence
	sentence = minetest.colorize(self.color, prefix) .. sentence
	local pos = self.object:get_pos()
	
	
	mobkit.make_sound(self, "talk")
	--send chat message to nearby players
	for i, p in ipairs(get_players_inside_radius(pos, HEAR_DISTANCE))
	do
		local name = p:get_player_name()
		minetest.chat_send_player(name, sentence)
	end
	
	--make nametag disappear again
	local timer = 0
	local func = function()
		timer = timer + self.dtime
		if timer > 1
		then
			set_nametag(self, "")
			return true
		end
	end
	mobkit.queue_low(self, func)
end

local function parrot_brain(self)
	if self.hp <= 0
	then	
		mobkit.clear_queue_high(self)
		mobkit.hq_die(self)
		return
	end
	
	if mobkit.timer(self,1)
	then
		local prty = mobkit.get_queue_priority(self)
		
		
		local talk_chance = PARROT_TALK_CHANCE
		
		--interact with player
		local chose_action, friend
		if prty < 10
		then
			chose_action, friend = choose_action(self)
		end
		if friend
		then
			--talk chance is increased if a friend is nearby
			talk_chance = PARROT_TALK_CHANCE_FRIEND
		end
		if math.random(100) < talk_chance
		then
			lq_talk(self)
		elseif math.random(100) < talk_chance
		then
			lq_make_sound(self, "playful")
		end
		
		if chose_action
		then
			return
		end
		
		
		if prty < 20 and self.isinliquid then
			mobkit.hq_liquid_recovery(self, 20)
			return
		end
		
		local pos = self.object:get_pos()
		
		
		if mobkit.is_queue_empty_high(self) then
			mobkit.hq_roam(self, 0)
		end
	end
end

return parrot_brain
