--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
--|	GypsyMod Library - Gypsy_Debug.lua
--|	Debugging tools
--|	Respect to Dhargo, creator of Flexbar, for the meta table usage
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--

-- Isolated file version
local version = 1.01;

--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
--|	Version History
--|	1.00 - Initial library will full complement of print functions
--|	1.01 - Removed Print method
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--

-- Load only if the library has not been loaded previously, or if previously loaded versions are older
if (not Gypsy_Debug or not Gypsy_Debug.version or Gypsy_Debug.version < version) then
	
	-- Depends on other libraries being loaded first, exit if they have not been
	if (not Gypsy_Color or not Gypsy_Utility) then
		return;
	end
	
	--= Libraries =--
	
	local color = Gypsy_Color:New();
	local utility = Gypsy_Utility:New();	
	
	Gypsy_Debug = {};
	Gypsy_Debug.version = version;

	-- Target chat frame number to use for debug output
	Gypsy_Debug.console = 7;
	-- Console title string, can be replaced with localized version
	Gypsy_Debug.consoleTitle = "Debug";
	-- Selected level of debug output - full or partial
	Gypsy_Debug.level = "partial";
	-- List of developer characters to load for
	Gypsy_Debug.devlist = {"Morquan", "Mondinga", "Jaruden", "Cairhien"};
	-- Tab size for table printing
	Gypsy_Debug.tab = "  ";
		
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:New
	--|	Used to make this library available for use locally from script files. 
	--|		Usage: local debug = Gypsy_Debug:New();
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:New ()			
		local object = {};
		setmetatable(object, self);
		self.__index = self;
		return object;
	end
	
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:DPrint
	--|	A debug specific formatted print-out to the debug console. Accepts an optional
	--|	level parameter which will allow it to override "partial" print level restictions.
	--|	Also accepts an optional source string.
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:DPrint (msg, src, level, r, g, b)
		if (not msg) then	msg = "nil";	end
		if (not src) then	src = "----";	end
		
		if (self.level == "partial" and not level) then		return;		end
		
		utility:Print(color.orange.code.."["..src..">]"..color.close..msg, self.console, r, g, b);
	end
	
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:EPrint
	--|	An error-specific debug printer, automatically colors output red, and overrides
	--|	output level.
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:EPrint (msg, src)
		if (not msg) then	msg = "nil";	end		
		
		self:DPrint(msg, src, 1, 1.0, 0.0, 0.0);
	end
	
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:MPrint
	--|	Prints memory usage to a target chat frame or error frame.
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:MPrint (target)
		local mem = gcinfo() / 1024;
		
		if (strfind(mem, ".")) then
			mem = strsub(mem, 1, strfind(mem, ".")+2);
		end
		
		utility:Print("Memory usage: "..mem.." MB", target);
	end
	
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:TPrint
	--|	A general purpose table printer. This function can print either whole tables or
	--|	select indexes from a table. It requires a name string, which should coorespond
	--|	to what it is printing - usually the table name or table + index. It will also
	--|	accept a table reference, but if none is passed, will attempt to get a global
	--|	reference based on the name string passed. It will also recieve an optional source
	--|	string, to describe the calling environment. Note that it can recieve an 'indent'
	--|	parameter, but this should never be supplied explicitely. The indent parameter
	--|	is used when the function finds a nested table in any index which it scans and 
	--|	calls back to itself, to make printed data readable.
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:TPrint (name, table, index, src, level, indent)
		if (self.level == "partial" and not level) then		return;		end
		
		if (not table) then
			table = getglobal(name);
		end
		if (not table or type(table) ~= "table") then
			return;
		end
		if (index and type(index) ~= "string" and type(index) ~= "number") then
			return;
		end
		
		-- Form indentation
		local space = self.tab;
		if (indent) then
			for i=1, indent do
				space = space..self.tab;
			end
		else
			indent = 0;
		end
		
		-- Specific steps only reached when an explicit index is supplied - the function will never supply an index to iself, so this code will run only once ever
		if (index and table[index]) then
			if (type(table[index]) == "table") then
				self:TPrint(color.orange.code..name.."["..index.."]"..color.close, table[index], nil, nil, 1);
			else
				self:DPrint(color.yellow.code..name.."["..index.."]"..color.close.." = "..color.white.code..table[index]..color.close..";", nil, 1, color.grey.r, color.grey.g, color.grey.b);
			end
		else		
			self:DPrint(color.orange.code..name..color.close.." = {", src, 1, color.grey.r, color.grey.g, color.grey.b);		
		
			for i,v in table do
				if (type(v) == "table") then
					self:TPrint(space..color.green.code.."["..i.."]"..color.close, v, nil, nil, 1, indent+1);
				else
					local msg = nil;
					-- Detect function references which can't be printed normally, and simply let the user know a function is there
					if (type(v) == "function") then
						msg = "FUNCTION";
					elseif (type(v) == "userdata") then
						msg = "USERDATA";
					else
						msg = v;
					end
					self:DPrint(space..color.yellow.code.."["..i.."]"..color.close.." = "..color.white.code..msg..color.close..";", nil, 1, color.grey.r, color.grey.g, color.grey.b);
				end
			end

			self:DPrint(strsub(space, strlen(self.tab)+1).."};", nil, 1, color.grey.r, color.grey.g, color.grey.b);
		end
	end	
	
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	--|	Gypsy_Debug:Console
	--|	Toggles the set chat frame on and off and sets it up for use as debug console.
	--|	Hoping to replace this in the future with an actual console-like window, not
	--|	utilizing any chat windows, as they cause issues with some output.
	--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
	
	function Gypsy_Debug:Console (toggle)
		local frame = getglobal("ChatFrame"..self.console);
		
		if (not toggle) then
			if (frame:IsVisible()) then
				toggle = 0;
			else
				toggle = 1;
			end
		end
		
		if (toggle ~= 1 and toggle ~= 0) then
			return;
		end
			
		if (toggle == 1) then
			if (not frame:IsVisible()) then
				frame:Show();
			end							
			FCF_SetWindowName(frame, self.consoleTitle, 1);	
		else
			FCF_SetWindowName(frame, "", 1);
			FCF_Close(frame);
		end
	end
end