require(game.ReplicatedFirst.ReadyModule)("GenerationForeman")
local rules = require(_G.Modules.RuleModule)

local CHUNK_SIZE = 512 -- wae
local RADIUS = 3
--if _G.IsStudio then RADIUS = 1 end -- stop my computer from dying
local LEEWAY = 20 -- WHY IS THIS SO BIG WTF
local COMBAT_RADIUS = 6
local POOL_SIZE = 4 -- 

local CHUNK_OFFSET_X = -1150
local CHUNK_OFFSET_Z = 120

local pool = 0
local chunks = {}
local schunks = {}
local _c = {}
_c.__index = _c
_c.delete = function(this)
	schunks[this.index.x][this.index.z] = nil
	--if #schunks[index.x] == 0 then schunks[index.x] = nil end
	if this.generator then this.generator:SendMessage("delete") end
	chunks[this.index] = nil
end
local function chunk(x,z)
	if not schunks[x] then schunks[x] = {} end
	local i = {x=x,z=z}
	local first,second
	local c
	
	c = {viable = true, permanent = nil, generator = nil, started = false, index = i}
	setmetatable(c,_c)
	chunks[i]=c
	schunks[x][z]=c
	
	spawn(function()
		repeat wait() until pool < POOL_SIZE
		if not c.viable then return end
		pool = pool + 1
		c.generator = _G.Modules.Generator:Clone()
		c.generator.Parent = game.Workspace
		c.generator:SendMessage("generate",x * CHUNK_SIZE,z * CHUNK_SIZE,CHUNK_OFFSET_X,CHUNK_OFFSET_Z)
		c.generator.Changed:Wait()
		pool = pool - 1
	end)
	
	return c
end

local function generateCombatZone()
	_G.Remotes.Notification:FireAllClients("Generation","Generating combat zone, please wait.")
	--[[rules.setRule("GenerationProcessing",true)
	for x = -COMBAT_RADIUS,COMBAT_RADIUS do
		for z = -COMBAT_RADIUS*2,COMBAT_RADIUS*2 do
			chunk(x,z).permanent = true
		end
	end
	wait()
	repeat wait() until pool == 0
	rules.setRule("GenerationProcessing",false)]]
	_G.Remotes.Notification:FireAllClients("Generation","Generation complete.")
end

local function generateForPlayer()
	while wait(0.5) and rules.rules.GenerationFollowPlayer do
		for index,chunk in pairs(chunks) do
			chunk.viable = false
		end
		local perPlayer = function(p)
			for index,chunk in pairs(chunks) do
				if Vector2.new(p.x-index.x*CHUNK_SIZE,p.z-index.z*CHUNK_SIZE).Magnitude < CHUNK_SIZE*(RADIUS+LEEWAY) then
					chunk.viable = true
				end
			end
			for x=math.ceil(p.x/CHUNK_SIZE)-RADIUS,math.ceil(p.x/CHUNK_SIZE)+RADIUS do
				for z=math.ceil(p.z/CHUNK_SIZE)-RADIUS,math.ceil(p.z/CHUNK_SIZE)+RADIUS do
					if not schunks[x] then schunks[x] = {} end
					if not schunks[x][z] then
						chunk(x,z)
					end
				end
			end
		end

		for _,player in pairs(game.Players:GetPlayers()) do
			if player.Character then
				if player.Character.PrimaryPart then
					perPlayer(player.Character.PrimaryPart.Position)
				end
			end
		end

		perPlayer(game.Workspace.CurrentCamera.CFrame.Position)

		for index,chunk in pairs(chunks) do
			if not chunk.viable and not chunk.permanent then
				chunk:delete()
			end
		end
	end
end

local function reloadGeneration()
	for index,chunk in pairs(chunks) do
		chunk:delete()
	end
end

rules.listenRule("GenerationNoiseOffset",function(x,z)
	CHUNK_OFFSET_X = x
	CHUNK_OFFSET_Z = z
	reloadGeneration()
end)
rules.listenRule("GenerationFollowPlayer",function(yes)
	if yes then generateForPlayer() else reloadGeneration() end
end)
local r = Random.new(os.time())
rules.listenRule("GenerationCombatZone",function()
	CHUNK_OFFSET_X = r:NextInteger(-10000,10000)
	CHUNK_OFFSET_Z = r:NextInteger(-10000,10000)
	reloadGeneration()
	generateCombatZone()
end)