local textures =
{
	"eg_goats_torso.png", --torso
	"eg_goats_leg.png", --legs
	"eg_goats_head.png", --head
	"eg_goats_mouth.png", --mouth
	"blank.png", --unihorn
	"eg_goats_horns.png", --horns
}

local function hq_follow_until_near(self, prty, tgtobj)
	local tgtpos = tgtobj:get_pos()
	local func = function()
		if mobkit.timer(self, 0.5)
		then
			if not mobkit.exists(tgtobj)
			then
				return true
			end
			tgtpos = tgtobj:get_pos()
			if vector.distance(self.object:get_pos(), tgtpos) < 5
			then
				return true
			end
		end
		if mobkit.is_queue_empty_low(self) and self.isonground
		then
			eg_moblib.goto_next_waypoint(self, tgtpos, 0.3)
		end
	end
	mobkit.queue_high(self, func, prty)
end

local function hq_gather(self, prty, attempts)
	local follow
	local func = function()
		if mobkit.timer(self, 2)
		then
			if not mobkit.exists(follow)
			then
				follow = mobkit.get_nearby_entity(self, self.name)
				return
			end
			hq_follow_until_near(self, prty + 1, follow)
			attempts = attempts - 1
		end
		return attempts < 1
	end
	mobkit.queue_high(self, func, prty)
end

local function defend(self)
	--get two random nearby players and select the worse one
	local nearbies = {mobkit.get_nearby_player(self), mobkit.get_nearby_player(self)}
	local badness = 0
	local worse
	for i, nearby in ipairs(nearbies)
	do
		local new_badness = self.enemy[nearby:get_player_name()]
		if new_badness and new_badness > badness
		then
			badness = new_badness
			worse = nearby
		end
	end

	if worse
	then
		if badness < 2
		then
			--forgive
			return
		elseif badness < self.hp * 1.5 --TODO: fine tune
		then
			--attack
			mobkit.hq_hunt(self, 20, worse)
		else
			--run
			mobkit.clear_queue_high(self)
			mobkit.clear_queue_low(self)
			mobkit.hq_runfrom(self, 21, worse)
		end
	end
end

local function lq_sleep(self, time)
	mobkit.animate(self, "sleep")
	local func = function()
		if mobkit.timer(self, 3) and math.random(5) == 1
		then
			mobkit.heal(self, 1)
			mobkit.make_sound(self, "snore")
			if math.random(5) == 1
			then
				--slowly forgive enemies
				for k, v in pairs(self.enemy)
				do
					v = v - 1
					self.enemy[k] = v > 0 and v or nil
				end
			end
		end
		if math.random(10) == 1
		then
			defend(self)
		end
		time = time - self.dtime
		return time <= 0
	end
	mobkit.queue_low(self, func)
end

local function is_day()
	local tod = minetest.get_timeofday()
	return tod > 0.25 and tod < 0.75
end


local function hq_sleep(self, prty)
	hq_gather(self, prty + 1, 5)
	local func = function()
		if mobkit.is_queue_empty_low(self)
		then
			lq_sleep(self, 3)
			return is_day()
		end
	end
	mobkit.queue_high(self, func, prty)
end

local function hq_eat(self, prty)
	local func = function()
		--TODO
	end
	mobkit.queue_high(self, func, prty)
end

local function alert_danger(self, attacker, damage)
	for i, obj in ipairs(self.nearby_objects)
	do
		local luae = obj:get_luaentity()
		if luae and luae.name == self.name
		then
			if attacker:is_player()
			then
				local name = attacker:get_player_name()
				luae.enemy[name] = (luae.enemy[name] or 0) + damage
				defend(luae)
			end
		end
	end
end

minetest.register_entity("eg_goats:goat",
	{
		initial_properties =
		{
			physical = true,
			collide_with_objects = true,
			collisionbox = {-0.3, 0, -0.3, 0.3, 1, 0.3},
			visual = "mesh",
			mesh = "eg_goats_goat.b3d",
			backface_culling = false,
		},
		timeout = 0,
		buoyancy = 0.5,
		lung_capacity = 5, --more than 5 is a waste after all
		max_hp = 30,
		on_step = mobkit.stepfunc,
		on_activate = function(self, staticdata, dtime_s)
			mobkit.actfunc(self, staticdata, dtime_s)
			--set textures
			local props = self.object:get_properties()
			props.textures = textures
			self.object:set_properties(props)
			--load enemy table and set it to be saved again
			self.enemy = mobkit.recall(self, "enemy") or {}
			mobkit.remember(self, "enemy", self.enemy)
			--start doing something
			if is_day()
			then
				mobkit.hq_roam(self, 1)
			else
				hq_sleep(self, 10)
			end
		end,
		get_staticdata = mobkit.statfunc,
		logic = function(self)
			if not mobkit.is_alive(self)
			then
				mobkit.clear_queue_high(self)
				mobkit.clear_queue_low(self)
				mobkit.hq_die(self, 100)
				return
			end
			if mobkit.timer(self, 1)
			then
				local prty = mobkit.get_queue_priority(self)
				if self.isinliquid and prty < 30
				then
					mobkit.hq_liquid_recovery(self, 30)
				end
				if is_day()
				then
					if prty < 20
					then
						defend(self)
					end
					if mobkit.is_queue_empty_high(self)
					then
						mobkit.hq_roam(self, 1)
					end
				else
					if prty < 10
					then
						hq_sleep(self, 10)
					end
				end
			end
		end,
		on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
			local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
		self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
			local dmg = tool_capabilities.damage_groups.fleshy or 1
			mobkit.hurt(self, dmg)
			if mobkit.is_alive(self)
			then
				if puncher:is_player()
				then
					local name = puncher:get_player_name()
					self.enemy[name] = (self.enemy[name] or 0) + dmg
					defend(self)
				end
				alert_danger(self, puncher, dmg)
				mobkit.make_sound(self, "hurt")
			end
		end,
		--TODO: animation
		--TODO: sounds
		max_speed = 12,
		jump_height = 2,
		view_range = 30,
		attack =
		{
			range = 1,
			damage_groups = {fleshy = 4},
		},
		armor_groups = {fleshy = 4},
	})
