--[[ ---------------------------------------------------------------------------
Created:		1/1/2011 12:34:27 AM
Last Modified:	2011-01-02T05:58:05Z
Author:			orgevo
Version:		v1.3a

Lib-OrgEvoUtils:	Collection of private utilities for me.
----------------------------------------------------------------------------- ]]
--[===[@debug@

local ADDON_TAG				= "AtlasLootAdvancedSearch"
alas_addon					= AtlasLootAdvancedSearch;
local string, table, pairs, ipairs, tostring = string, table, pairs, ipairs, tostring;
local strformat, strrep, strsub, strgsub, strlen = string.format, string.rep, string.sub, string.gsub, string.len
local tinsert, tremove, tsort = table.insert, table.remove, table.sort


local function LclRenderStr(Obj, TruncLen)
	local typeStr = type(Obj)
	if typeStr == "string" then
--		Obj = strgsub(Obj, "\t", "    ");
		Obj = strgsub(Obj, "[^%w%p ]", function(Ch)
			return "\\" .. strformat("%03d", string.byte(Ch))
		end )
		
		if TruncLen and TruncLen > 0 and strlen(Obj) > TruncLen + 3 then
			-- This could misleadingly truncate numeric escape value
			Obj = strsub(Obj, 1, TruncLen) .. "..."
		end
		Obj = '"' .. Obj .. '"';
	elseif typeStr == "boolean" then
		Obj = "boolean: " .. tostring(Obj);
	else
		Obj = tostring(Obj);
	end
	return Obj
end

-- This function replaces ["x"]["y"] stubble with x.y. Keys are assumed to be
-- identifier-compatible.

local function LclShave(Str)
	local Count
	Str, Count = strgsub(Str, '^%[%"(.+)%"%]$', '%1');
	if Count == 1 then
		Str = strgsub(Str, '%"%]%[%"', '.');
	end
	return Str
end

local function LclRender(Tbl, Val, KeyStr, TruncLen, Lvl, Visited, KeyPathStr)
	local valueTypeStr, valueStr;
	
	valueTypeStr = type(Val)
	
	if Visited[Val] then
		valueStr = "same as " .. Visited[Val];
		
	else
		valueStr = LclRenderStr(Val, TruncLen);
		if valueTypeStr == "function" then -- Display function's environment
			local Env = getfenv(Val);
			Env = Visited[Env] or Env;
			valueStr = strgsub(valueStr, "(function:%s*.*)$", "%1 (env " ..
				strgsub(tostring(Env), "table: ", "")	.. ")")
				
		elseif valueTypeStr == "table" then
			valueStr = valueStr .. strformat(" (n = %d)", #Val)
		end
	end
	
	KeyPathStr = KeyPathStr .. "[" .. KeyStr .. "]"
	tinsert(Tbl, { Lvl, strformat('[%s] %s', KeyStr, valueStr) })
	if valueTypeStr == "table" and not Visited[Val] then
		Visited[Val] = LclShave(KeyPathStr)
		local SrtTbl = {}
		for K, V in pairs(Val) do
			tinsert(SrtTbl, { LclRenderStr(K, TruncLen), V, K, type(K) })
		end
		local function LclCmp(A, B)
			local Cmp
			local Ta, Tb = A[4], B[4]
			if Ta == "number" then
				if Tb == "number" then
					Cmp = A[3] < B[3]
				else
					Cmp = true -- Numbers appear first
				end
			else -- A is not a number
				if Tb == "number" then
					Cmp = false -- Numbers appear first
				else
					Cmp = A[1] < B[1]
				end
			end
			return Cmp
		end
		tsort(SrtTbl, LclCmp)
		for J, Rec in ipairs(SrtTbl) do
			LclRender(Tbl, Rec[2], Rec[1], TruncLen, Lvl + 1, Visited, KeyPathStr)
		end
	end
end

-- This function appends a series of records of the form { level,
-- description_string } to the indexed table specified by Tbl. When this
-- function returns, Tbl can be used to inspect the Lua object specified by
-- Val. Key specifies the name of the object. TruncLen specifies the maximum
-- length of each description string; if this value is zero, no truncation will
-- take place. Keys are sorted natively (that is, numbers are sorted
-- numerically and everything else lexically). String values are displayed with
-- quotes, numbers are unadorned, and all other values have an identifying
-- prefix such as "boolean". Consequently, all keys are displayed within their
-- type partition. This function returns nothing; its only effect is to augment
-- Tbl.

function ObjectDescribe(Tbl, Val, Key, TruncLen)
	LclRender(Tbl, Val, LclRenderStr(Key, TruncLen), TruncLen or 0, 1, {}, "")
end

-- This function prints a hierarchical summary of the object specified by Val
-- to standard out. See ObjectDescribe for more details.
function DumpObject(Val, Key, TruncLen)
	local Tbl = {}
	ObjectDescribe(Tbl, Val, Key, TruncLen);
	for J, Rec in ipairs(Tbl) do
		print(strrep("    ", Rec[1] - 1), Rec[2]);
	end
end


function ALAS_DumpObj( obj, objTag )
	DumpObject(obj, objTag);
end


function ALAS_CopyTable( SrcTable, tablesCopied )
	local Dest;
	if tablesCopied then
		-- this will only set Dest if Src has been seen before
		Dest = tablesCopied[SrcTable];
	else
		-- initial call
		tablesCopied = {};
	end
	
	-- so if we haven't encountered SrcTable yet, create a copy and store it into our list of tables that have already been copied
	if not Dest then
		Dest = {}
		tablesCopied[SrcTable] = Dest;
		for key, val in pairs(SrcTable) do
			key = type(key) == "table" and ALAS_CopyTable(key, tablesCopied) or key;
			val = type(val) == "table" and ALAS_CopyTable(val, tablesCopied) or val;
			Dest[key] = val;
		end
	end
	return Dest;
end

--@end-debug@]===]