LoadedObjects.Spawns = {}

function addSpawn(archetype, ...)
	local o = {
		archetype = archetype,
		args = {...}
	}
	table.insert(LoadedObjects.Spawns, o)
end

function activateSpawns()
	for _, spawn in pairs(LoadedObjects.Spawns) do
		spawn.archetype:new(unpack(spawn.args))
	end
end

function deselectSpawns()
	for _, spawn in pairs(LoadedObjects.Spawns) do
		spawn.selected = nil
	end
end

function selectSpawns(rect)
	local x, y = rect:getPoints()
	local select_rect = Rect:fromPoints(x-{x=Camera.pos.x,y=Camera.pos.y},y-{x=Camera.pos.x,y=Camera.pos.y})
	select_rect:fix()

	for _, spawn in pairs(LoadedObjects.Spawns) do

		local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
		local left = spawn.args[1] - Camera.pos.x - offset_x
		local top = spawn.args[2] - Camera.pos.y - offset_y
		local right = spawn.args[1] - Camera.pos.x + offset_x
		local bottom = spawn.args[2] - Camera.pos.y + offset_y

		local spawn_rect = Rect:fromCoords(left, top, right, bottom)
		if spawn_rect:overlapsRect(select_rect) then
			spawn.selected = true
		end

		if spawn.selected then
			love.graphics.setColor(0,1,1,1)
		else
			love.graphics.setColor(0,1,0,1)
		end

		love.graphics.rectangle("fill",left-2,top-2,4,4)
		love.graphics.rectangle("fill",right-2,bottom-2,4,4)
		love.graphics.setColor(1,1,1,1)
	end
end

function moveSpawns(x,y)
	local move_x = nil
	local move_y = nil
	for _, spawn in pairs(LoadedObjects.Spawns) do
		if spawn.selected then
			local difference_x = math.floor((x/game.scale)+Camera.pos.x) - spawn.args[1]
			local difference_y = math.floor((y/game.scale)+Camera.pos.y) - spawn.args[2]
			if move_x == nil or Point.abs({x=difference_x,y=difference_y}) < Point.abs({x=move_x,y=move_y}) then
				move_x = difference_x
				move_y = difference_y
			end
		end
	end
	for _, spawn in pairs(LoadedObjects.Spawns) do
		if spawn.selected then
			spawn.args[1] = spawn.args[1] + move_x
			spawn.args[2] = spawn.args[2] + move_y
		end
	end
end


function promptSpawnNew()
	Prompt:cancelActive()
	local text = ""
	local prompt = Prompt:new({
		name = "new spawn",
		input = text,
		func = function(prompt)
			local f = loadstring("return {"..prompt.input.."}")
			if f ~= nil then
				local succ, result = pcall(f)
				local arch = result[1]
				local args = {}
				if #result > 1 then
					for i=2, #result+1 do
						print("arg #"..i-1)
						args[i-1] = result[i]
						if i < 4 then
							args[i-1] = math.floor(args[i-1])
						end
					end
				else
					args = {0,0}
				end

				print("new entity spawn --",succ)
				if not succ
				or checkArchetypeInvalid(arch)
				then
					print("invalid input for prompt "..prompt.name)
				else
					print("archetype: ",arch.type)
					print("args:      ",unpack(args))
					addSpawn(arch, unpack(args))
				end
			else
				print("invalid input for prompt "..prompt.name)
			end
		end,
	})
	prompt.pos.x = 0
	prompt.pos.y = 10
	prompt:activate()
end

function deleteSpawn()
	for i=1, #LoadedObjects.Spawns do
		if LoadedObjects.Spawns[i]
		and LoadedObjects.Spawns[i].selected then
			table.remove(LoadedObjects.Spawns,i)
			break
		end
	end
end

function checkArchetypeInvalid(arch)
	return type(arch) ~= "table" or type(arch.type) ~= "string"
end

function promptSpawnArchetype()
	Prompt:cancelActive()
	for _, spawn in pairs(LoadedObjects.Spawns) do
		if spawn.selected then
			local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
			local text = ""
			for i=1, #spawn.args do
				if i > 1 then text = text .. ", " end
				text = text .. tostring(spawn.args[i])
			end
			local prompt = Prompt:new({
				name = "archetype",
				input = spawn.archetype.type,
				spawn = spawn,
				func = function(prompt)
					print("return "..prompt.input)
					local f = loadstring("return "..prompt.input)
					if f ~= nil then
						local succ, arch = pcall(f)
						print("archetype changed --",succ)
						print("from: ", spawn.archetype.type)
						if not succ
						or checkArchetypeInvalid(arch)
						then
							arch = spawn.archetype
						end
						print("to: ", arch.type)
						spawn.archetype = arch
					else
						print("invalid input for prompt "..prompt.name)
					end
				end,
			})
			prompt.pos.x = (spawn.args[1]-4)*game.scale - Camera.pos.x - offset_x
			prompt.pos.y = (spawn.args[2]-20)*game.scale - Camera.pos.y - offset_y
			prompt:activate()
		end
	end
end

function checkArgsInvalid(args)
	for _, arg in pairs(args) do
		-- this is checking the args are not nil variables
		if arg == nil
		or arg == ""
		then
			return true
		end
	end
end

function promptSpawnArgs()
	Prompt:cancelActive()
	for _, spawn in pairs(LoadedObjects.Spawns) do
		if spawn.selected then
			local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
			local text = ""
			for i=1, #spawn.args do
				if i > 1 then text = text .. ", " end
				text = text .. tostring(spawn.args[i])
			end
			local prompt = Prompt:new({
				name = "args",
				input = text,
				func = function(prompt)
					local f = loadstring("return {"..prompt.input.."}")
					if f ~= nil then
						local succ, args = pcall(f)
						print("args changed --",succ)
						print("from: ", unpack(args))
						if not succ
						or checkArgsInvalid(args)
						then
							args = spawn.args
						end
						print("to: ", unpack(args))
						spawn.args = args
					else
						print("invalid input for prompt "..prompt.name)
					end
				end,
			})
			prompt.pos.x = (spawn.args[1]-4)*game.scale - Camera.pos.x - offset_x
			prompt.pos.y = (spawn.args[2]-4)*game.scale - Camera.pos.y - offset_y
			prompt:activate()
		end
	end
end

function drawSpawns()
	for _, spawn in pairs(LoadedObjects.Spawns) do
		local offset_x, offset_y = spawn.archetype.display:getCenteredOffset()
		love.graphics.setColor(1,1,1,1)
		spawn.archetype.display:draw(
			spawn.args[1] - Camera.pos.x - offset_x,
			spawn.args[2] - Camera.pos.y - offset_y
		)


		if spawn.selected then
			love.graphics.setColor(0,1,1,1)
		else
			love.graphics.setColor(0,1,0,1)
		end

		love.graphics.rectangle(
			"line",
			spawn.args[1] - Camera.pos.x - offset_x,
			spawn.args[2] - Camera.pos.y - offset_y,
			spawn.args[1] - Camera.pos.x + offset_x - (spawn.args[1] - Camera.pos.x - offset_x),
			spawn.args[2] - Camera.pos.y + offset_y - (spawn.args[2] - Camera.pos.y - offset_y)
		)

		if spawn.selected then
			local text = spawn.archetype.type .."\n("
			local ancestors = getAncestors(spawn.archetype)
			for i=1, #ancestors do
				if i > 1 then text = text .. ", " end
				text = text .. ancestors[i].type
			end
			text = text ..")\n---\nPosition\n["..spawn.args[1]..","..spawn.args[2].."]"
			if #spawn.args > 2 then
				text = text .. "\n---\nData:\n"
				for i=3, #spawn.args do
					if i > 3 then text = text .. ", " end
					text = text .. tostring(spawn.args[i])
				end
			end
			drawTextBox(
				text,
				spawn.args[1] - Camera.pos.x + 20,
				spawn.args[2] - Camera.pos.y
			)
		end
	end
end
