--[[ @brief Returns the number of entries in a given table.
--]]

function module.CountMapEntries(t)
	local n = 0;
	for i in pairs(t) do
		n = n + 1;
	end
	return n;
end

module.newLayeredTable = require(script.LayeredTable).new;
module.newReadOnlyWrapper = require(script.ReadOnlyWrapper).new;

function module.AddTableToTable(t1, t2)
	local output = {};
	for i, v in pairs(t1) do
		output[i] = v + t2[i];
	end
	return output;
end
function module.AddNumberToTable(n, t)
	local output = {};
	for i, v in pairs(t) do
		output[i] = v + n;
	end
	return output;
end
function module.Add(...)
	local AddQueue = {...};
	--Peel off the last two elements and add them.
	for i = #AddQueue - 1, 1, -1 do
		local a = AddQueue[i + 1];
		local b = AddQueue[i];
		if type(a) == 'table' then
			if type(b) == 'table' then
				AddQueue[i] = module.AddTableToTable(a, b);
			else
				AddQueue[i] = module.AddNumberToTable(b, a);
			end
		else
			if type(b) == 'table' then
				AddQueue[i] = module.AddNumberToTable(a, b);
			else
				AddQueue[i] = a * b;
			end
		end
	end
	return AddQueue[1];
end

function module.MultiplyTableByTable(t1, t2)
	local output = {};
	for i = 1, #t1 do
		output[i] = t1[i] * t2[i];
	end
	return output;
end
function module.MultiplyNumberByTable(n, t)
	local output = {};
	for i = 1, #t do
		output[i] = t[i] * n;
	end
	return output;
end
function module.Multiply(t1, t2)
	if type(t1) == 'table' then
		if type(t2) == 'number' then
			return module.MultiplyNumberByTable(t2, t1);
		elseif type(t2) == 'table' then
			return module.MultiplyTableByTable(t1, t2);
		else
			Utils.Log.AssertNonNilAndType("argument 2", "table or number", t2);
		end
	elseif type(t1) == 'number' then
		if type(t2) == 'table' then
			return module.MultiplyNumberByTable(t1, t2);
		else
			Utils.Log.AssertNonNilAndType("argument 2", "table", t2);
		end
	end
end

local function rawRange(start, stop, step)
	local output = {};
	if step > 0 then
		local i = start;
		while i < stop do
			output[#output + 1] = i;
			i = i + step;
		end
	elseif step < 0 then
		local i = start;
		while i > stop do
			output[#output + 1] = i;
			i = i + step;
		end
	end
	return output;
end
function module.Range(start, stop, step)
	if start and stop and step then
		return rawRange(start, stop, step);
	elseif start and stop then
		return rawRange(start, stop, 1);
	elseif start then
		return rawRange(0, start, 1);
	else
		return {};
	end
end

function module.RangeInclusive(start, stop, step)
	return module.Range(start, stop + step/2, step);
end
