local function c(c,...)for m,V in ipairs({...})do for m,V in pairs(V)do c[m]=V end end return c end local function m(c,m)for m,V in pairs(m)do c[m]=V end end local function V(c,m,V)assert(type(c)=="\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(m==nil or type(m)=="\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")m=m or"\084\065\066\076\069"local R={}local O=" - "local function L(c,m)R[#R+1]=O:rep(m)..(c.."\n")end local function Z(c,m)return tostring(c.k)<tostring(m.k)end local function D(c,m,R)L(R.."\058",m-1)local O={}local f={}local d=0 for c,m in pairs(c)do if type(m)=="\116\097\098\108\101"then table.insert(f,{k=c,v=m})else table.insert(O,{k=c;v="\091"..(typeof(m)..("\093 "..tostring(m)))})end local V=#tostring(c)+1 if V>d then d=V end end table.sort(O,Z)table.sort(f,Z)for c,V in ipairs(O)do L(tostring(V.k)..("\058"..((" "):rep(d-#tostring(V.k))..V.v)),m)end if V then for c,V in ipairs(f)do D(V.v,m+1,tostring(V.k)..((" "):rep(d-#tostring(V.k)).." \091\084\097\098\108\101\093"))end else for c,V in ipairs(f)do L(tostring(V.k)..("\058"..((" "):rep(d-#tostring(V.k)).."\091\084\097\098\108\101\093")),m)end end end D(c,1,m)print(table.concat(R,""))end local function R(c)local m=#c local V=table.create(m)for R=1,m,1 do V[R]=c[(m-R)+1]end return V end local function O(c)assert(type(c)=="\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 m=Random.new()for V=#c,2,-1 do local R=m:NextInteger(1,V)c[V],c[R]=c[R],c[V]end end local function L(c)return next(c)==nil end local function Z(c)return http:JSONEncode(c)end local function D(c)return http:JSONDecode(c)end local function f(c,m)local V=IndexOf(c,m)if V then FastRemove(c,V)return true,V end return false,nil end TableUtil.Copy=CopyTable TableUtil.CopyShallow=CopyTableShallow TableUtil.Sync=Sync TableUtil.FastRemove=FastRemove TableUtil.FastRemoveFirstValue=f TableUtil.Print=V TableUtil.Map=Map TableUtil.Filter=Filter TableUtil.Reduce=Reduce TableUtil.Assign=c TableUtil.Extend=m TableUtil.IndexOf=IndexOf TableUtil.Reverse=R TableUtil.Shuffle=O TableUtil.IsEmpty=L TableUtil.EncodeJSON=Z TableUtil.DecodeJSON=D 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 Extend(tbl, extension)
	for k,v in pairs(extension) do
		tbl[k] = v
	end
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 ipairs(nonTbls) do
			Insert(tostring(v.k) .. ":" .. (" "):rep(keySpaces - #tostring(v.k)) .. v.v, lvl)
		end
		if (deepPrint) then
			for _,v in ipairs(tbls) do
				PrintTable(v.v, lvl + 1, tostring(v.k) .. (" "):rep(keySpaces - #tostring(v.k)) .. " [Table]")
			end
		else
			for _,v in ipairs(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 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.Extend = Extend
TableUtil.IndexOf = IndexOf
TableUtil.Reverse = Reverse
TableUtil.Shuffle = Shuffle
TableUtil.IsEmpty = IsEmpty
TableUtil.EncodeJSON = EncodeJSON
TableUtil.DecodeJSON = DecodeJSON


return TableUtil
