local function w(w,...)for n,N in ipairs({...})do for n,N in pairs(N)do w[n]=N end end return w end local function n(w,n,N)assert(type(w)=="\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(n==nil or type(n)=="\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")n=n or"\084\065\066\076\069"local X={}local t=" - "local function H(w,n)X[#X+1]=t:rep(n)..(w.."\n")end local function q(w,n)return tostring(w.k)<tostring(n.k)end local function R(w,n,X)H(X.."\058",n-1)local t={}local d={}local p=0 for w,n in pairs(w)do if type(n)=="\116\097\098\108\101"then table.insert(d,{k=w;v=n})else table.insert(t,{k=w,v="\091"..(typeof(n)..("\093 "..tostring(n)))})end local N=#tostring(w)+1 if N>p then p=N end end table.sort(t,q)table.sort(d,q)for w,N in pairs(t)do H(tostring(N.k)..("\058"..((" "):rep(p-#tostring(N.k))..N.v)),n)end if N then for w,N in pairs(d)do R(N.v,n+1,tostring(N.k)..((" "):rep(p-#tostring(N.k)).." \091\084\097\098\108\101\093"))end else for w,N in pairs(d)do H(tostring(N.k)..("\058"..((" "):rep(p-#tostring(N.k)).."\091\084\097\098\108\101\093")),n)end end end R(w,1,n)print(table.concat(X,""))end local function N(w,n)for N=1,#w,1 do if w[N]==n then return N end end return nil end local function X(w)local n=#w local N=table.create(n)for X=1,n,1 do N[X]=w[(n-X)+1]end return N end local function t(w)assert(type(w)=="\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 n=Random.new()for N=#w,2,-1 do local X=n:NextInteger(1,N)w[N],w[X]=w[X],w[N]end end local function H(w)return next(w)==nil end local function q(w)return http:JSONEncode(w)end local function R(w)return http:JSONDecode(w)end local function d(w,n)local X=N(w,n)if X then FastRemove(w,X)return true,X end return false,nil end TableUtil.Copy=CopyTable TableUtil.CopyShallow=CopyTableShallow TableUtil.Sync=Sync TableUtil.FastRemove=FastRemove TableUtil.FastRemoveFirstValue=d TableUtil.Print=n TableUtil.Map=Map TableUtil.Filter=Filter TableUtil.Reduce=Reduce TableUtil.Assign=w TableUtil.IndexOf=N TableUtil.Reverse=X TableUtil.Shuffle=t TableUtil.IsEmpty=H TableUtil.EncodeJSON=q TableUtil.DecodeJSON=R return TableUtil

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
