-- Made referencing Mineclonia's mcl_util.queue code

local setmetatable = setmetatable

queue = {}

local metatable = {__index = queue}
queue.metatable = metatable

-- The queue class stores its front and back indices in the same table as the
-- elements:
--
-- * index 1: front
-- * index 2: back
-- * indices 3..: elements
--
-- This is done in order to avoid allocating more memory than needed, as in
-- both PUC Lua and LuaJIT the hash part of the table is much less efficient to
-- access, even though it looks cleaner (compare `queue.front` to `queue[1]`).

-- Pushes the `element` to the back of the queue
function queue:push(element)
	self[self[2]] = element
	self[2] = self[2] + 1
end

-- Returns the front-most element of the queue
function queue:pop()
	local element = self[self[1]]
	if element == nil then return end

	self[self[1]] = nil
	self[1] = self[1] + 1
	return element
end

-- Returns the size of the queue
function queue:length()
	return self[2] - self[1]
end
metatable.__len = queue.length

-- Simple queue iterator: loops through the elements until it had reached the
-- back of the queue
function queue:iterate()
	local i = self[1] - 1
	return function()
		i = i + 1
		if self[2] <= i then return end
		return i - 2, self[i]
	end
end

-- Creates a new empty queue
local function new()
	-- 3 is the next available index as 1 & 2 are reserved
	return setmetatable({3, 3}, metatable)
end
queue.new = new

-- Creates a queue from an existing list
function queue.from(list)
	local new_queue = new()
	for _, element in ipairs(list) do
		new_queue:push(element)
	end
	return new_queue
end
