view Core.lua @ 50:8e2138877ebf

Added neat(er) tooltips for both the mail opener status toggler as the config button. Added an option below the filters to disable the shift click functionality of the open all button.
author Zerotorescue
date Sun, 12 Sep 2010 21:06:05 +0200
parents 1805df31794d
children fcc7112cc365
line wrap: on
line source
-- You can access this addon's object through: LibStub("AceAddon-3.0"):GetAddon("MailOpener")
local MailOpener = LibStub("AceAddon-3.0"):NewAddon("MailOpener", "AceEvent-3.0", "AceTimer-3.0");

-- You can check if MailOpener is busy with the global MailAddonBusy (if not MailAddonBusy then ...do something... end)
-- MailAddonBusy will be nil when nothing is happening or filled with the addon name when MO is working
-- Another addon can use this variable to indicate they're working too, MailOpener will then wait for that to finish

local AutoOpenMail, MailOpenerConfig, lastAmount, lastQuickAuctionsStatus, freshList, mailboxEmptySoundPlayed, mailboxEmptySoundPlayedThisVisit;

function MailOpener:OnInitialize()
	self:Debug("OnInitialize");
	
	
	
	
	-- SAVED VARIABLES
	
	local defaults = {
		profile = {
			uses = 0,
			general = {
				defaultStatus = "disabled", -- addon enabled, but mail opening not auto on
				defaultQAStatus = "__remember",
				continueOpeningStackableItems = false,
				autoDisableQAAutoMail = true,
				autoReenableQAAutoMail = false,
				autoSetBackQAAutoMail = true,
				continueOpening = false,
				waitTime = 5,
				initialDelay = 0.5,
			},
			modules = {
				BeanCounterSupport = true,
				Config = false,
				Collected = true,
				FailSafe = true,
			},
			notifications = {
				welcome = false,
				bye = false,
				finishedCurrentBatch = true,
				mailboxIsEmpty = true,
				
				skipped = {
					all = true,
					inventoryFull = true,
					keepFreeSpaceLimit = true,
					GMMail = true,
					COD = true,
					normalGoldMail = true,
					normalItemsMail = true,
					AHexpired = true,
					AHsuccess = true,
					AHwon = true,
					AHcanceled = true,
					AHoutbid = true,
					other = true,
				},
				processed = {
					all = true,
					normalGoldMail = true,
					normalItemsMail = true,
					AHexpired = true,
					AHsuccess = true,
					AHwon = true,
					AHcanceled = true,
					AHoutbid = true,
					other = true,
				},
				
				bagsFullSound = false,
				bagsFullSoundFile = "Sound\\Spells\\SimonGame_Visual_BadPress.wav",
				bagsFullSoundFileName = "Simon Error",
				bagsFullSoundOnlyOnce = true,
				bagsFullSoundOnlyOncePerMailboxVisit = false,
				mailboxEmptySound = false,
				mailboxEmptySoundFile = "Sound\\Spells\\SimonGame_Visual_GameStart.wav",
				mailboxEmptySoundFileName = "Simon Start",
				mailboxEmptySoundOnlyOnce = true,
				mailboxEmptySoundOnlyOncePerMailboxVisit = false,
			},
		},
	};
	
	-- Register our saved variables database
	self.db = LibStub("AceDB-3.0"):New("MailOpenerDB", defaults, true);
	
	
	
	
	
	-- MODULE TOGGLING
	
	-- Don't enable the config module until we need it
	for name, module in self:IterateModules() do
		if self.db.profile.modules[name] ~= nil then
			if self.db.profile.modules[name] then
				self:Debug("|cff00ff00Enabling|r module: " .. name);
			else
				self:Debug("|cffff0000Disabling|r module: " .. name);
			end
			
			module:SetEnabledState(self.db.profile.modules[name]);
		end
	end
	
	
	
	
	
	-- SLASH COMMANDS
	
	-- Disable the AddonLoader slash commands
	SLASH_MO1 = nil;
	SLASH_MAILOPEN1 = nil;
	SLASH_MAILOPENER1 = nil;
	
	-- Register our own slash commands
	SLASH_MAILOPENER1 = "/mo";
	SLASH_MAILOPENER2 = "/mailopen";
	SLASH_MAILOPENER3 = "/mailopener";
	SlashCmdList["MAILOPENER"] = function(msg)
		MailOpener:EnableConfigModule();
		
		MailOpenerConfig:CommandHandler(msg);
	end
	
	
	
	
	
	-- INTERFACE OPTIONS
		
	 -- Attempt to remove the interface options added by AddonLoader (if enabled)
	if AddonLoader and AddonLoader.RemoveInterfaceOptions then
		AddonLoader:RemoveInterfaceOptions("Mail Opener");
	end
	
	-- Now create our own options frame
	local frame = CreateFrame("Frame", nil, UIParent);
	frame:Hide();
	frame.name = "Mail Opener";
	frame:HookScript("OnShow", function(self)
		-- Enable the config module
		MailOpener:EnableConfigModule();
		
		-- Load the options and add it to the blizzard interface list
		MailOpenerConfig:Load();
		
		-- Refresh the frame to instantly show the right options
		InterfaceOptionsFrame_OpenToCategory(self.name)
	end);
	-- And add it to the interface options
	InterfaceOptions_AddCategory(frame);
	
	
	
	
	
	-- ADDON / MAIL OPENING STATUS TOGGLER
	
	-- Make the open all checkbox
	local check = CreateFrame("CheckButton", "cbMailOpenerEnable", MailFrame, "OptionsCheckButtonTemplate");
	check:SetHeight(26);
	check:SetWidth(26);
	check:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 68, -13);
	check:SetChecked(true);
	check:SetHitRectInsets(0, -80, 0, 0);
	check:SetScript("OnClick", function(self)
		if IsShiftKeyDown() then
			-- Shift key = toggle addon on or off, since addon is already on there's only one option
			
			if not MailOpener:IsEnabled() then
				print("|cff15ff00Mail Opener|r: Shift key was held down, so |cff00ff00enabling|r the entire addon as well as automatic opening of mail.");
				
				MailOpener:Enable();
				
				-- The above calls MAIL_SHOW which changes AutoOpenMail, so we can't remember the old setting
				AutoOpenMail = true;
				
				self:SetChecked(true);
			else
				print("|cff15ff00Mail Opener|r: Shift key was held down, so |cffff0000disabling|r the entire addon.");
				
				MailOpener:Disable();
				
				self:SetChecked(false);
			end
		else
			-- Normal click
			
			if self:GetChecked() then
				print("|cff15ff00Mail Opener|r: |cff00ff00Enabling|r automatic opening of mail.");
				
				AutoOpenMail = true;
				MailOpener:ScheduleOpen(false);
			else
				print("|cff15ff00Mail Opener|r: |cffff0000Disabling|r automatic opening of mail.");
				
				AutoOpenMail = false;
			end
		end
	end);
	check.tooltipTitle = "Mail Opener status";
	check.tooltip = "Toggle automatic mail opening |cff00ff00on|r or |cffff0000off|r (you can also enforce this by holding shift when opening the mailbox).\n\nYou can also hold the |cfffed000shift|r key while clicking this checkbox to disable the entire addon instead.";
	check:SetScript("OnEnter", function(self)
		GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
		GameTooltip:SetPoint("BOTTOM", self, "BOTTOM")
		GameTooltip:SetText(self.tooltipTitle, 1, .82, 0, 1)
		
		if type(self.tooltip) == "string" then
			GameTooltip:AddLine(self.tooltip, 1, 1, 1, 1);
		end
		
		GameTooltip:Show();
	end);
	button:SetScript("OnLeave", function(self)
		GameTooltip:Hide();
	end);
	
	-- Get reference to the text field
	local checkboxText = _G[check:GetName() .. "Text"];
	checkboxText:SetText("Mail Opener");
	
	self.cbOpenAll = check;
	
	
	
	
	-- CONFIG BUTTON
	
	-- Make the config button
	local button = CreateFrame("Button", "btnMailOpenerConfig", MailFrame, "UIPanelButtonTemplate")
	button:SetText("Config")
	button:SetHeight(23)
	button:SetWidth(55)
	button:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -55, -13);
	button:SetScript("OnClick", function()
		MailOpener:EnableConfigModule();
		
		MailOpenerConfig:Show();
	
		--BETA:if MailOpener.db.profile.uses >= 15 then
		--BETA:	MailOpener:ShowBetaPopup();
		--BETA:end
	end);
	button.tooltipTitle = "Mail Opener Config";
	button.tooltip = "Click to open the configuration window for Mail Opener.";
	button:SetScript("OnEnter", function(self)
		GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
		GameTooltip:SetPoint("BOTTOM", self, "TOP")
		GameTooltip:SetText(self.tooltipTitle, 1, .82, 0, 1)
		
		if type(self.tooltip) == "string" then
			GameTooltip:AddLine(self.tooltip, 1, 1, 1, 1);
		end
		
		GameTooltip:Show();
	end);
	button:SetScript("OnLeave", function(self)
		GameTooltip:Hide();
	end);
	
	self.btnConfig = button;
	
	
	
	
	
	-- ADDON LOADING
	-- THE BELOW WILL TAKE SOME TIME; WE WILL BE LOADING OTHER ADDONS
	
	if select(6, GetAddOnInfo("Postal")) == nil then
		self.PostalEnabled = true; -- Set this as an object variable so we can use it in our modules
		
		-- Ensure this addon is loaded if AddonLoader is installed
		if AddonLoader and AddonLoader.LoadAddOn and not Postal then
			AddonLoader:LoadAddOn("Postal");
		end
	end
	
	if select(6, GetAddOnInfo("QuickAuctions")) == nil then
		self.QuickAuctionsEnabled = true; -- Set this as an object variable so we can use it in our modules
		
		-- Ensure this addon is loaded if AddonLoader is installed
		if AddonLoader and AddonLoader.LoadAddOn then
			AddonLoader:LoadAddOn("QuickAuctions");
		end
	end
	
	
	
	
	
	-- ADJUST POSITIONS
	
	if self.QuickAuctionsEnabled then
		-- QA is enabled so move the checkbox further to the right
		
		self.cbOpenAll:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 155, -13);
	end
	
	if self.PostalEnabled then
		self.btnConfig:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -75, -13);
	end
end

function MailOpener:OnEnable()
	self:RegisterEvent("MAIL_SHOW");
	self:RegisterEvent("PLAYER_ENTERING_WORLD");
	
	self.btnConfig:Show();
	
	-- Reset variables
	lastAmount = 0;
	self.debugChannel = nil;
	
	--BETA:if (self.db.profile.uses % 15) == 0 then
	--BETA:	-- Automatically show once every 15 uses
	--BETA:	self:ShowBetaPopup();
	--BETA:end
	
	-- If we were toggling this addon on while the mailbox is opened we must register all events again
	if MailFrame:IsVisible() then
		self:MAIL_SHOW();
	end
end

function MailOpener:OnDisable()
	self:UnregisterEvent("MAIL_SHOW");
	
	self.btnConfig:Hide();
	
	MailOpener:Stop();
end

-- We must disable Quick Auction's auto mail (if set up that way in the settings) before opening the mailbox or it will instantly start sending stuff
function MailOpener:PLAYER_ENTERING_WORLD()
	self:UnregisterEvent("PLAYER_ENTERING_WORLD");
	
	self:ToggleQAStatus();
end

-- Fired when the mailbox is opened
function MailOpener:MAIL_SHOW()
	-- To stop the timer when the mailbox is closed
	self:RegisterEvent("MAIL_CLOSED", "Stop");
	self:RegisterEvent("PLAYER_LEAVING_WORLD", "Stop");
	
	-- To set the timer for when to refresh again
	self:RegisterEvent("MAIL_INBOX_UPDATE");
	
	-- We need to know when opening has completed
	self:RegisterMessage("MO_OPEN_COMPLETE");
	
	if self.db.profile.uses == 0 and MailOpener.db.profile.general.defaultStatus ~= "_enabled" then
		StaticPopupDialogs["MailOpenerFirstUseConfirmBox"] = {
			text = "You are using |cff15ff00Mail Opener|r for the first time. Do you wish to always |cf00ff000enable|r |cfffed000automatic mail opening when you open the mailbox|r?\n\nYou can always change the standard behaviour in the General options.",
			button1 = "Yes",
			button2 = "No",
			OnAccept = function()
				MailOpener.db.profile.general.defaultStatus = "_enabled";
				print("|cff15ff00Mail Opener|r: You can always change the default status in the General config (|cff00ffff/mo c|r).");
				
				print("|cff15ff00Mail Opener|r: |cff00ff00Enabling|r automatic opening of mail.");
				MailOpener.cbOpenAll:SetChecked(true);
				
				AutoOpenMail = true;
				MailOpener:ScheduleOpen(false);
			end,
			OnCancel = function (_,reason)
				print("|cff15ff00Mail Opener|r: You can always change the default status in the General config (|cff00ffff/mo c|r).");
			end,
			timeout = 0,
			whileDead = 1,
			hideOnEscape = 1,
		};
		StaticPopup_Show("MailOpenerFirstUseConfirmBox");
	end
	
	self.db.profile.uses = ( self.db.profile.uses + 1 );
	
	self:Debug("defaultStatus:" .. self.db.profile.general.defaultStatus);
	-- Change the mail opening status according to our settings
	if self.db.profile.general.defaultStatus == "_enabled" then
		AutoOpenMail = true;
		self.cbOpenAll:SetChecked(true);
	elseif self.db.profile.general.defaultStatus == "disabled" then
		-- Disable auto opening but leave mail opener enabled
		
		AutoOpenMail = false;
		self.cbOpenAll:SetChecked(false);
	elseif self.db.profile.general.defaultStatus == "xdisabled" then
		-- Disable entire addon
		
		MailOpener:Disable();
		self.cbOpenAll:SetChecked(false);
	end
	
	if IsShiftKeyDown() then
		print("|cff15ff00Mail Opener|r: |cffff0000Disabling|r automatic opening of mail, shift key was down when opening the mailbox.");
		
		AutoOpenMail = false;
		self.cbOpenAll:SetChecked(false);
	end
	
	self:ToggleQAStatus();
	
	-- Hide the InboxTooMuchMail warning to allow room for our mail remaining info line
	InboxTooMuchMail:Hide()
	InboxTooMuchMail.Show = function() end
	
	if self.QuickAuctionsEnabled then
		local QAMail = LibStub("AceAddon-3.0"):GetAddon("QuickAuctions", true):GetModule("Mail", true);
		
		if QAMail then
			-- Hide the open all button
			QAMail.massOpening:Hide();
			-- Hide the x mail remaining text
			QAMail.totalMail:Hide();
		end
	end
	
	if self.db.profile.notifications.welcome then
		-- Welcome notification
		local _, c = UnitClass("player");
		c = RAID_CLASS_COLORS[c];
		c = string.format("|cff%02x%02x%02x", c.r * 255 + 0.5, c.g * 255 + 0.5, c.b * 255 + 0.5);
	
		print("|cff15ff00Mail Opener|r: Welcome back "..c..UnitName("player").."|r. Requesting new mail from the local Postal Service, your mail will automatically be opened when it becomes available.");
	end
	
	mailboxEmptySoundPlayed = nil;
	mailboxEmptySoundPlayedThisVisit = nil;
	
	self:Recheck();
	
	if self.db.profile.general.continueOpening then
		-- Continue opening mail, but use the "initial mail opening interval" as time
		self:ScheduleOpen(false);
	end
end

-- Fired after a successful server sync
-- Fired when mail is deleted (which happens after taking all attachments from a mail sent by the game)
function MailOpener:MAIL_INBOX_UPDATE()
	local current, total = GetInboxNumItems();
	
	-- Calculate the amount of mail waiting that actually have attachments
	-- If we just compare numbers we won't be including mail that isn't automatically deleted when opened, such as mail with attachments sent by other players
	local currentMailWithAttachments = 0;
	for i = 1, current do
		local _, _, _, _, money, _, _, items = GetInboxHeaderInfo(i);
		
		if (items and items > 0) or (money and money > 0) then
			currentMailWithAttachments = currentMailWithAttachments + 1;
		end
	end
	
	local tempLastAmount = lastAmount;
	lastAmount = currentMailWithAttachments;
	
	--if currentMailWithAttachments ~= tempLastAmount then
	--	self:Debug("MAIL_INBOX_UPDATE - lastAmount:" .. tempLastAmount .. " - current:" .. currentMailWithAttachments);
	--end
	
	if currentMailWithAttachments > tempLastAmount then
		-- New messages arrived in our mailbox, so this was a refresh, so set a timer
		
		self:Debug("MO_SERVER_SYNCED");
		
		-- Yell that we successfully synced with the server
		self:SendMessage("MO_SERVER_SYNCED");
		
		if MailAddonBusy == MailOpener:GetName() then
			MailAddonBusy = nil;
		end
		
		-- This list is fresh
		freshList = true;
		mailboxEmptySoundPlayed = nil;
		
		-- Stop previous timer
		self:CancelTimer(self.tmrRecheck, true);
		-- More will arrive in 60 seconds
		self.tmrRecheck = self:ScheduleTimer(function()
			self:Debug("tmrRecheck 61 finished");
			
			-- We can get a fresh list now, so query the server
			freshList = false;
			
			-- Look for mail
			self:Recheck();
		end, 61);
		self:Debug("tmrRecheck 61");
		
		-- Open the current mail
		self:ScheduleOpen(false);
	elseif currentMailWithAttachments < tempLastAmount then
		-- We lost a mail
		
		--TODO: NYI: May need to delay this until the mail is actually deleted to keep the mail count more realtime
		
		self:Debug("MO_MAIL_EMPTIED");
		
		-- Yell that we successfully opened/removed a mail
		self:SendMessage("MO_MAIL_EMPTIED");
	elseif (currentMailWithAttachments == 50 and tempLastAmount == 50) then
		-- Open the current mail
		self:ScheduleOpen(false);
	end
end

function MailOpener:ScheduleOpen(continued)
	if lastAmount > 0 then
		local waitTime;
		if continued then
			waitTime = self.db.profile.general.waitTime;
		else
			-- Even though this is not a continuation and should be instant, we set a .5 second timer to prevent multiple calls of the OpenNow function
			waitTime = self.db.profile.general.initialDelay;
		end
		
		-- Stop previous timer
		self:CancelTimer(self.tmrOpenNow, true);
		-- Schedule the next open
		self.tmrOpenNow = self:ScheduleTimer("OpenNow", waitTime);
	end
end

function MailOpener:OpenNow()
	self:Debug("OpenNow (" .. ((MailAddonBusy and "1") or "0") .. ")");
	if MailFrame:IsVisible() and AutoOpenMail then
		self:Debug("OpenNow");
			
		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
		--local BeanCounterActive = not InboxCloseButton:IsVisible();
		
		--if not BeanCounterActive and not MailAddonBusy then
		if not MailAddonBusy then
			-- No other addon is currently active
			
			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
			
			if QuickAuctionsAutoMail then
				-- Remember the last known quick auctions status
				lastQuickAuctionsStatus = QuickAuctionsAutoMail:GetChecked();
			end
			if self.db.profile.general.autoDisableQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and QuickAuctionsAutoMail:GetChecked() then
				-- If auto disable "QA Auto mail" is enabled and QA's auto mail is currently toggled on, turn it off
				-- We need to do this with a :click to trigger the right events
				
				self:Debug("Turning automail |cffff0000off|r.");
				
				QuickAuctionsAutoMail:Click();
			end
			
			MailAddonBusy = self:GetName();
			
			self:Debug("MO_OPEN_MAIL");
			
			-- Summon the mail opening gods
			self:SendMessage("MO_OPEN_MAIL");
		else
			-- Another addon is ACTIVE
			self:Debug("Another addon active, waiting .5 seconds... (" .. MailAddonBusy .. ")");
			
			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
			-- Try again every 0.5 seconds
			self.tmrTryAgain = self:ScheduleTimer("OpenNow", 0.5);
		end
	end
end

function MailOpener:MO_OPEN_COMPLETE()
	if MailAddonBusy == self:GetName() then
		MailAddonBusy = nil;
	end
	
	-- Try a recheck
	self:Recheck();
	
	local current, total = GetInboxNumItems();
	
	if (total - current) == 0 then
		-- There is probably no unopenable mail remaining, so play the sound (if enabled)
		
		if self.db.profile.notifications.mailboxEmptySound and (not MailOpener.db.profile.notifications.mailboxEmptySoundOnlyOnce or not mailboxEmptySoundPlayed) and (not MailOpener.db.profile.notifications.mailboxEmptySoundOnlyOncePerMailboxVisit or not mailboxEmptySoundPlayedThisVisit) then
			PlaySoundFile(self.db.profile.notifications.mailboxEmptySoundFile);
			mailboxEmptySoundPlayed = true;
			mailboxEmptySoundPlayedThisVisit = true;
		end
	end
	
	if self.QuickAuctionsEnabled then
		-- Quick Auctions enabled?
		-- Toggle automailing as per settings
		
		if self.db.profile.general.autoReenableQAAutoMail and  QuickAuctionsAutoMail and not QuickAuctionsAutoMail:GetChecked() then
			-- If auto re-enable "QA Auto mail" is enabled and QA's auto mail is currently toggled OFF, turn it on
			-- We need to do this with a :click to trigger the right events
			
			self:Debug("Turning automail |cff00ff00on|r.");
			
			QuickAuctionsAutoMail:Click();
		elseif self.db.profile.general.autoSetBackQAAutoMail and QuickAuctionsAutoMail and lastQuickAuctionsStatus ~= QuickAuctionsAutoMail:GetChecked() then
			-- If auto set back "QA Auto mail" is enabled and QA's auto mail is currently not the same as it was before starting, toggle it
			-- We need to do this with a :click to trigger the right events
			
			if lastQuickAuctionsStatus then
				self:Debug("Turning automail |cff00ff00on|r.");
			else
				self:Debug("Turning automail |cffff0000off|r.");
			end
				
			QuickAuctionsAutoMail:Click();
		end
	end
	
	if self.db.profile.general.continueOpening then
		self:ScheduleOpen(true);
	end
end

-- Run another CheckInbox
function MailOpener:Recheck()
	self:Debug("|cffffff00Recheck|r");
	
	-- Freshlist prevents this from being run too often
	-- It is set to true after a server sync
	-- and set to false 61 seconds afterwards with a recheck called instantly after it
	
	-- We're not refreshing while we're opening because it is automatically done when current batch was completely opened
	if not freshList and MailFrame:IsVisible() then
		self:Debug("|cff00ff00Recheck|r");
		
		-- If this isn't a fresh list (so messages weren't received within the last 60 seconds) and the mailbox wasn't closed
	
		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
		--local BeanCounterActive = not InboxCloseButton:IsVisible();
		
		--if not BeanCounterActive and AutoOpenMail and not MailAddonBusy then
		if AutoOpenMail and not MailAddonBusy then
			-- Query the server
			CheckInbox();
		end
		
		-- Stop previous timer
		self:CancelTimer(self.tmrRecheck, true);
		-- Keep trying until it works
		self.tmrRecheck = self:ScheduleTimer("Recheck", 2);
		
		self:Debug("tmrRecheck 2");
	end
end

-- Stop checking for new mail and unregister the events we needed
function MailOpener:Stop()
	if self.db.profile.notifications.bye then
		print("|cff15ff00Mail Opener|r: Have a nice day. :)");
	end
	
	if MailAddonBusy == self:GetName() then
		MailAddonBusy = nil;
	end
	
	-- We won't need this anymore
	self:UnregisterEvent("MAIL_CLOSED");
	self:UnregisterEvent("PLAYER_LEAVING_WORLD");
	self:UnregisterEvent("MAIL_INBOX_UPDATE");
	
	-- Messages
	self:UnregisterMessage("MO_OPEN_COMPLETE");
	
	-- Timers
	self:CancelTimer(self.tmrTryAgain, true);
	self:CancelTimer(self.tmrOpenNow, true);
	
	-- If we wait with disabling QA automail until MAIL_SHOW, QA will beat us to it and already start sending stuff
	self:ToggleQAStatus();
end

function MailOpener:Debug(t)
	if not self.debugChannel and self.debugChannel ~= false then
		-- We want to check just once, so if you add a debug channel later just do a /reload (registering an event for this is wasted resources)
		self.debugChannel = false;
		
		for i = 1, NUM_CHAT_WINDOWS do
			local name = GetChatWindowInfo(i);
			
			if name:upper() == "DEBUG" then
				self.debugChannel = _G["ChatFrame" .. i];
			end
		end
	end
	
	if self.debugChannel then
		self.debugChannel:AddMessage(t);
	end
end

-- Enable our config module if it's disabled and make a reference to it
function MailOpener:EnableConfigModule()
	if not MailOpenerConfig then
		MailOpenerConfig = self:GetModule("Config");
		MailOpenerConfig:Enable();
	end
end

-- Toggle Postal's opening modules on or off
function MailOpener:TogglePostalModule(name, status)
	if MailOpener.PostalEnabled and Postal then
		-- Postal must be enabled
		
		-- Toggle module (let Postal handle this)
		Postal.ToggleModule(nil, name, Postal:GetModule(name), status);
	end
end

-- Change Quick Auction's auto mail status based on our prefered settings
function MailOpener:ToggleQAStatus()
	self:Debug("defaultQAStatus:" .. self.db.profile.general.defaultQAStatus);
	
	if self.QuickAuctionsEnabled and self.db.profile.general.defaultQAStatus ~= "__remember" and QuickAuctionsAutoMail then
		if self.db.profile.general.defaultQAStatus == "_enabled" and not QuickAuctionsAutoMail:GetChecked() then
			self:Debug("Turning automail |cff00ff00on|r.");
			
			QuickAuctionsAutoMail:Click();
		elseif self.db.profile.general.defaultQAStatus == "disabled" and QuickAuctionsAutoMail:GetChecked() then
			self:Debug("Turning automail |cffff0000off|r.");
			
			QuickAuctionsAutoMail:Click();
		end
	end
end

function MailOpener:FormatMoney(copper)
	local gold = floor( copper / 10000 );
	local silver = floor( ( copper - ( gold * 10000 ) ) / 100 );
	local copper = mod(copper, 100);
	
	if gold > 0 then
		return format(GOLD_AMOUNT_TEXTURE .. " " .. SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, gold, 0, 0, silver, 0, 0, copper, 0, 0);
	elseif silver > 0 then
		return format(SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, silver, 0, 0, copper, 0, 0);
	else
		return format(COPPER_AMOUNT_TEXTURE, copper, 0, 0);
	end
end

-- General copy window for multiple things (clickable URLs, the time remaining, and such)
StaticPopupDialogs["MailOpenerCopyWindow"] = {
	text = "Please CTRL-C to copy.",
	button2 = CLOSE,
	hasEditBox = 1,
	hasWideEditBox = 1,
	OnShow = function()
		local editBox = _G[this:GetName().."WideEditBox"];
		if editBox and MailOpener.currentPopupContents then
			editBox:SetText(MailOpener.currentPopupContents);
			editBox:SetFocus();
			editBox:HighlightText(0);
		end
		
		-- Position the close button in the middle
		local button = _G[this:GetName().."Button2"];
		if button then
			-- Remove previous know position
			button:ClearAllPoints();
			button:SetWidth(200);
			-- Reposition in the center
			button:SetPoint("CENTER", editBox, "CENTER", 0, -30);
		end
	end,
	EditBoxOnEscapePressed = function()
		this:GetParent():Hide();
	end,
	timeout = 0,
	whileDead = 1,
	hideOnEscape = 1,
	maxLetters = 1024,
};

--BETA: The below either has to be removed or changed when releasing

--[[
BETA/ALPHA request box
function MailOpener:ShowBetaPopup()
	function TableDump(key, val, jumps)
		local cache = "";
		
		if not jumps then
			jumps = 0;
		end
		
		local spacer = "";
		if jumps > 0 then
			for i = 1, jumps do
				spacer = spacer .. "    ";
			end
		end
		
		if type(val) == "table" then
			cache = cache .. spacer .. key .. " = {\n";
			foreach(val, function(k, v)
				cache = cache .. TableDump(k, v, (jumps + 1));
			end);
			cache = cache .. spacer .. "},\n";
		else
			cache = cache .. spacer .. key .. " = " .. tostring(val) .. ",\n";
		end
		
		return cache;
	end
	
	local cache = "";
	foreach(MailOpener.db.profile, function(k, v)
		cache = cache .. TableDump(k, v, 0);
	end);
	
	local AceGUI = LibStub("AceGUI-3.0");
	local frame = AceGUI:Create("Frame");
	frame:SetTitle("Mail Opener ALPHA");
	frame:SetWidth(575);
	frame:SetHeight(375);
	
	-- Add a normal description label
	local desc = AceGUI:Create("Label");
	desc:SetText("|cff00ff00After you have been using Mail Opener for a while and configured it just as you want it to be, please report your favorite settings by copying the text below at either of the below links. Thanks in advance!|r\n\n");
	desc:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc:SetFullWidth(true);
	frame:AddChild(desc);
	
	-- Add a MultiLineEditBox
	local settingsMLEEB = AceGUI:Create("MultiLineEditBox");
	settingsMLEEB:SetText(cache);
	settingsMLEEB:SetLabel("Hit CTRL-A to select all and CTRL-C to copy the text. You can then use CTRL-V to paste.");
	settingsMLEEB:SetFullWidth(true);
	settingsMLEEB:SetNumLines(8);
	settingsMLEEB:DisableButton(true);
	settingsMLEEB:SetCallback("OnTextChanged", function()
		settingsMLEEB:SetText(cache);
	end);
	frame:AddChild(settingsMLEEB);
	
	-- Empty line between the two links
	local label = AceGUI:Create("Label");
	label:SetText("Please post the above text at either of these two links:");
	label:SetFullWidth(true);
	frame:AddChild(label);
	
	local desc1 = AceGUI:Create("InteractiveLabel");
	desc1:SetText("|cff00bbbb[http://wow.curseforge.com/addons/mailopener/create-ticket/]|r");
	desc1:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc1:SetFullWidth(true);
	desc1:SetCallback("OnClick", function()
		MailOpener.currentPopupContents = "http://wow.curseforge.com/addons/mailopener/create-ticket/";
		
		StaticPopup_Show("MailOpenerCopyWindow");
	end);
	desc1:SetCallback("OnEnter", function()
		frame:SetStatusText("Click to copy this URL.");
	end);
	desc1:SetCallback("OnLeave", function()
		frame:SetStatusText("");
	end);
	frame:AddChild(desc1);
	
	-- Empty line between the two links
	local spacer = AceGUI:Create("Label");
	spacer:SetText(" ");
	frame:AddChild(spacer);
	
	local desc2 = AceGUI:Create("InteractiveLabel");
	desc2:SetText("|cff00bbbb[http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403]|r");
	desc2:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc2:SetFullWidth(true);
	desc2:SetCallback("OnClick", function()
		MailOpener.currentPopupContents = "http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403";
		
		StaticPopup_Show("MailOpenerCopyWindow");
	end);
	desc2:SetCallback("OnEnter", function()
		frame:SetStatusText("Click to copy this URL.");
	end);
	desc2:SetCallback("OnLeave", function()
		frame:SetStatusText("");
	end);
	frame:AddChild(desc2);
	
	-- Empty line between the two links
	local label = AceGUI:Create("Label");
	label:SetText("\n\nps. You can always view this window again at a later time by clicking the \"Config\" button in the mail frame.\nps2. The information above is completely Mail Opener related. It will be used to determine the best default settings.");
	label:SetFullWidth(true);
	frame:AddChild(label);
end
]]