-- SCP-3008-2 IKEA Staff --
-- By GreenXenith        --
-- (Mostly Rewritten By Benrob0329) --

local DEBUG = false

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

local RANGE = 100

--[[ Debug Entities ]]--
minetest.register_entity("ikea_staff:debug", {
	visual = "sprite",
	textures = {"blank.png^[invert:a^[colorize:red"},
	visual_size = {x = 0.3, y = 0.3},
	on_activate = function(self, data)
		self.object:set_nametag_attributes({text = data})
		minetest.after(5, function()
			if self.object then
				self.object:remove()
			end
		end)
	end,
	on_punch = function(self)
		self.object:remove()
	end,
})

do --[[ Staff Entity ]]--
	-- Global Memory --
	local player_sightings = {}

	-- Entity Registration --
	minetest.register_entity("ikea_staff:member", {
		initial_properties = {
			physical = true,
			collide_with_objects = true,
			visual = "mesh",
			mesh = "ikea_staff_member.b3d",
			textures = {"ikea_staff_member.png"},
			collisionbox = {-0.45, 0, -0.45, 0.45, 3.1, 0.45},
			selectionbox = {-0.45, 0, -0.45, 0.45, 3.1, 0.45},
		},

		animation = {
			stand = {range = {x = 0, y = 140}, speed = 15},
			walk = {range = {x = 141, y = 181}, speed = 80},
			attack = {range = {x = 204, y = 244}, speed = 45},
			fallover = {range = {x = 182, y = 202}, speed = 10, loop = false},
		},

		-- Stats --
		armor_groups = {fleshy = 100},
		max_hp = 20,
		timeout = 0,
		buoyancy = 0,
		max_speed = 4.5,
		jump_height = 1,
		view_range = RANGE,
		attack = {
			range = 1,
			damage_groups = {fleshy = 5},
		},

		-- Base Mobkit Functions --
		on_activate = mobkit.actfunc,
		get_staticdata = mobkit.statfunc,

		-- Custom Logic --
		on_step = function(self, dtime, moveresult)
			self.moveresult = moveresult
			mobkit.stepfunc(self, dtime)
		end,

		logic = function(self)
			if mobkit.timer(self, 1) then
				-- Vitals and Death
				mobkit.vitals(self)

				if not mobkit.is_alive(self) then
					mobkit.clear_queue_high(self)
					mobkit.clear_queue_low(self)
					behaviors.hq_die(self)
					return
				end

				-- Player Sighting and Memory
				local player = mobkit.get_nearby_player(self)
				if player then
					table.insert(player_sightings, 1, player:get_pos())
					player_sightings[101] = nil
				end

				-- Actual Behavior
				local pos = self.object:get_pos()
				local priority = mobkit.get_queue_priority(self)
				local is_open = ikea.is_open()

				if is_open ~= mobkit.recall(self, "is_open") then
					mobkit.clear_queue_high(self)
					mobkit.clear_queue_low(self)
				end

				if DEBUG or not is_open then
					if player then
						behaviors.hq_hunt(self, 100, player)
					else
						for i, v in ipairs(player_sightings) do
							if vector.distance(v, pos) < RANGE then
								behaviors.hq_goto(self, 50, v)
								break
							end
						end
					end
				end

				if mobkit.is_queue_empty_high(self) then
					behaviors.hq_roam(self, 0)
				end

				mobkit.remember(self, "is_open", is_open)
			end
		end,

		on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
			if mobkit.is_alive(self) then
				if time_from_last_punch and (time_from_last_punch > tool_capabilities.full_punch_interval) then
					local dmg = tool_capabilities.damage_groups.fleshy or 0
					dir = vector.multiply(dir, dmg)
					self.object:set_velocity(vector.new(dir.x, 2, dir.y))
					mobkit.hurt(self, dmg)
				end

				return true
			end
		end,
	})
end

do --[[ Corpse ]]--
	local function randtime()
		return math.random(5, 120)
	end

	minetest.register_node("ikea_staff:corpse", {
		description = "SCP-3008-2 (Deceased)",
		drawtype = "mesh",
		mesh = "ikea_staff_member_dead.obj",
		tiles = {"ikea_staff_member.png"},
		selection_box = {type = "fixed", fixed = {-0.5, -0.5, 0, 0.5, 0, 3}},
		collision_box = {type = "fixed", fixed = {-0.5, -0.5, 0, 0.5, 0, 3}},
		walkable = false,
		paramtype = "light",
		paramtype2 = "facedir",
		sunlight_propagates = true,
		groups = {carryable = 1, falling_node = 1},

		-- Corpse Mob Spawner --
		on_timer = function(pos, elapsed)
			if not helpers.is_visible(pos, 3, RANGE) then
				local spawnpos = helpers.randompos(pos, 5)
				local height = mobkit.get_terrain_height(spawnpos)
				if height then
					spawnpos = vector.offset(spawnpos, 0, height, 0)
					minetest.add_entity(spawnpos, "ikea_staff:member")
				end
			end
			minetest.get_node_timer(pos):start(randtime())
			return false
		end,
		on_construct = function(pos)
			minetest.get_node_timer(pos):start(randtime())
		end,
	})
end

do --[[ Rare "Thin Air" Spawning ]]--
	local TRIES = 20 -- How many times to try finding a valid spawn point before giving up
	local timer = 0

	minetest.register_globalstep(function(dtime)
		timer = timer + dtime
		if timer >= (5 * 60) then
			for _, player in pairs(minetest.get_connected_players()) do
				local pos = player:get_pos()

				local tries = 0
				while tries <= TRIES do
					local testpos = helpers.randompos(pos, RANGE)
					local height = mobkit.get_terrain_height(testpos)
					if height then
						local spawnpos = vector.offset(testpos, 0, height, 0)
						if helpers.is_visible(spawnpos, 3, RANGE) then
							tries = tries + 1
						else
							minetest.add_entity(spawnpos, "ikea_staff:member")
							break
						end
					else
						tries = tries + 1
					end
				end
			end
			timer = 0
		end
	end)
end
