local PATH = minetest.get_modpath(minetest.get_current_modname()) .. "/"
local behaviors = dofile(PATH .. "behaviors2override.lua")

local abs = math.abs
local pi = math.pi
local floor = math.floor
local ceil = math.ceil
local random = math.random
local sqrt = math.sqrt
local max = math.max
local min = math.min
local tan = math.tan
local pow = math.pow
local dbg = minetest.chat_send_all

local abr = tonumber(minetest.get_mapgen_setting("active_block_range")) or 3

local neighbors = {
	{x = 1, z = 0},
	{x = 1, z = 1},
	{x = 0, z = 1},
	{x = -1, z = 1},
	{x = -1, z = 0},
	{x = -1, z = -1},
	{x = 0, z = -1},
	{x = 1, z = -1},
}

--[[ Movement ]] --
function behaviors.lq_yeet(self, tpos)
	local timer = (self.animation.attack.range.y - self.animation.attack.range.x) / self.animation.attack.speed
	local stage = 1
	local func = function(self)
		if stage == 1 then
			local node = minetest.get_node_or_nil(tpos)
			if node and (minetest.get_item_group(node.name, "falling_node") >= 1) then
				mobkit.animate(self, "yeet")
				stage = 3
			else
				return true
			end
		elseif stage == 2 then
			if timer < 0.9 then -- correspond to the animation
				stage = 3
			end
		elseif stage == 3 then
			local success, obj = minetest.spawn_falling_node(tpos)
			if success then
				local dir = vector.subtract(mobkit.get_stand_pos(self), tpos)
				dir.y = 1
				minetest.after(0, function()
					obj:set_velocity(vector.multiply(dir, 5))
				end)
			else
				return true
			end
		end
		timer = timer - self.dtime
		if (timer < 0) then
			return true
		end
	end
	mobkit.queue_low(self, func)
end

function behaviors.lq_dumbwalk(self, dest, speed_factor)
	local timer = 3 -- failsafe
	speed_factor = speed_factor or 1
	local func = function(self)
		mobkit.animate(self, "walk")
		timer = timer - self.dtime
		if timer < 0 then
			return true
		end

		local pos = mobkit.get_stand_pos(self)
		local y = self.object:get_velocity().y

		if mobkit.is_there_yet2d(pos, minetest.yaw_to_dir(self.object:get_yaw()), dest) then
			if not self.isonground or abs(dest.y - pos.y) > 0.1 then -- prevent uncontrolled fall when velocity too high
				self.object:set_velocity({x = 0, y = y, z = 0})
			end
			return true
		end

		if self.isonground then
			local dir = vector.direction({x = pos.x, y = 0, z = pos.z}, {x = dest.x, y = 0, z = dest.z})
			dir = vector.multiply(dir, self.max_speed * speed_factor)
			mobkit.turn2yaw(self, minetest.dir_to_yaw(dir))
			dir.y = y
			self.object:set_velocity(dir)
		end

		if self.moveresult.collides then
			for i, v in ipairs(self.moveresult.collisions) do
				if v.type == "node" and v.axis ~= "y" then
					behaviors.lq_turn2pos(self, v.node_pos)
					behaviors.lq_yeet(self, v.node_pos)
					return true
				end
			end
		end
	end
	mobkit.queue_low(self, func)
end

function behaviors.goto_next_waypoint(self, tpos)
	local height, pos2 = behaviors.get_next_waypoint(self, tpos)

	if not height then
		local pos = mobkit.get_stand_pos(self)
		local ypos = vector.add(vector.direction(pos, tpos), pos)
		behaviors.lq_turn2pos(self, tpos)
		behaviors.lq_yeet(self, ypos)
		return false
	end

	if height <= 0.01 then
		local yaw = self.object:get_yaw()
		local tyaw = minetest.dir_to_yaw(vector.direction(self.object:get_pos(), pos2))
		if abs(tyaw - yaw) > 1 then
			behaviors.lq_turn2pos(self, pos2)
		end
		behaviors.lq_dumbwalk(self, pos2)
	else
		behaviors.lq_turn2pos(self, pos2)
		behaviors.lq_dumbjump(self, height)
	end
	return true
end

--[[ Death ]] --
function behaviors.lq_fallover(self)
	local timer = (self.animation.fallover.range.y - self.animation.fallover.range.x) / self.animation.fallover.speed
	local init = true
	local func = function(self)
		if init then
			local yaw = math.rad(90 * math.floor((math.deg(self.object:get_yaw()) / 90) + 0.5))
			local pos = mobkit.get_stand_pos(self)

			mobkit.turn2yaw(self, yaw, 10)
			mobkit.animate(self, "fallover")

			self.object:set_pos({x = math.floor(pos.x + 0.5), y = pos.y, z = math.floor(pos.z + 0.5)})
			self.object:set_velocity({x = 0, y = 0, z = 0})
		end
		timer = timer - self.dtime
		if (timer >= 0) then
			return true
		end
	end
	mobkit.queue_low(self, func)
end

function behaviors.hq_die(self)
	local timer = (self.animation.fallover.range.y - self.animation.fallover.range.x) / self.animation.fallover.speed
	local start = true
	local func = function(self)
		if start then
			behaviors.lq_fallover(self)
			self.logic = function(self)
			end -- brain dead as well
			start = false
		end
		timer = timer - self.dtime
		if timer < 0 then
			local pos = mobkit.get_stand_pos(self)
			local height = mobkit.get_terrain_height(pos)
			local npos = vector.offset(self.object:get_pos(), 0, height, 0)
			local yaw = self.object:get_yaw()
			minetest.set_node(npos, {name = "ikea_staff:corpse", param2 = minetest.dir_to_facedir(minetest.yaw_to_dir(yaw))})
			self.object:remove()
		end
	end
	mobkit.queue_high(self, func, 100)
end

return behaviors
