--[[
Name: LibMMButton-1.1
Revision: $Revision: 72150 $
Author(s): Pernicius (pernicius@web.de)
EditBy: InTheBlue (intheblue@inven.co.kr)
Description: A library to handle a minimap button.
Dependencies: LibStub
]]--


----------------------------------------
-- Library setup
----------------------------------------


-- #AUTODOC_NAMESPACE LibMMButton

local MAJOR, MINOR = "LibMMButton-1.1", 4

local LibMMButton, oldminor = LibStub:NewLibrary(MAJOR, MINOR)

if not LibMMButton then return end

LibMMButton.embeds = LibMMButton.embeds or {}


----------------------------------------
-- Library API
----------------------------------------


--------------------------------------------------------------------------------
-- Notes:
-- * Creates a minimap button.
--
-- Example:
-- MyAddon:CreateMMButton()
--------------------------------------------------------------------------------
function LibMMButton:CreateMMButton()
	-- init AceDB values
	if self.db then
		if(not self.db.profile.LibMMButton) then
			self.db.profile.LibMMButton = {
				dragable = true,
				angle = 0,
				radius = 80,
				rounding = 10,
			}
		end
	else

	end

	local name = tostring(self).."LibMMButtonFrame"
	local f = CreateFrame("Button", name, Minimap)
	f:SetFrameStrata("LOW")
	f:SetWidth(33)
	f:SetHeight(33)
	f:SetPoint("CENTER")
	f:EnableMouse(true)
	f:RegisterForClicks("AnyUp")
	f:RegisterForDrag("LeftButton", "RightButton")
	f:SetNormalTexture("Interface\\Icons\\INV_Misc_QuestionMark")
	f:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
	local s = f:GetNormalTexture()
	s:SetWidth(18)
	s:SetHeight(18)
	s:ClearAllPoints()
	s:SetPoint("CENTER", f, "CENTER")
	f.dragme = false
	f:Show()
	self.LibMMButtonFrame = f
	self.LibMMButtonIconTexture = s
	local t = f:CreateTexture(name.."Border", "OVERLAY")
	t:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
	t:SetWidth(52)
	t:SetHeight(52)
	t:SetPoint("TOPLEFT", f, "TOPLEFT")

	f:SetScript("OnDragStart", function()
		if self.db.profile.LibMMButton.dragable then
			this.dragme = true
			this:LockHighlight()
		end
	end)
	f:SetScript("OnDragStop", function()
		this.dragme = false
		this:UnlockHighlight()
	end)
	f:SetScript("OnUpdate", function()
		if this.dragme then
			self:LibMMButtonBeingDragged()
		end
	end)
	f:SetScript("OnEnter", function()
		self:LibMMButtonOnEnter()
	end)
	f:SetScript("OnLeave", function()
		GameTooltip:Hide()
	end)
	f:SetScript("OnClick", function(frame, button)
		self:OnMMButtonClick(button)
	end)
	self:LibMMButtonUpdatePosition()
end


--------------------------------------------
-- Arguments:
-- string - Path to the texture
--
-- Notes:
-- * Sets the button texture
-- * Default is "Interface\Icons\INV_Misc_QuestionMark"
--
-- Example:
-- MyAddon:SetMMButtonIcon("path\\to\\my\\texture")
--------------------------------------------
function LibMMButton:SetMMButtonIcon(path)
	if(not type(path)=="string") then
		error('Usage: SetMMButtonIcon("path")', 2)
	end
	self.LibMMButtonIconTexture:SetTexture(path)
	if path:sub(1, 16) == "Interface\\Icons\\" then
		self.LibMMButtonIconTexture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	else
		self.LibMMButtonIconTexture:SetTexCoord(0, 1, 0, 1)
	end
end


--------------------------------------------
-- Arguments:
-- integer - Angle of the button at the minimap.
-- [optional] integer - Radius of the button relative to the minimap center.
-- [optional] integer - Rounding of the minimap edge if the shape of the minimap is not round.
--
-- Notes:
-- * Sets the position of the minimap button.
-- * Default angle is 0
-- * Default radius is 80
-- * Default rounding is 10
--
-- Example:
-- MyAddon:SetMMButtonPosition(180, 80, 10)
--------------------------------------------
function LibMMButton:SetMMButtonPosition(angle, radius, rounding)
	if(not type(angle)=="number") then
		error('Usage: SetMMButtonPosition(angle[, radius[, rounding]])', 2)
	end
	self.db.profile.LibMMButton.angle = angle
	if(radius) then
		self.db.profile.LibMMButton.radius = radius
	end
	if(rounding) then
		self.db.profile.LibMMButton.rounding = rounding
	end
	self:LibMMButtonUpdatePosition()
	self:OnMMButtonMove(angle)
end

function LibMMButton:SetMMButtonDropDownMenu(initDropdown)
	local f = self.LibMMButtonFrame
	if not f.dropdown then
		f.dropdown = CreateFrame("Frame", f:GetName().."DropDown", f, "UIDropDownMenuTemplate")
		f.dropdown:SetID(1)
		f.dropdown:Hide()
	end
	if initDropdown then
		UIDropDownMenu_Initialize(f.dropdown, initDropdown, "MENU")
		f:SetScript("OnClick", function(frame, button)
			GameTooltip:Hide()
			if button == "RightButton" then
				ToggleDropDownMenu(1, nil, frame.dropdown, frame)
			else
				self:OnMMButtonClick(button)
			end
		end)
	else
		f:SetScript("OnClick", function(frame, button)
			self:OnMMButtonClick(button)
		end)
	end
end



--------------------------------------------
-- Notes:
-- * Show the button.
--
-- Example:
-- MyAddon:ShowMMButton()
--------------------------------------------
function LibMMButton:ShowMMButton()
	self.LibMMButtonFrame:Show()
end


--------------------------------------------
-- Notes:
-- * Hide the button.
--
-- Example:
-- MyAddon:HideMMButton()
--------------------------------------------
function LibMMButton:HideMMButton()
	self.LibMMButtonFrame:Hide()
end


--------------------------------------------
-- Arguments:
-- string - First line of the Tooltip.
-- [optional] string - Second line of the Tooltip.
--
-- Notes:
-- * Sets the text of theTooltip.
--
-- Example:
-- MyAddon:SetMMButtonTooltip("foo", "bar")
--------------------------------------------
function LibMMButton:SetMMButtonTooltip(lineone, linetwo)
	self.LibMMButtonFrame.tooltipA = lineone
	self.LibMMButtonFrame.tooltipB = linetwo
end


--------------------------------------------
-- Notes:
-- Called when ever the button is left-clicked
--
-- Example:
-- function MyAddon:OnMMButtonClick()
-- 	-- do something
-- end
--------------------------------------------
function LibMMButton:OnMMButtonClick()
end


--------------------------------------------
-- Arguments:
-- integer - angle of the button position
--
-- Notes:
-- Called when ever the button is moved
--
-- Example:
-- function MyAddon:OnMMButtonMove()
-- 	-- do something
-- end
--------------------------------------------
function LibMMButton:OnMMButtonMove(angle)
end


----------------------------------------
-- Internal library stuff
----------------------------------------

-- #NODOC
function LibMMButton:LibMMButtonBeingDragged()
	local mx, my = Minimap:GetCenter()
	local mz = MinimapCluster:GetScale()
	local cx, cy = GetCursorPosition(UIParent)
	local cz = UIParent:GetEffectiveScale()
	local v = math.deg(math.atan2(cy / cz - my * mz, cx / cz - mx * mz))
	if v < 0 then
		v = v + 360
	elseif v > 360 then
		v = v - 360
	end
	self:SetMMButtonPosition(v)
end


-- #NODOC
function LibMMButton:LibMMButtonOnEnter()
	if(not self.LibMMButtonFrame.tooltipA or self.LibMMButtonFrame.tooltipA.len == 0) then
		return
	end
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
	GameTooltip:SetText(self.LibMMButtonFrame.tooltipA)
	if(self.LibMMButtonFrame.tooltipB and self.LibMMButtonFrame.tooltipB.len ~= 0) then
		GameTooltip:AddLine(self.LibMMButtonFrame.tooltipB, 0.8, 0.8, 0.8, 1)
	end
	GameTooltip:Show()
end


local MinimapShapes = {
	-- quadrant booleans (same order as SetTexCoord)
	-- {upper-left, lower-left, upper-right, lower-right}
	-- true = rounded, false = squared
	["ROUND"] = {true, true, true, true},
	["SQUARE"] = {false, false, false, false},
	["CORNER-TOPLEFT"] = {true, false, false, false},
	["CORNER-TOPRIGHT"] = {false, false, true, false},
	["CORNER-BOTTOMLEFT"] = {false, true, false, false},
	["CORNER-BOTTOMRIGHT"] = {false, false, false, true},
	["SIDE-LEFT"] = {true, true, false, false},
	["SIDE-RIGHT"] = {false, false, true, true},
	["SIDE-TOP"] = {true, false, true, false},
	["SIDE-BOTTOM"] = {false, true, false, true},
	["TRICORNER-TOPLEFT"] = {true, true, true, false},
	["TRICORNER-TOPRIGHT"] = {true, false, true, true},
	["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
	["TRICORNER-BOTTOMRIGHT"] = {false, true, true, true},
}
-- #NODOC
function LibMMButton:LibMMButtonUpdatePosition()
	GameTooltip:Hide()
	local radius, rounding, angle

	radius = self.db.profile.LibMMButton.radius
	rounding = self.db.profile.LibMMButton.rounding
	angle = math.rad(self.db.profile.LibMMButton.angle)

	local x = math.cos(angle)
	local y = math.sin(angle)
	local q = 1;
	if x < 0 then
		q = q + 1;	-- lower
	end
	if y > 0 then
		q = q + 2;	-- right
	end
	local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
	local quadTable = MinimapShapes[minimapShape]
	if quadTable[q] then
		x = x*radius
		y = y*radius
	else
		local diagRadius = math.sqrt(2*(radius)^2)-rounding
		x = math.max(-radius, math.min(x*diagRadius, radius))
		y = math.max(-radius, math.min(y*diagRadius, radius))
	end
	self.LibMMButtonFrame:SetPoint("CENTER", Minimap, "CENTER", x, y-1)
end


----------------------------------------
-- Base library stuff
----------------------------------------


--- embedding and embed handling
local mixins = {
	"CreateMMButton",
	"SetMMButtonIcon",
	"SetMMButtonPosition",
	"SetMMButtonDropDownMenu",
	"ShowMMButton",
	"HideMMButton",
	"SetMMButtonTooltip",

	-- overwriteables
	"OnMMButtonClick",
	"OnMMButtonMove",

	-- only internal ... how to hide???
	"LibMMButtonBeingDragged",
	"LibMMButtonOnEnter",
	"LibMMButtonUpdatePosition",
	}


-- #NODOC
function LibMMButton:Embed(target)
	for k, v in pairs(mixins) do
		target[v] = self[v]
	end
	self.embeds[target] = true
	return target
end


-- #NODOC
function LibMMButton:OnEmbedEnable(target)
end


-- #NODOC
function LibMMButton:OnEmbedDisable(target)
--	target:UnregisterAllEvents()
--	target:UnregisterAllMessages()
end


for target, v in pairs(LibMMButton.embeds) do
	LibMMButton:Embed(target)
end