--[[

BCUI Tracking Menu
==================

Description:
------------
Replaces the default active tracking ability icon in the minimap cluster with an icon that 
supports a mouse-over popup menu that lists all tracking abilities available to the character.
Right-clicking on the icon will still cancel the active tracking ability.

Credits:
--------
- Thanks to Malecandra for helping come up with this idea in the first place.

- Big thanks to Jet for localizing all of the strings to French and doing most (if not all)
  of the code changes to hook that up.

- The bcTM_pairsByKeys() function was taken from the LUA reference available at
  http://www.lua.org/pil/index.html.
  
- Thanks to Markus for localizing the strings to German and clueing me in to the escape codes
  for the different characters.

Revision History:
-----------------
01/29/2005 v1.14
- Added German localization strings.

- Tweaked the French localization strings.

- Added version numbers.

- Added the /bctm_report command to list out the current values being searched for in the spellbook.
  Mainly a debugging tool.

01/23/2005 v1.10
- I think I've fixed a display problem that I introduced with the "don't show the icon when
  you don't have any tracking abilities" code.  Please let me know if you run into any other
  oddities while using the mod.

01/15/2005 v1.09
- Displayed strings are now localized to English and French.  If anyone out there wishes to
  translate them into another language, just send me the text and I'll get it hooked up.

- The list of abilities on the menu is now sorted alphabetically.  If other sorting/grouping
  options are desired, let me know and I'll see what I can do.

- The icon in the minimap cluster will no longer show if no tracking abilities are available to
  the current character.
  
- Fixed a nil reference if the MiniMapTrackingFrame was hidden for some reason, as well as
  a few other minor code changes and optimizations.
  
- Added Sense Demons to the list of abilities to check for.
  
01/07/2004 v1.04
- Fix: The tracking menu should no longer crash the game client when right-clicked on when
  no tracking abilities were active.  Evidently, calling CancelTrackingBuff() with no active
  tracking ability causes problems.  Thanks go out to Brent and Amberly for helping track
  this down.

- Added more verbose comments throughout the code.

12/??/2004 v1.02
Minor redesign to better accomodate other AddOns.

- Instead of adding an additional icon to the minimap cluster, changed it to replace the 
  existing tracking icon.

- Made the icon respond to mouse-over events instead of right-click events to display
  the menu.

12/??/2004 v1.0
Initial release.

]]

-- Number of buttons for the menu defined in the XML file.
BCTM_NUM_BUTTONS = 12;

-- List of tracking abilities to look for.
bcTM_TrackingAbilities = {
	[BCTM_TEXT_FIND_HERBS] = 0,
	[BCTM_TEXT_FIND_MINERALS] = 0,
	[BCTM_TEXT_FIND_TREASURE] = 0,
	[BCTM_TEXT_TRACK_BEASTS] = 0,
	[BCTM_TEXT_TRACK_HUMANOIDS] = 0,
	[BCTM_TEXT_TRACK_HIDDEN] = 0,
	[BCTM_TEXT_TRACK_ELEMENTALS] = 0,
	[BCTM_TEXT_TRACK_UNDEAD] = 0,
	[BCTM_TEXT_TRACK_DEMONS] = 0,
	[BCTM_TEXT_TRACK_GIANTS] = 0,
	[BCTM_TEXT_TRACK_DRAGONKIN] = 0,
	[BCTM_TEXT_SENSE_UNDEAD] = 0,
	[BCTM_TEXT_SENSE_DEMONS] = 0,
}

function bcWrite(msg)
	if (msg and DEFAULT_CHAT_FRAME) then
		DEFAULT_CHAT_FRAME:AddMessage(msg);
	end
end

function bcTM_Report()
	bcWrite(BCTM_TEXT_MENU_TITLE);
	bcWrite(BCTM_TEXT_TOOLTIP);
	bcWrite(BCTM_TEXT_FIND_HERBS);
	bcWrite(BCTM_TEXT_FIND_MINERALS);
	bcWrite(BCTM_TEXT_FIND_TREASURE);
	bcWrite(BCTM_TEXT_TRACK_BEASTS);
	bcWrite(BCTM_TEXT_TRACK_HUMANOIDS);
	bcWrite(BCTM_TEXT_TRACK_HIDDEN);
	bcWrite(BCTM_TEXT_TRACK_ELEMENTALS);
	bcWrite(BCTM_TEXT_TRACK_UNDEAD);
	bcWrite(BCTM_TEXT_TRACK_DEMONS);
	bcWrite(BCTM_TEXT_TRACK_GIANTS);
	bcWrite(BCTM_TEXT_TRACK_DRAGONKIN);
	bcWrite(BCTM_TEXT_SENSE_UNDEAD);
	bcWrite(BCTM_TEXT_SENSE_DEMONS);
end

function bcTM_OnLoad()
	-- Register for the neccessary events.
	this:RegisterEvent("SPELLS_CHANGED");
	this:RegisterEvent("LEARNED_SPELL_IN_TAB");
	this:RegisterEvent("PLAYER_AURAS_CHANGED");
	this:RegisterEvent("VARIABLES_LOADED");
	
	-- Create a slash command to list out the values being searched for in the spellbook.
	SlashCmdList["BCTM_REPORT"] = bcTM_Report;
	SLASH_BCTM_REPORT1 = "/bctm_report";
	
	-- Let the user know the mod loaded.
	if ( DEFAULT_CHAT_FRAME ) then 
		bcWrite("BC Tracking Menu loaded");
	end
end

function bcTM_OnEvent()
-- Debug code:  Used to tell when this function is called.
--	bcWrite("bcTM_OnEvent(): called");

	if ( event == "PLAYER_AURAS_CHANGED" ) then
		-- When the user changes their active tracking ability, do the following.
		
		-- Hide the default tracking icon.
		if (MiniMapTrackingFrame) then
			MiniMapTrackingFrame:Hide();
		end
		
		-- Get the icon for the currently active tracking ability.
		local icon = GetTrackingTexture();
		if ( icon ) then
			-- Set our icon to match the active ability.
			bcTM_IconTexture:SetTexture(icon);
		else
			-- No ability active... Set our icon to something else.
			--bcTM_IconTexture:SetTexture("Interface\\Icons\\INV_Misc_Map_01");
		end
		
		return;
	elseif (event == "VARIABLES_LOADED") then
		bcTM_InitializeMenu();
	else
		-- When the player learns a new spell, re-initialize the menu's contents.
		bcTM_InitializeMenu();
	end
end

function bcTM_InitializeMenu()
-- Debug code:  Used to tell when this function is called.
--	bcWrite("bcTM_InitializeMenu(): called");
	
	-- Calculate the total number of spells known by scanning the spellbook.
	local numTotalSpells = 0;
	for i=1, MAX_SKILLLINE_TABS do
		local name, texture, offset, numSpells = GetSpellTabInfo(i);
		if (name) then
			numTotalSpells = numTotalSpells + numSpells
		end
	end

	local haveAbilities = false;
	
	-- Find the tracking abilities available.
	for i=1, numTotalSpells do
		local spellName, subSpellName = GetSpellName(i, SpellBookFrame.bookType);
		if (spellName) then
			if (bcTM_TrackingAbilities[spellName]) then
				haveAbilities = true;
				bcTM_TrackingAbilities[spellName] = i
			end
		end
	end
	
	if (haveAbilities) then
		bcTM_IconFrame:Show();
	end
end

function bcTM_ButtonClick()
-- Debug code:  Used to tell when this function is called.
--	bcWrite("bcTM_ButtonClick(): called");
	
	-- Cast the selected spell.
	CastSpell(this.SpellID, "spell");
end

function bcTM_Show()
-- Debug code:  Used to tell when this function is called.
--	bcWrite("bcTM_Show(): called");

	-- Set the anchor and text for the tooltip.
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT");
	local icon = GetTrackingTexture();
	if ( icon ) then
		GameTooltip:SetTrackingSpell();
	else
		GameTooltip:SetText("Set Tracking");
	end

	-- Set the text for the buttons while keeping track of how many
	-- buttons we actually need.
	local count = 0;
	for spell, id in bcTM_pairsByKeys(bcTM_TrackingAbilities) do
		if (id > 0) then
			count = count + 1;
			local button = getglobal("bcTM_PopupButton"..count);
			button:SetText(spell);
			button.SpellID = id;
			button:Show();
		end
	end
	
	-- Set the width for the menu.
	local width = bcTM_PopupTitle:GetWidth();
	for i = 1, count, 1 do
		local button = getglobal("bcTM_PopupButton"..i);
		local w = button:GetTextWidth();
		if (w > width) then
			width = w;
		end
	end
	bcTM_Popup:SetWidth(width + 2 * UNITPOPUP_BORDER_WIDTH);

	-- By default, the width of the button is set to the width of the text
	-- on the button.  Set the width of each button to the width of the
	-- menu so that you can still click on it without being directly
	-- over the text.
	for i = 1, count, 1 do
		local button = getglobal("bcTM_PopupButton"..i);
		button:SetWidth(width);
	end

	-- Hide the buttons we don't need.
	for i = count + 1, BCTM_NUM_BUTTONS, 1 do
		local button = getglobal("bcTM_PopupButton"..i);
		button:Hide();
	end
	
	-- Set the height for the menu.
	bcTM_Popup:SetHeight(UNITPOPUP_TITLE_HEIGHT + (count * UNITPOPUP_BUTTON_HEIGHT) + (3 * UNITPOPUP_BORDER_HEIGHT));

	-- Show the menu.
	bcTM_Popup:Show();
end

function bcTM_OnUpdate(elapsed)
-- Debug code:  Used to tell when this function is called.
--	bcWrite("bcTM_OnUpdate(): called");

	-- Check to see if the mouse is still over the menu or the icon.
	if (not MouseIsOver(bcTM_Popup) and not MouseIsOver(bcTM_IconFrame)) then
		-- If not, hide the menu.
		bcTM_Popup:Hide();
	end
end

function bcTM_pairsByKeys(t, f)
	local a = {}
	for n in pairs(t) do table.insert(a, n) end
	table.sort(a, f)
	local i = 0      -- iterator variable
	local iter = function ()   -- iterator function
		i = i + 1
		if a[i] == nil then return nil
			else return a[i], t[a[i]]
		end
	end
	return iter
end