local function R(R,...)for d,e in ipairs({...})do for d,e in pairs(e)do R[d]=e end end return R end local function d(R,d,e)assert(type(R)=="\116\097\098\108\101","\070\105\114\115\116 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \116\097\098\108\101")assert(d==nil or type(d)=="\115\116\114\105\110\103","\083\101\099\111\110\100 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103 \111\114 \110\105\108")d=d or"\084\065\066\076\069"local B={}local C=" - "local function z(R,d)B[#B+1]=C:rep(d)..(R.."\n")end local function y(R,d)return tostring(R.k)<tostring(d.k)end local function a(R,d,B)z(B.."\058",d-1)local C={}local M={}local F=0 for R,d in pairs(R)do if type(d)=="\116\097\098\108\101"then table.insert(M,{k=R,v=d})else table.insert(C,{k=R,v="\091"..(typeof(d)..("\093 "..tostring(d)))})end local e=#tostring(R)+1 if e>F then F=e end end table.sort(C,y)table.sort(M,y)for R,e in pairs(C)do z(tostring(e.k)..("\058"..((" "):rep(F-#tostring(e.k))..e.v)),d)end if e then for R,e in pairs(M)do a(e.v,d+1,tostring(e.k)..((" "):rep(F-#tostring(e.k)).." \091\084\097\098\108\101\093"))end else for R,e in pairs(M)do z(tostring(e.k)..("\058"..((" "):rep(F-#tostring(e.k)).."\091\084\097\098\108\101\093")),d)end end end a(R,1,d)print(table.concat(B,""))end local function e(R,d)for e=1,#R,1 do if R[e]==d then return e end end return nil end local function B(R)local d=#R local e=table.create(d)for B=1,d,1 do e[B]=R[(d-B)+1]end return e end local function C(R)assert(type(R)=="\116\097\098\108\101","\070\105\114\115\116 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \116\097\098\108\101")local d=Random.new()for e=#R,2,-1 do local B=d:NextInteger(1,e)R[e],R[B]=R[B],R[e]end end local function z(R)return next(R)==nil end local function y(R)return http:JSONEncode(R)end local function a(R)return http:JSONDecode(R)end local function M(R,d)local B=e(R,d)if B then FastRemove(R,B)return true,B end return false,nil end TableUtil.Copy=CopyTable TableUtil.CopyShallow=CopyTableShallow TableUtil.Sync=Sync TableUtil.FastRemove=FastRemove TableUtil.FastRemoveFirstValue=M TableUtil.Print=d TableUtil.Map=Map TableUtil.Filter=Filter TableUtil.Reduce=Reduce TableUtil.Assign=R TableUtil.IndexOf=e TableUtil.Reverse=B TableUtil.Shuffle=C TableUtil.IsEmpty=z TableUtil.EncodeJSON=y TableUtil.DecodeJSON=a return TableUtil
-- tableUtil.Assign(Table target, ...Table sources)
local function Assign(target, ...)
	for _, src in ipairs({ ... }) do
		for k, v in pairs(src) do
			target[k] = v
		end
	end
	return target
end

local function Print(tbl, label, deepPrint)
	assert(type(tbl) == "table", "First argument must be a table")
	assert(label == nil or type(label) == "string", "Second argument must be a string or nil")

	label = (label or "TABLE")

	local strTbl = {}
	local indent = " - "

	-- Insert(string, indentLevel)
	local function Insert(s, l)
		strTbl[#strTbl + 1] = (indent:rep(l) .. s .. "\n")
	end

	local function AlphaKeySort(a, b)
		return (tostring(a.k) < tostring(b.k))
	end

	local function PrintTable(t, lvl, lbl)
		Insert(lbl .. ":", lvl - 1)
		local nonTbls = {}
		local tbls = {}
		local keySpaces = 0
		for k, v in pairs(t) do
			if type(v) == "table" then
				table.insert(tbls, { k = k, v = v })
			else
				table.insert(nonTbls, { k = k, v = "[" .. typeof(v) .. "] " .. tostring(v) })
			end
			local spaces = #tostring(k) + 1
			if spaces > keySpaces then
				keySpaces = spaces
			end
		end
		table.sort(nonTbls, AlphaKeySort)
		table.sort(tbls, AlphaKeySort)
		for _, v in pairs(nonTbls) do
			Insert(tostring(v.k) .. ":" .. (" "):rep(keySpaces - #tostring(v.k)) .. v.v, lvl)
		end
		if deepPrint then
			for _, v in pairs(tbls) do
				PrintTable(v.v, lvl + 1, tostring(v.k) .. (" "):rep(keySpaces - #tostring(v.k)) .. " [Table]")
			end
		else
			for _, v in pairs(tbls) do
				Insert(tostring(v.k) .. ":" .. (" "):rep(keySpaces - #tostring(v.k)) .. "[Table]", lvl)
			end
		end
	end

	PrintTable(tbl, 1, label)

	print(table.concat(strTbl, ""))
end

local function IndexOf(tbl, item)
	for i = 1, #tbl do
		if tbl[i] == item then
			return i
		end
	end
	return nil
end

local function Reverse(tbl)
	local n = #tbl
	local tblRev = table.create(n)
	for i = 1, n do
		tblRev[i] = tbl[n - i + 1]
	end
	return tblRev
end

local function Shuffle(tbl)
	assert(type(tbl) == "table", "First argument must be a table")
	local rng = Random.new()
	for i = #tbl, 2, -1 do
		local j = rng:NextInteger(1, i)
		tbl[i], tbl[j] = tbl[j], tbl[i]
	end
end

local function IsEmpty(tbl)
	return (next(tbl) == nil)
end

local function EncodeJSON(tbl)
	return http:JSONEncode(tbl)
end

local function DecodeJSON(str)
	return http:JSONDecode(str)
end

local function FastRemoveFirstValue(t, v)
	local index = IndexOf(t, v)
	if index then
		FastRemove(t, index)
		return true, index
	end
	return false, nil
end

TableUtil.Copy = CopyTable
TableUtil.CopyShallow = CopyTableShallow
TableUtil.Sync = Sync
TableUtil.FastRemove = FastRemove
TableUtil.FastRemoveFirstValue = FastRemoveFirstValue
TableUtil.Print = Print
TableUtil.Map = Map
TableUtil.Filter = Filter
TableUtil.Reduce = Reduce
TableUtil.Assign = Assign
TableUtil.IndexOf = IndexOf
TableUtil.Reverse = Reverse
TableUtil.Shuffle = Shuffle
TableUtil.IsEmpty = IsEmpty
TableUtil.EncodeJSON = EncodeJSON
TableUtil.DecodeJSON = DecodeJSON

return TableUtil
