------------------------------------------------
--                 DagAssist                  --
--             Dagos of Cenarius              --
------------------------------------------------

DagAssist = {};

local DA_MENU_WIDTH = 220;
local DA_MENUITEM_INDENT = 15;
local DA_MENUITEM_HEIGHT = 17;
local DA_TOOLTIP_TEXT = "|cff00e4ffDagAssist";

local DA_Defaults = {	
		Minimap = {
			Y = 631,
			X = 964,
			}
		};	

local hdr;
local btnMinimap;
local DA_Menu;
local hoverButton;
local bDragging = false;
local bTrackBag = false;
local bLoaded = false;
local bVariablesLoaded = false;

--Strip the line break from the global spell reagent text.
DAGASSIST_SPELL_REAGENTS = string.sub(SPELL_REAGENTS, 1, string.len(SPELL_REAGENTS) - 1);

------------------------------------------------------
--Debugging function
--Prints message to the default chat window
------------------------------------------------------
function DagDebug(temp)
	DEFAULT_CHAT_FRAME:AddMessage(temp);
end

------------------------------------------------------
--Table of menu items  
------------------------------------------------------
local MenuList = DagAssist_MenuList;

------------------------------------------------------
--Addon event handler.  
--Calls SetMenuItemVisibility
------------------------------------------------------
function DagAssist_OnEvent()
	if (event == "PLAYER_LOGIN") then
		if (bVariablesLoaded) then
			BuildMenu();
		end
	elseif (event == "VARIABLES_LOADED") then
		bVariablesLoaded = true;
		if (not DA_Vars) then
			DA_Vars = DA_Defaults;
		end
	end
	
	if event == "PLAYER_ENTERING_WORLD" then bTrackBag = true end;
	if event == "PLAYER_LEAVING_WORLD"  then bTrackBag = false end;
	if not bTrackBag then
		return
	end;
	
	if (((event == "PLAYER_REGEN_DISABLED") or 
         (event == "PLAYER_REGEN_ENABLED") or 
		 (event == "LEARNED_SPELL_IN_TAB") or
		 ((event == "UNIT_MANA") and (arg1 == "player")) or
		 (event == "BAG_UPDATE")) and bLoaded) then
		SetMenuItemVisibility();
	end
end

------------------------------------------------------
--Addon load event handler.  
--Registers events
--Creates Minimap button
--Creates menu items and menu frames
------------------------------------------------------
function DagAssist_OnLoad()		
	this:RegisterEvent("BAG_UPDATE");
	this:RegisterEvent("PLAYER_LOGIN");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("PLAYER_LEAVING_WORLD");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("LEARNED_SPELL_IN_TAB");
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UNIT_MANA");
end

function BuildMenu()
	--Set up hook for tooltip handling
	hooksecurefunc("SecureStateAnchor_RunChild", DisplayTooltip);
	
	DagAssist.Header = CreateFrame("Frame", "DA_StateHeader", UIParent, "SecureStateHeaderTemplate");
	hdr = DagAssist.Header;
	hdr:SetPoint("CENTER") hdr:SetWidth(2) hdr:SetHeight(2)
	hdr:SetAttribute("statemap-anchor-enter", "1");
	hdr:SetAttribute("statemap-anchor-close", "0");
	hdr:SetAttribute("statemap-anchor-leave", ";");
	hdr:SetAttribute("delaystatemap-anchor-leave", "1:0");
	hdr:SetAttribute("delaytimemap-anchor-leave",  "1:1");
	hdr:SetAttribute("delayhovermap-anchor-leave", "1:true");
	
	function hdr:StateChanged(newstate)
		--DagDebug("hdr: ".. newstate);
	end
	
	--Set up the minimap button
	DagAssist.MinimapButton = CreateFrame("Button", "DA_Minimap", Minimap, "SecureAnchorButtonTemplate, SecureAnchorEnterTemplate");
	btnMinimap = DagAssist.MinimapButton;
	btnMinimap:SetMovable(true);
	btnMinimap:RegisterForDrag("LeftButton");
	
	if (DA_Vars.Minimap.X and DA_Vars.Minimap.Y) then
		--Restore last position
		local s = btnMinimap:GetEffectiveScale();

		btnMinimap:ClearAllPoints()
		btnMinimap:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", DA_Vars.Minimap.X / s, DA_Vars.Minimap.Y /s);
	else
		btnMinimap:SetPoint("CENTER", Minimap, "BOTTOMLEFT", 15, 15);
	end
	
	btnMinimap:SetFrameStrata("LOW");
	btnMinimap:SetWidth(32);
	btnMinimap:SetHeight(32);
	btnMinimap:SetClampedToScreen(true);
	
	btnMinimap:SetNormalTexture("Interface\\AddOns\\DagAssist\\Images\\MinmapIcon");
	btnMinimap:SetPushedTexture("Interface\\AddOns\\DagAssist\\Images\\MinmapIconDown");
	
	local texture = btnMinimap:CreateTexture(nil, "ARTWORK");
	texture:SetTexture("Interface\\AddOns\\DagAssist\\Images\\MinmapIconHighlight");
	texture:SetBlendMode("BLEND");
	texture:SetAllPoints(btnMinimap);
	btnMinimap:SetHighlightTexture(texture);
	
	btnMinimap:SetScript("OnDragStart", 
		function()
			btnMinimap:StartMoving();
			bDragging = true;
			
			if (InCombatLockdown() ~= 1) then
				DA_Menu:Hide();
				btnMinimap.updateTooltip = nil;
				GameTooltip:Hide();
			end
		end
	)
	
	btnMinimap:SetScript("OnDragStop",
		function()
			btnMinimap:StopMovingOrSizing();
			
			if (bDragging) then
				bDragging = false;
				local s = btnMinimap:GetEffectiveScale();
				DA_Vars.Minimap.X = btnMinimap:GetLeft() * s;
				DA_Vars.Minimap.Y = btnMinimap:GetTop() * s;
			end
		end
	)
	
	btnMinimap:RegisterForClicks("AnyDown");
	btnMinimap.NeedsTooltip = true;
	btnMinimap.TooltipText = DA_TOOLTIP_TEXT;
	
	btnMinimap:SetAttribute("anchorchild", hdr);
	btnMinimap:SetAttribute("*childraise-OnLeave", true)
	btnMinimap:SetAttribute("*childstate1", "enter");
	btnMinimap:SetAttribute("*childstate-OnLeave", "leave");
	
	btnMinimap:Show();
	
	--Set up the menu
	DagAssist.DA_Menu = CreateFrame("Frame", "DA_Menu", UIParent, "SecureStateHeaderTemplate");
	DA_Menu = DagAssist.DA_Menu;
	DA_Menu:SetWidth(DA_MENU_WIDTH);
	DA_Menu:SetPoint("TOPLEFT", btnMinimap, "BOTTOMLEFT", 0, 0);
	DA_Menu:SetToplevel(true);
	DA_Menu:SetScript("OnUpdate", DA_Menu_OnUpdate);
	DA_Menu:SetScript("OnShow", SetMenuItemVisibility);
	
	DA_Menu:SetBackdrop( { 
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", 
		edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", 
		tile = true, tileSize = 16, edgeSize = 16, 
		insets = { left = 5, right = 5, top = 5, bottom = 5 }
	});
	
	DA_Menu:SetClampedToScreen(true);
	DA_Menu:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
	DA_Menu:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b, 1);
	DA_Menu:SetAttribute("hidestates", 0);	
	hdr:SetAttribute("addchild", DA_Menu)	
	DA_Menu:SetFrameStrata("HIGH");

	--Create an invisible button that will allow the frame to continue to display
	--so long as the mouse is over it
	--hoverButton = CreateFrame("Button", nil, DA_Menu);
	hoverButton = CreateFrame("Button", "DA_HoverButton", DA_Menu, "SecureAnchorButtonTemplate");
	hoverButton:SetPoint("CENTER");
	hoverButton:RegisterForClicks("AnyDown");
	hoverButton:SetAttribute("anchorchild", hdr);
	hoverButton:SetAttribute("*childstate1", "close");
	
	for index = 1, table.getn(MenuList) do 
		local value = MenuList[index];
			
		local btnMenuItem;
		if (value.type == "header") or (value.type == "spacer") then
			btnMenuItem = CreateFrame("Button", "DA_MenuButton"..index, DA_Menu, "DA_MenuLabelTemplate, SecureAnchorUpDownTemplate");
			btnMenuItem:SetWidth(DA_Menu:GetWidth() - (DA_MENUITEM_INDENT * 2));
			
		elseif value.type == "spell" then
			btnMenuItem = CreateFrame("Button", "DA_MenuButton"..index, DA_Menu, "DA_MenuSpellButtonTemplate, SecureActionButtonTemplate, SecureAnchorUpDownTemplate");
			btnMenuItem:SetWidth(DA_Menu:GetWidth() - (DA_MENUITEM_INDENT * 3));
			btnMenuItem:SetAttribute("type","spell");
			btnMenuItem:SetAttribute("*unit*","player");
			btnMenuItem:SetAttribute("spell1",value.spellname);

		elseif value.type == "buff" then
			btnMenuItem = CreateFrame("Button", "DA_MenuButton"..index, DA_Menu, "DA_MenuSpellButtonTemplate, SecureActionButtonTemplate, SecureAnchorUpDownTemplate");
			btnMenuItem:SetWidth(DA_Menu:GetWidth() - (DA_MENUITEM_INDENT * 3));
			btnMenuItem:SetAttribute("type","spell");
			btnMenuItem:SetAttribute("*unit*","target");
			btnMenuItem:SetAttribute("spell1",value.spellname);

		elseif value.type == "item" then
			btnMenuItem = CreateFrame("Button", "DA_MenuButton"..index, DA_Menu, "DA_MenuSpellButtonTemplate, SecureActionButtonTemplate, SecureAnchorUpDownTemplate");
			btnMenuItem:SetWidth(DA_Menu:GetWidth() - (DA_MENUITEM_INDENT * 3));
			btnMenuItem:SetAttribute("type","item");
			btnMenuItem:SetAttribute("*unit*","player");
			btnMenuItem:SetAttribute("item1",value.item);
		end		
		value.button = btnMenuItem;
		value.buttonIcon = getglobal("DA_MenuButton"..index.."Icon");
		
		SetButtonIcon(value);
		btnMenuItem:SetFrameLevel(hoverButton:GetFrameLevel() + 1);
		btnMenuItem:SetHeight(DA_MENUITEM_HEIGHT);
		
		if (value.keepopen ~= 1) then
			btnMenuItem:RegisterForClicks("AnyDown");
			btnMenuItem:SetAttribute("anchorchild", hdr);
			btnMenuItem:SetAttribute("*onmousedownbutton*", "donothing");
			btnMenuItem:SetAttribute("*childstate1", "close");
		end
		
		if ((value.reagent) and (value.reagent ~= "")) then
			btnMenuItem:SetText(value.text .. " (" .. DAGASSIST_SPELL_REAGENTS .. GetItemCount(value.reagent, false) .. ")");
		else
			btnMenuItem:SetText(value.text);
		end		
	end
	
	--Add the hide button
	local btnMenuItem = CreateFrame("Button", "DA_MenuCancelButton", DA_Menu, "SecureAnchorButtonTemplate, DA_MenuSpellButtonTemplate");
	btnMenuItem:SetFrameLevel(hoverButton:GetFrameLevel() + 1);
	btnMenuItem:SetPushedTexture(nil);
	btnMenuItem:SetTextColor(1, 1, 1, 1);
	btnMenuItem:SetHeight(DA_MENUITEM_HEIGHT)	
	btnMenuItem:SetText(CANCEL);
	btnMenuItem:RegisterForClicks("AnyDown");
	btnMenuItem:SetAttribute("anchorchild", hdr);
	btnMenuItem:SetAttribute("*childstate1", "close");
	getglobal("DA_MenuCancelButtonText"):SetPoint("TOPLEFT");
	btnMenuItem:SetWidth(DA_Menu:GetWidth() - (DA_MENUITEM_INDENT * 2));
	
	local value = {};
	value.text = CANCEL;
	value.type = "special";
	value.button = btnMenuItem;
	table.insert(MenuList,value);
	
	bLoaded = true;
		
	if (Titan_DagAssist) then
		Titan_DagAssist:Load();
	end

	SetMenuItemVisibility();
end

function SetButtonIcon(tableEntry)
	local itemTexture;
	if ((tableEntry.type == "spell") or (tableEntry.type == "buff")) then
		itemTexture = GetSpellTexture(tableEntry.spellname);
		
	elseif tableEntry.type == "item" then
		--Get the item texture
		_, _, _, _, _, _, _, _, _, itemTexture = GetItemInfo(tableEntry.item);
	end		
	
	if (itemTexture) then
		tableEntry.buttonIcon:SetTexture(itemTexture);
		tableEntry.IconSet = true;
	end
end

function DA_Menu_OnUpdate()
	if (this.TimeSinceLastUpdate) then
		this.TimeSinceLastUpdate = this.TimeSinceLastUpdate + arg1; 	

		if (this.TimeSinceLastUpdate >= 1) then
			this.TimeSinceLastUpdate = 0;
			
			SetMenuItemVisibility();
		end
	else
		this.TimeSinceLastUpdate = 0;
	end
end

------------------------------------------------------
--Hide or show menu items based on availability
--Disable or enable spells and items
--Sets reagent counts
--Hides headers if there are no visible items under them
------------------------------------------------------
function SetMenuItemVisibility()
	if (not bLoaded) then
		return;
	end
	
	--Don't update the menu item visibility if the player is in combat.
	if (InCombatLockdown()) then
		return;
	end
	
	local previousItem = nil;
	for index = 1, table.getn(MenuList) do 
		local value = MenuList[index];
		
		if ((value.button) and (value.reagent) and (value.reagent ~= "")) then
			value.button:SetText(value.text .. " (" .. DAGASSIST_SPELL_REAGENTS .. GetItemCount(value.reagent, false) .. ")");
		end

		if ((value.type) and (value.type ~= "") and (value.button)) then
			if (value.type == "header") then
				value.visible = true;
				
			elseif ((value.type == "spell") or (value.type == "buff")) then
				if ((value.spellname) and (value.spellname ~= "")) then
					if (PlayerKnowsSpell(value.spellname)) then
						value.visible = true;
						if (not value.IconSet) then
							SetButtonIcon(value);
						end
						
						if (IsUsableSpell(value.spellname)) then
							value.button:Enable();
						else
							value.button:Disable();
						end
					else
						value.visible = false;
					end
				else
					value.visible = false;
				end
				
			elseif (value.type == "item") then
				value.visible = true;
				if (not value.IconSet) then
					SetButtonIcon(value);
				end
				if (GetItemCount(value.item, false)) > 0 then
					
					if (value.hearthstone) then
						--Set the text and cooldown
						value.text = GetBindLocation();
					end
					
					local startTime, duration, cooldownEnabled;	
					startTime, duration, cooldownEnabled = GetItemCooldown(value.item);
					
					local secondsRemaining = math.ceil(duration - (GetTime() - startTime));
					if ((cooldownEnabled == 1) and (secondsRemaining > 0)) then
						if (secondsRemaining > 60) then
							secondsRemaining = math.ceil(secondsRemaining / 60);
							secondsRemaining = secondsRemaining.." "..MINUTES_ABBR;
						else
							secondsRemaining = secondsRemaining.." "..SECONDS_ABBR;
						end
						value.button:Disable();
						value.button:SetText(value.text.." ("..secondsRemaining..")");
					else
						value.button:Enable();
						value.button:SetText(value.text);
					end
				else
					value.button:Disable();
				end
				
			elseif (value.type == "special") then
				value.visible = true;
				
			elseif (value.type == "spacer") then
				value.visible = true;
				
			end
			
			if (value.visible) then
				if previousItem then
					if ((value.type == "header") and (previousItem.type == "header")) then
						if previousItem.button then
							previousItem.button:Hide();
						end
						previousItem = previousItem.previous;
					end
				end
				
				if previousItem then
					value.count = previousItem.count + 1;
					value.previous = previousItem;
				else
					value.count = 1;
				end
				value.button:SetPoint("TOPRIGHT", DA_Menu, "TOPRIGHT", -DA_MENUITEM_INDENT, -DA_MENUITEM_INDENT - (DA_MENUITEM_HEIGHT * (value.count - 1)));
				
				previousItem = value;
				
				value.button:Show();
			else
				value.button:Hide();
			end
		end
		
	end
	
	--Set menu height
	if previousItem then
		DA_Menu:SetHeight((previousItem.count * DA_MENUITEM_HEIGHT) + (DA_MENUITEM_INDENT * 2));
	else
		DA_Menu:SetHeight(DA_MENUITEM_INDENT * 2);
	end
	hoverButton:SetHeight(DA_Menu:GetHeight());
	hoverButton:SetWidth(DA_Menu:GetWidth());
end

------------------------------------------------------
--Requires two properties to be set on the button
--NeedsTooltip (boolean): Display a tooltip
--TooltipText  (string):  Text of the tooltip
------------------------------------------------------
function DisplayTooltip(self, button, remapButton)
	-- return if we didn't register a 'need'.
	if this.NeedsTooltip and this.TooltipText and (not bDragging) then
		-- otherwise handle enter/leave
		if button == "OnEnter" then
			GameTooltip:SetOwner(btnMinimap, "ANCHOR_NONE");
			GameTooltip:SetPoint("TOPRIGHT", btnMinimap, "BOTTOMLEFT", -3, -3);
			GameTooltip.default = 1;
			GameTooltip:SetText(this.TooltipText);
		elseif (button == "OnLeave") or (remapButton == "onclickbutton") then
			this.updateTooltip = nil;
			GameTooltip:Hide();
		end
	end
end

------------------------------------------------------
--Given a spell name, will return whether or not the
--player has learned the spell (ie. is it in their
--spell book).
------------------------------------------------------
function PlayerKnowsSpell(spell)
	local i = 1;
	while true do
		local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL);
		if not spellName then
			do break end;
		end

		if (spellName == spell) then
			return true;
		end

		i = i + 1;
	end
	
	return false;
end

------------------------------------------------------
--Given a spell name, will display the appropriate
--tooltip.
------------------------------------------------------
function DisplaySpellToolTip()
	local i, s;
	local spellName = this:GetAttribute("spell1");
	
	if not spellName then
		return;
	end
	
	for i = 1, MAX_SKILLLINE_TABS do
		local name, texture, offset, numSpells = GetSpellTabInfo(i);
	   
		if not name then
			break;
		end
	   
	   for s = offset + 1, offset + numSpells do
			local spell, rank = GetSpellName(s, BOOKTYPE_SPELL);
	      
			if spell == spellName then
				GameTooltip:SetOwner(UIParent, "ANCHOR_BOTTOMRIGHT");
				if ( GameTooltip:SetSpell(s, i) ) then
					this.updateTooltip = TOOLTIP_UPDATE_TIME;
				else
					this.updateTooltip = nil;
				end
				return;
			end
	   end
	end
end


