Quantcast
--[[
##############################################################################
_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
	__\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
	 ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
		______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
		 _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
			__/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
			 _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
				___\///////////___________\///___________\/////////_____\///////////_#
##############################################################################
S U P E R - V I L L A I N - U I   By: Munglunch                              #
##############################################################################
##########################################################
LOCALIZED LUA FUNCTIONS
##########################################################
]]--
--[[ GLOBALS ]]--
local _G = _G;
local unpack        = _G.unpack;
local select        = _G.select;
local assert        = _G.assert;
local type          = _G.type;
local error         = _G.error;
local pcall         = _G.pcall;
local print         = _G.print;
local ipairs        = _G.ipairs;
local pairs         = _G.pairs;
local tostring      = _G.tostring;
local tonumber      = _G.tonumber;

--STRING
local string        = _G.string;
local upper         = string.upper;
local format        = string.format;
local find          = string.find;
local match         = string.match;
local gsub          = string.gsub;
--TABLE
local table 		= _G.table;
local tinsert       = _G.tinsert;
local tremove       = _G.tremove;
local twipe 		= _G.wipe;
--MATH
local math      	= _G.math;
local min 			= math.min;
local floor         = math.floor
local ceil          = math.ceil
--BLIZZARD API
local GameTooltip          	= _G.GameTooltip;
local InCombatLockdown     	= _G.InCombatLockdown;
local CreateFrame          	= _G.CreateFrame;
local GetTime         		= _G.GetTime;
local GetItemCooldown       = _G.GetItemCooldown;
local GetItemCount         	= _G.GetItemCount;
local GetItemInfo          	= _G.GetItemInfo;
local GetSpellInfo         	= _G.GetSpellInfo;
local IsSpellKnown         	= _G.IsSpellKnown;
local GetProfessions       	= _G.GetProfessions;
local GetProfessionInfo    	= _G.GetProfessionInfo;
local hooksecurefunc     	= _G.hooksecurefunc;
--[[
##########################################################
ADDON
##########################################################
]]--
local SV = select(2, ...)
local L = SV.L
--[[
##########################################################
DOCKING
##########################################################
]]--
local Dock = SV:NewPackage("Dock", L["Screen Docks"]);
Dock.DefaultDocklet = "";
Dock.DockletWindows = {};
Dock.DockletButtons = {};
Dock.HandledDocklets = {};
Dock.Border = {};

local addonDock1 = CreateFrame("Frame", "SVUI_DockedAddon1", UIParent, "SVUI_DockletWindowTemplate");
local addonDock2 = CreateFrame("Frame", "SVUI_DockedAddon2", UIParent, "SVUI_DockletWindowTemplate");

Dock.Addons = {addonDock1, addonDock2};
Dock.Dropdown = CreateFrame("Frame", "SVUI_DockDropdown", UIParent);

-- MAIN REGIONS
Dock.Left = _G["SVUI_DockLeft"]
Dock.Right = _G["SVUI_DockRight"]
Dock.Top = _G["SVUI_DockTop"]

local AlertActivate = function(self, child)
	local size = SV.db.Dock.buttonSize or 22;
	self:Height(size)
	child:ClearAllPoints()
	child:SetAllPoints(self)
end

local AlertDeactivate = function(self)
	self:Height(1)
end

Dock.Left.Alert.Activate = AlertActivate
Dock.Left.Alert.Deactivate = AlertDeactivate

Dock.Right.Alert.Activate = AlertActivate
Dock.Right.Alert.Deactivate = AlertDeactivate

local ICONFILE = [[Interface\AddOns\SVUI\assets\artwork\Icons\DOCK-BAG-MICRO]];
local TOOL_DATA = {
	[171] 	= {0,0.25,0,0.25}, 				-- PRO-ALCHEMY
    [794] 	= {0.25,0.5,0,0.25,80451}, 		-- PRO-ARCHAELOGY
    [164] 	= {0.5,0.75,0,0.25}, 			-- PRO-BLACKSMITH
    [185] 	= {0.75,1,0,0.25,818,67097}, 	-- PRO-COOKING
    [333] 	= {0,0.25,0.25,0.5,13262}, 		-- PRO-ENCHANTING
    [202] 	= {0.25,0.5,0.25,0.5}, 			-- PRO-ENGINEERING
    [129] 	= {0.5,0.75,0.25,0.5}, 			-- PRO-FIRSTAID
    [773] 	= {0,0.25,0.5,0.75,51005}, 		-- PRO-INSCRIPTION
    [755] 	= {0.25,0.5,0.5,0.75,31252},	-- PRO-JEWELCRAFTING
    [165] 	= {0.5,0.75,0.5,0.75}, 			-- PRO-LEATHERWORKING
    [186] 	= {0.75,1,0.5,0.75}, 			-- PRO-MINING
    [197] 	= {0.25,0.5,0.75,1}, 			-- PRO-TAILORING
}
local HEARTH_SPELLS = {556,50977,18960,126892}
--[[
##########################################################
PRE VARS/FUNCTIONS
##########################################################
]]--
local DD_OnClick = function(self)
	-- DO STUFF
	self:GetParent():Hide()
end

local DD_OnEnter = function(self)
	self.hoverTex:Show()
end

local DD_OnLeave = function(self)
	self.hoverTex:Hide()
end

local function SetFilterMenu(self)
	Dock.Dropdown:ClearAllPoints()
	Dock.Dropdown:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, -8)
	ToggleFrame(Dock.Dropdown)
end

local function CycleDocklets()
	local list = Dock.DockletWindows
	for i=1, #list do
		local f = list[i]
		if(not InCombatLockdown() or (InCombatLockdown() and (f.IsProtected and not f:IsProtected()))) then
			local b = _G[f.ToggleName]
			if(b) then
				b:Deactivate()
			end
			if f.Hide then
				f:Hide()
			end
		end
	end
end

local function GetDefaultWindow()
	local window = Dock.DefaultDocklet
	if window and _G[window] then
		Dock.Right.Window.FrameName = window
		Dock.Right.Window:Show()
	end
end

local ToggleDocks = function(self)
	GameTooltip:Hide()
	if SV.cache.Docks.IsFaded then
		SV.cache.Docks.IsFaded = nil;
		SV:SecureFadeIn(Dock.Left, 0.2, Dock.Left:GetAlpha(), 1)
		SV:SecureFadeIn(Dock.Right, 0.2, Dock.Right:GetAlpha(), 1)
	else
		SV.cache.Docks.IsFaded = true;
		SV:SecureFadeOut(Dock.Left, 0.2, Dock.Left:GetAlpha(), 0, true)
		SV:SecureFadeOut(Dock.Right, 0.2, Dock.Right:GetAlpha(), 0, true)
	end
end

local Docklet_OnShow = function(self)
	if(_G[Dock.Right.Window.FrameName]) then
		if(InCombatLockdown() and (_G[Dock.Right.Window.FrameName].IsProtected and _G[Dock.Right.Window.FrameName]:IsProtected())) then return end
		_G[Dock.Right.Window.FrameName]:Show()
	end
	if _G[Dock.Right.Window.SecondName] then
		if(InCombatLockdown() and (_G[Dock.Right.Window.SecondName].IsProtected and _G[Dock.Right.Window.SecondName]:IsProtected())) then return end
		_G[Dock.Right.Window.SecondName]:Show()
	end
end

local DockButtonActivate = function(self)
	self:SetAttribute("isActive", true)
	self:SetPanelColor("green")
	self.Icon:SetGradient(unpack(SV.Media.gradient.green))
end

local DockButtonDeactivate = function(self)
	self:SetAttribute("isActive", false)
	self:SetPanelColor("default")
	self.Icon:SetGradient(unpack(SV.Media.gradient.icon))
end

local function ToggleDockletWindow(button)
	local frameName = button.FrameName
	local window = _G[frameName];
	if(window) then
		Dock.Right.Window.FrameName = frameName
		if(not window:IsShown()) then
			CycleDocklets()
		end

		if(not Dock.Right.Window:IsShown()) then
			Dock.Right.Window:Show()
		end

		window:Show()
		button:Activate()
	else
		button:Deactivate()
		GetDefaultWindow()
	end
end

local DockletButton_OnEnter = function(self, ...)
	if SV.cache.Docks.IsFaded then
		Dock.Left:Show()
		SV:SecureFadeIn(Dock.Left, 0.2, Dock.Left:GetAlpha(), 1)
		Dock.Right:Show()
		SV:SecureFadeIn(Dock.Right, 0.2, Dock.Right:GetAlpha(), 1)
	end

	self:SetPanelColor("highlight")
	self.Icon:SetGradient(unpack(SV.Media.gradient.bizzaro))

	GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4)
	GameTooltip:ClearLines()
	if(self.CustomTooltip) then
		self:CustomTooltip()
	else
		local tipText = self:GetAttribute("tipText")
		GameTooltip:AddLine(tipText, 1, 1, 1)
	end
	GameTooltip:Show()
end

local DockletButton_OnLeave = function(self, ...)
	if SV.cache.Docks.IsFaded then
		SV:SecureFadeOut(Dock.Left, 0.2, Dock.Left:GetAlpha(), 0, true)
		SV:SecureFadeOut(Dock.Right, 0.2, Dock.Right:GetAlpha(), 0, true)
	end

	if(self:GetAttribute("isActive")) then
		self:SetPanelColor("green")
		self.Icon:SetGradient(unpack(SV.Media.gradient.green))
	else
		self:SetPanelColor("default")
		self.Icon:SetGradient(unpack(SV.Media.gradient.icon))
	end

	GameTooltip:Hide()
end

local DockletButton_OnClick = function(self, button)
	if InCombatLockdown() then return end
	if button == "RightButton" then
		SetFilterMenu(self);
	else
		if self.PostClickFunction then
			if(self:GetAttribute("isActive")) then
				self:Deactivate()
				GetDefaultWindow()
			else
				self:Activate()
			end
			self:PostClickFunction()
		else
			ToggleDockletWindow(self)
		end
	end
end

local DockletFrame_OnShow = function(self)
	local frameName = self.FrameName;
	if (frameName and _G[frameName]) then
		_G[frameName]:Show()
	end
end

local AddonDockletToggle = function(self)
	if addonDock1.FrameName and _G[addonDock1.FrameName] then
		if not _G[addonDock1.FrameName]:IsShown() then
			CycleDocklets()
			if not InCombatLockdown() and not addonDock1:IsShown()then
				addonDock1:Show()
			end
			_G[addonDock1.FrameName]:Show()
			self:Activate()
		elseif not addonDock1:IsShown()then
			if not InCombatLockdown() then addonDock1:Show() end
			_G[addonDock1.FrameName]:Show()
			self:Activate()
		end
	else
		addonDock1.FrameName = "None"
		if InCombatLockdown()then return end
		if addonDock1:IsShown()then
			addonDock1:Hide()
		else
			addonDock1:Show()
		end
		self:Deactivate()
	end
	if SV.db.Dock.docklets.enableExtra and addonDock2.FrameName and _G[addonDock2.FrameName] then
		if not _G[addonDock2.FrameName]:IsShown() then
			if not InCombatLockdown() and not addonDock2:IsShown()then
				addonDock2:Show()
				addonDock1:Show()
			end
			_G[addonDock2.FrameName]:Show()
			self:Activate()
		elseif not addonDock2:IsShown() then
			if not InCombatLockdown() then
				addonDock2:Show()
				addonDock1:Show()
			end
			_G[addonDock2.FrameName]:Show()
			self:Activate()
		else
			if not InCombatLockdown() then
				addonDock2:Hide()
				addonDock1:Hide()
			end
			self:Deactivate()
		end
	else
		addonDock2.FrameName = "None"
	end
end

local function SetSuperDockStyle(dock)
	if dock.backdrop then return end
	local backdrop = CreateFrame("Frame", nil, dock)
	backdrop:SetAllPoints(dock)
	backdrop:SetFrameStrata("BACKGROUND")
	backdrop.bg = backdrop:CreateTexture(nil, "BORDER")
	backdrop.bg:FillInner(backdrop)
	backdrop.bg:SetTexture(1, 1, 1, 1)
	backdrop.bg:SetGradientAlpha("VERTICAL", 0, 0, 0, 0.8, 0, 0, 0, 0)
	backdrop.left = backdrop:CreateTexture(nil, "OVERLAY")
	backdrop.left:SetTexture(1, 1, 1, 1)
	backdrop.left:Point("TOPLEFT", 1, -1)
	backdrop.left:Point("BOTTOMLEFT", -1, 1)
	backdrop.left:Width(4)
	backdrop.left:SetGradientAlpha("VERTICAL", 0, 0, 0, 1, 0, 0, 0, 0)
	backdrop.right = backdrop:CreateTexture(nil, "OVERLAY")
	backdrop.right:SetTexture(1, 1, 1, 1)
	backdrop.right:Point("TOPRIGHT", -1, -1)
	backdrop.right:Point("BOTTOMRIGHT", -1, 1)
	backdrop.right:Width(4)
	backdrop.right:SetGradientAlpha("VERTICAL", 0, 0, 0, 1, 0, 0, 0, 0)
	backdrop.bottom = backdrop:CreateTexture(nil, "OVERLAY")
	backdrop.bottom:SetTexture(0, 0, 0, 1)
	backdrop.bottom:Point("BOTTOMLEFT", 1, 1)
	backdrop.bottom:Point("BOTTOMRIGHT", -1, 1)
	backdrop.bottom:Height(4)
	backdrop.top = backdrop:CreateTexture(nil, "OVERLAY")
	backdrop.top:SetTexture(0,0,0,0)
	backdrop.top:Point("TOPLEFT", 1, -1)
	backdrop.top:Point("TOPRIGHT", -1, 1)
	backdrop.top:SetAlpha(0)
	backdrop.top:Height(1)
	return backdrop
end

Dock.CycleDocklets = CycleDocklets
--[[
##########################################################
CORE FUNCTIONS
##########################################################
]]--
_G.HideSuperDocks = function()
	ToggleDocks(LeftDockToggleButton)
end
--[[
##########################################################
DOCKLET HELPERS
##########################################################
]]--
local function AddTool(button)
	local name = button:GetName();
	if Dock.HandledDocklets[name] then return end
	Dock.HandledDocklets[name] = true;
	local height = Dock.Right.ToolBar:GetHeight();
	local xOffset = #Dock.DockletButtons * (height + 6) + 6
	button:SetPoint("RIGHT", Dock.Right.ToolBar, "RIGHT", (xOffset * -1), 0);
	tinsert(Dock.DockletButtons, button)
 	button.listIndex = #Dock.DockletButtons;
	button:Show()
end

function Dock:ActivateDockletButton(button, clickFunction, tipFunction, isdefault)
	button.Activate = DockButtonActivate
	button.Deactivate = DockButtonDeactivate

	if(tipFunction and type(tipFunction) == "function") then
		button.CustomTooltip = tipFunction
	end

	button:SetPanelColor("default")
	button.Icon:SetGradient(unpack(SV.Media.gradient.icon))
	button:SetScript("OnEnter", DockletButton_OnEnter)
	button:SetScript("OnLeave", DockletButton_OnLeave)
	button:SetScript("OnClick", DockletButton_OnClick)

	if(clickFunction and type(clickFunction) == "function") then
		button.PostClickFunction = clickFunction
	end

	if(isdefault) then
		self.DefaultDocklet = button:GetAttribute("ownerFrame")
		button:Activate()
	end
end

local function CreateBasicToolButton(name, texture, onclick, frameName, isdefault)
	local fName = frameName or name;
	local dockIcon = texture or [[Interface\AddOns\SVUI\assets\artwork\Icons\DOCK-ADDON]];
	local size = Dock.Right.ToolBar:GetHeight();
	local button = _G[fName .. "_ToolBarButton"] or CreateFrame("Button", ("%s_ToolBarButton"):format(fName), Dock.Right.ToolBar, "SVUI_DockletButtonTemplate")

	AddTool(button)

	button:Size(size,size)
	button:SetFramedButtonTemplate()
	button.Icon:SetTexture(dockIcon)
	button:SetAttribute("tipText", "Open " .. name)
    button:SetAttribute("ownerFrame", fName)
    button.FrameName = fName

	Dock:ActivateDockletButton(button, onclick, nil, isdefault)

	_G[fName].ToggleName = fName.."_ToolBarButton";

	return button
end
--[[
##########################################################
DOCKS
##########################################################
]]--
function Dock:CreateDockPanels()
	local leftWidth = SV.db.Dock.dockLeftWidth or 350;
	local leftHeight = SV.db.Dock.dockLeftHeight or 180;
	local rightWidth = SV.db.Dock.dockRightWidth or 350;
	local rightHeight = SV.db.Dock.dockRightHeight or 180;
	local buttonsize = SV.db.Dock.buttonSize or 22;
	local spacing = SV.db.Dock.buttonSpacing or 4;
	local texture = [[Interface\AddOns\SVUI\assets\artwork\Template\BUTTON]];

	-- [[ TOP AND BOTTOM BORDERS ]] --

	self.Border.Top = CreateFrame("Frame", "SVUITopBorder", SV.Screen)
	self.Border.Top:Point("TOPLEFT", SV.Screen, "TOPLEFT", -1, 1)
	self.Border.Top:Point("TOPRIGHT", SV.Screen, "TOPRIGHT", 1, 1)
	self.Border.Top:Height(14)
	self.Border.Top:SetBackdrop({
		bgFile = texture,
		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
		tile = false,
		tileSize = 0,
		edgeSize = 1,
		insets = {left = 0, right = 0, top = 0, bottom = 0}
	})
	self.Border.Top:SetBackdropColor(unpack(SV.Media.color.special))
	self.Border.Top:SetBackdropBorderColor(0,0,0,1)
	self.Border.Top:SetFrameLevel(0)
	self.Border.Top:SetFrameStrata('BACKGROUND')
	self.Border.Top:SetScript("OnShow", function(this)
		this:SetFrameLevel(0)
		this:SetFrameStrata('BACKGROUND')
	end)
	self:TopBorderVisibility()

	self.Border.Bottom = CreateFrame("Frame", "SVUIBottomBorder", SV.Screen)
	self.Border.Bottom:Point("BOTTOMLEFT", SV.Screen, "BOTTOMLEFT", -1, -1)
	self.Border.Bottom:Point("BOTTOMRIGHT", SV.Screen, "BOTTOMRIGHT", 1, -1)
	self.Border.Bottom:Height(14)
	self.Border.Bottom:SetBackdrop({
		bgFile = texture,
		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
		tile = false,
		tileSize = 0,
		edgeSize = 1,
		insets = {left = 0, right = 0, top = 0, bottom = 0}
	})
	self.Border.Bottom:SetBackdropColor(unpack(SV.Media.color.special))
	self.Border.Bottom:SetBackdropBorderColor(0,0,0,1)
	self.Border.Bottom:SetFrameLevel(0)
	self.Border.Bottom:SetFrameStrata('BACKGROUND')
	self.Border.Bottom:SetScript("OnShow", function(this)
		this:SetFrameLevel(0)
		this:SetFrameStrata('BACKGROUND')
	end)
	self:BottomBorderVisibility()

	-- [[ BOTTOM LEFT DOCK ]] --

    self.Left:SetParent(SV.Screen)
    self.Left:Point("BOTTOMLEFT", SV.Screen, "BOTTOMLEFT", 2, 2)
    self.Left:Size(leftWidth, leftHeight)
    self.Left:SetAttribute("buttonSize", buttonsize)
    self.Left:SetAttribute("spacingSize", spacing)
    self.Left.Button:Size(buttonsize, buttonsize)
    self.Left.Button:SetFramedButtonTemplate()
    self.Left.Button.Icon:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Icons\SVUI-EMBLEM]])
    self.Left.Button:SetAttribute("tipText", L["Toggle Docks"])
    self.Left.Button:RegisterForClicks("AnyUp")
    self.Left.ToolBar:Point("LEFT", self.Left.Button, "RIGHT", spacing, 0)
    self.Left.ToolBar:Height(buttonsize)
    self.Left.Window:Size(leftWidth, leftHeight - (buttonsize + 4))
	self.Left.Alert.Activate = AlertActivate
	self.Left.Alert.Deactivate = AlertDeactivate
	self.Left.backdrop = SetSuperDockStyle(self.Left.Window)

	self:ActivateDockletButton(self.Left.Button, ToggleDocks)

	-- [[ BOTTOM RIGHT DOCK ]] --

	self.Right:SetParent(SV.Screen)
	self.Right:Point("BOTTOMRIGHT", SV.Screen, "BOTTOMRIGHT", -2, 2)
	self.Right:Size(rightWidth, rightHeight)
	self.Right:SetAttribute("buttonSize", buttonsize)
    self.Right:SetAttribute("spacingSize", spacing)
	self.Right.Button:Size(buttonsize, buttonsize)
	self.Right.Button:SetFramedButtonTemplate()
	self.Right.Button.Icon:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Icons\DOCK-HENCHMAN]])
	self.Right.Button:SetAttribute("tipText", "Call Henchman!")
	self.Right.Button:RegisterForClicks("AnyUp")
	self.Right.ToolBar:Point("RIGHT", self.Right.Button, "LEFT", -spacing, 0)
	self.Right.ToolBar:Height(buttonsize)
	self.Right.ToolBar.AddonButton:Size(buttonsize, buttonsize)
	self.Right.ToolBar.AddonButton:SetFramedButtonTemplate()
	self.Right.ToolBar.AddonButton.Icon:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Icons\DOCK-ADDON]])
	self.Right.ToolBar.AddonButton:SetAttribute("tipText", "")
	self.Right.ToolBar.AddonButton.IsRegistered = false;
	self.Right.Window:Size(rightWidth, rightHeight - (buttonsize + 4))
	self.Right.Alert.Activate = AlertActivate
	self.Right.Alert.Deactivate = AlertDeactivate
	self.Right.backdrop = SetSuperDockStyle(self.Right.Window)

	self:ActivateDockletButton(self.Right.Button, SV.ToggleHenchman)
	self:ActivateDockletButton(self.Right.ToolBar.AddonButton, AddonDockletToggle)

	SV.Mentalo:Add(self.Left.BarHolder, L["Left Dock Buttons"])
	SV.Mentalo:Add(self.Left.Window, L["Left Dock Window"])
	SV.Mentalo:Add(self.Right.BarHolder, L["Right Dock Buttons"])
	SV.Mentalo:Add(self.Right.Window, L["Right Dock Window"])
	SV:AddToDisplayAudit(self.Right.Window)

	if SV.cache.Docks.IsFaded then Dock.Left:Hide() Dock.Right:Hide() end

	-- [[ TOP LEFT DOCK ]] --

	self.Top:SetParent(SV.Screen)
	self.Top:Point("TOPLEFT", SV.Screen, "TOPLEFT", 1, -2)
	self.Top:Size(leftWidth, leftHeight)
	self.Top:SetAttribute("buttonSize", buttonsize)
    self.Top:SetAttribute("spacingSize", spacing)
	self.Top.ToolBar:Size(1, buttonsize)

	SV.Mentalo:Add(self.Top, L["Top Dock"])

	--RIGHT CLICK MENU

	self.Dropdown:SetParent(SV.Screen)
	self.Dropdown:SetPanelTemplate("Default")
	self.Dropdown.buttons = {}
	self.Dropdown:SetFrameStrata("DIALOG")
	self.Dropdown:SetClampedToScreen(true)

	for i = 1, 4 do
		self.Dropdown.buttons[i] = CreateFrame("Button", nil, self.Dropdown)

		self.Dropdown.buttons[i].hoverTex = self.Dropdown.buttons[i]:CreateTexture(nil, 'OVERLAY')
		self.Dropdown.buttons[i].hoverTex:SetAllPoints()
		self.Dropdown.buttons[i].hoverTex:SetTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]])
		self.Dropdown.buttons[i].hoverTex:SetBlendMode("ADD")
		self.Dropdown.buttons[i].hoverTex:Hide()

		self.Dropdown.buttons[i].activeTex = self.Dropdown.buttons[i]:CreateTexture(nil, 'OVERLAY')
		self.Dropdown.buttons[i].activeTex:SetAllPoints()
		self.Dropdown.buttons[i].activeTex:SetTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]])
		self.Dropdown.buttons[i].activeTex:SetVertexColor(0,0.7,0)
		self.Dropdown.buttons[i].activeTex:SetBlendMode("ADD")
		self.Dropdown.buttons[i].activeTex:Hide()

		self.Dropdown.buttons[i].text = self.Dropdown.buttons[i]:CreateFontString(nil, 'BORDER')
		self.Dropdown.buttons[i].text:SetAllPoints()
		self.Dropdown.buttons[i].text:SetFont(SV.Media.font.roboto,12,"OUTLINE")
		self.Dropdown.buttons[i].text:SetJustifyH("LEFT")
		self.Dropdown.buttons[i].text:SetText(("Option %d"):format(i))

		self.Dropdown.buttons[i]:SetHeight(16)
		self.Dropdown.buttons[i]:SetWidth(115)

		self.Dropdown.buttons[i]:SetScript("OnEnter", DD_OnEnter)
		self.Dropdown.buttons[i]:SetScript("OnLeave", DD_OnLeave)
		self.Dropdown.buttons[i]:SetScript("OnClick", DD_OnClick)

		if i == 1 then
			self.Dropdown.buttons[i]:SetPoint("TOPLEFT", self.Dropdown, "TOPLEFT", 10, -10)
		else
			self.Dropdown.buttons[i]:SetPoint("TOPLEFT", self.Dropdown.buttons[i - 1], "BOTTOMLEFT", 0, 0)
		end

		self.Dropdown.buttons[i]:Show()
	end

	self.Dropdown:SetSize(135, 94)
	self.Dropdown:Hide()
	SV:AddToDisplayAudit(self.Dropdown)
end

local function BorderColorUpdates()
	Dock.Border.Top:SetBackdropColor(unpack(SV.Media.color.special))
	Dock.Border.Top:SetBackdropBorderColor(0,0,0,1)
	Dock.Border.Bottom:SetBackdropColor(unpack(SV.Media.color.special))
	Dock.Border.Bottom:SetBackdropBorderColor(0,0,0,1)
end

SV:NewCallback(BorderColorUpdates)

do
	local LastAddedMacro;
	local MacroCount = 0;

	local function GetMacroCooldown(itemID)
		local start,duration = GetItemCooldown(itemID)
		local expires = duration - (GetTime() - start)
		if expires > 0.05 then
			local timeLeft = 0;
			local calc = 0;
			if expires < 4 then
				return format("|cffff0000%.1f|r", expires)
			elseif expires < 60 then
				return format("|cffffff00%d|r", floor(expires))
			elseif expires < 3600 then
				timeLeft = ceil(expires / 60);
				calc = floor((expires / 60) + .5);
				return format("|cffff9900%dm|r", timeLeft)
			elseif expires < 86400 then
				timeLeft = ceil(expires / 3600);
				calc = floor((expires / 3600) + .5);
				return format("|cff66ffff%dh|r", timeLeft)
			else
				timeLeft = ceil(expires / 86400);
				calc = floor((expires / 86400) + .5);
				return format("|cff6666ff%dd|r", timeLeft)
			end
		else
			return "|cff6666ffReady|r"
		end
	end

	local SetMacroTooltip = function(self)
		local text1 = self:GetAttribute("tipText")
		local text2 = self:GetAttribute("tipExtraText")
		if(not text2) then
			GameTooltip:AddLine(text1, 1, 1, 1)
		else
			GameTooltip:AddDoubleLine("[Left-Click]", text1, 0, 1, 0, 1, 1, 1)
			GameTooltip:AddDoubleLine("[Right-Click]", "Use " .. text2, 0, 1, 0, 1, 1, 1)
			if InCombatLockdown() then return end
			if(self.ItemToUse) then
				GameTooltip:AddLine(" ", 1, 1, 1)
				local remaining = GetMacroCooldown(self.ItemToUse)
				GameTooltip:AddDoubleLine(text2, remaining, 1, 0.5, 0, 0, 1, 1)
			end
		end
	end

	local SetHearthTooltip = function(self)
		GameTooltip:AddLine(L["Hearthstone"], 1, 1, 1)
		if InCombatLockdown() then return end
		local remaining = GetMacroCooldown(6948)
		GameTooltip:AddDoubleLine(L["Time Remaining"], remaining, 1, 1, 1, 0, 1, 1)
		local extraText = self:GetAttribute("tipExtraText")
		if(extraText) then
			GameTooltip:AddLine(" ", 1, 1, 1)
			GameTooltip:AddDoubleLine(extraText, "[Right Click]", 1, 1, 1, 0, 1, 0)
		end
	end

	local function CreateMacroToolButton(proName, proID, itemID, size)
		local data = TOOL_DATA[proID]
		if(not data) then return end
		local button = CreateFrame("Button", ("%s_MacroBarButton"):format(itemID), Dock.Right.ToolBar, "SecureActionButtonTemplate,SVUI_DockletButtonTemplate")
		button:Size(size, size)
		AddTool(button)
		button:SetFramedButtonTemplate()
		button.Icon:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Icons\PROFESSIONS]])
		button.Icon:SetTexCoord(data[1], data[2], data[3], data[4])
		button.Icon:SetGradient("VERTICAL", 0.5, 0.53, 0.55, 0.8, 0.8, 1)
		button:SetAttribute("tipText", "Open " .. proName)

		if proID == 186 then proName = "Smelting" end

		if(data[5]) then
			local rightClick
			button:RegisterForClicks("AnyDown")
			if(data[6] and GetItemCount(data[6], true) > 0) then
				rightClick = GetItemInfo(data[6])
				button.ItemToUse = data[6]
			else
				rightClick = GetSpellInfo(data[5])
			end
			button:SetAttribute("tipExtraText", rightClick)
			button:SetAttribute("type", "macro")
			button:SetAttribute("macrotext", "/cast [button:2] " .. rightClick .. ";" .. proName)
		else
			button:SetAttribute("type", "macro")
			button:SetAttribute("macrotext", "/cast " .. proName)
		end

		Dock:ActivateDockletButton(button, nil, SetMacroTooltip)
	end

	function Dock:LoadToolBarProfessions()
		if(SV.ToolBarLoaded) then return end
		if(InCombatLockdown()) then Dock:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
		local size = Dock.Right.ToolBar:GetHeight()
		local hearth = CreateFrame("Button", "SVUI_HearthButton", Dock.Right.ToolBar, "SecureActionButtonTemplate, SVUI_DockletButtonTemplate")
		hearth:Size(size, size)
		AddTool(hearth)
		hearth:SetFramedButtonTemplate()
		hearth.Icon:SetTexture("Interface\\AddOns\\SVUI\\assets\\artwork\\Icons\\DOCK-HEARTH")
		hearth.Icon:SetTexCoord(0,0.5,0,1)
		hearth:RegisterForClicks("AnyUp")
		hearth:SetAttribute("type", "item")
		hearth:SetAttribute("item", "Hearthstone")

		Dock:ActivateDockletButton(hearth, nil, SetHearthTooltip)

		for i = 1, #HEARTH_SPELLS do
			if(IsSpellKnown(HEARTH_SPELLS[i])) then
				local rightClickSpell = GetSpellInfo(HEARTH_SPELLS[i])
				hearth:SetAttribute("type2", "spell")
				hearth:SetAttribute("spell", rightClickSpell)
				hearth:SetAttribute("tipExtraText", rightClickSpell)
			end
		end

		local proName, proID
		local prof1, prof2, archaeology, _, cooking, firstAid = GetProfessions()
		if(firstAid ~= nil) then
			proName, _, _, _, _, _, proID = GetProfessionInfo(firstAid)
			CreateMacroToolButton(proName, proID, firstAid, size)
		end
		if(archaeology ~= nil) then
			proName, _, _, _, _, _, proID = GetProfessionInfo(archaeology)
			CreateMacroToolButton(proName, proID, archaeology, size)
		end
		if(cooking ~= nil) then
			proName, _, _, _, _, _, proID = GetProfessionInfo(cooking)
			CreateMacroToolButton(proName, proID, cooking, size)
		end
		if(prof2 ~= nil) then
			proName, _, _, _, _, _, proID = GetProfessionInfo(prof2)
			if(proID ~= 182 and proID ~= 393) then
				CreateMacroToolButton(proName, proID, prof2, size)
			end
		end
		if(prof1 ~= nil) then
			proName, _, _, _, _, _, proID = GetProfessionInfo(prof1)
			if(proID ~= 182 and proID ~= 393) then
				CreateMacroToolButton(proName, proID, prof1, size)
			end
		end

		SV.ToolBarLoaded = true
	end
end
--[[
##########################################################
EXTERNALLY ACCESSIBLE METHODS
##########################################################
]]--
SV.CurrentlyDocked = {};

function Dock:IsDockletReady(arg)
	local addon = arg;
	if arg == "DockletMain" or arg == "DockletExtra" then
		addon = SV.db.Dock.docklets[arg]
	end
	if addon == nil or addon == "None" then
		return false
	end
	return true
end

do
	local function UnregisterDocklet(name)
		local frame = _G[name];
		if not frame or not frame.listIndex then return end
		local i = frame.listIndex;
		tremove(Dock.DockletWindows, i)
	end

	local function RemoveDocklet(button)
		if not button or not button.listIndex then return end
		local name = button:GetName();
		if not Dock.HandledDocklets[name] then return end
		Dock.HandledDocklets[name] = nil;
		local index = button.listIndex;
		tremove(Dock.DockletButtons, index)
		button:Hide()

		local height = Dock.Right.ToolBar:GetHeight();

		for i = 1, #Dock.DockletButtons do
			local nextButton = Dock.DockletButtons[i]
			local xOffset = (i - 1) * (height + 6) + 6
			nextButton:ClearAllPoints()
			nextButton:SetPoint("RIGHT", Dock.Right.ToolBar, "RIGHT", (xOffset * -1), 0);
		end
	end

	function Dock:ReloadDocklets(alert)
		if InCombatLockdown() then return end

		local frame, i;
		twipe(SV.CurrentlyDocked);
		if self:IsDockletReady("DockletMain") then
			frame = SV.db.Dock.docklets.MainWindow
			if frame ~= nil and frame ~= "None" and _G[frame] then
				UnregisterDocklet(frame)
				SV.db.Dock.docklets.MainWindow = "None"
			end
		elseif self.Right.ToolBar.AddonButton.IsRegistered then
			RemoveDocklet(self.Right.ToolBar.AddonButton)
			self.Right.ToolBar.AddonButton:SetAttribute("tipText", "")
			self.Right.ToolBar.AddonButton.IsRegistered = false;
		end
		if self:IsDockletReady("DockletExtra") then
			frame = SV.db.Dock.docklets.ExtraWindow
			if frame ~= nil and frame ~= "None" and _G[frame] then
				UnregisterDocklet(frame)
				SV.db.Dock.docklets.ExtraWindow = "None"
			end
		end
		addonDock1.FrameName = "None"
		addonDock2.FrameName = "None"

		local width,height = Dock.Right.Window:GetSize();

		if self:IsDockletReady('DockletMain') then
			if self:IsDockletReady("DockletExtra") and SV.db.Dock.docklets.enableExtra then
				width = width * 0.5;
			end
			addonDock1:ClearAllPoints()
			addonDock1:Size(width,height)
			addonDock1:Point('BOTTOMLEFT',Dock.Right.Window,'BOTTOMLEFT',1,1)
			addonDock2:ClearAllPoints()
			addonDock2:Size(width,height)
			addonDock2:Point('BOTTOMLEFT',addonDock1,'BOTTOMRIGHT',0,0)
		end
	end
end


function Dock:RegisterDocklet(name, tooltip, texture, onclick, isdefault)
	local frame = _G[name];
	if frame and (frame.IsObjectType and frame:IsObjectType("Frame")) and (frame.IsProtected and not frame:IsProtected()) then
		frame:ClearAllPoints()
		frame:SetParent(self.Right.Window)
		frame:FillInner(self.Right.Window, 4, 4)
		frame.FrameName = name;
		tinsert(self.DockletWindows, frame);
		frame.listIndex = #self.DockletWindows;
		frame.ToolbarButton = CreateBasicToolButton(tooltip, texture, onclick, name, isdefault)
	end
end

function Dock:RegisterMainDocklet(name)
	local frame = _G[name];
	if (frame and (frame.IsObjectType and frame:IsObjectType("Frame")) and (frame.IsProtected and not frame:IsProtected())) then
		addonDock1.FrameName = name;
		SV.db.Dock.docklets.MainWindow = name;
		frame:ClearAllPoints()
		frame:SetParent(addonDock1)
		frame:SetAllPoints(addonDock1)
		frame.ToggleName = "Dock.RightToolBarAddonButton";
		tinsert(self.DockletWindows, frame);
		frame.listIndex = #self.DockletWindows;
		AddTool(self.Right.ToolBar.AddonButton)
		self.Right.ToolBar.AddonButton:SetAttribute("tipText", "")
		self.Right.ToolBar.AddonButton.IsRegistered = true
		SV.CurrentlyDocked[name] = true
		if not InCombatLockdown() and frame:IsShown() then frame:Hide() end
	end
end

function Dock:RegisterExtraDocklet(name)
	local frame = _G[name];
	if (frame and (frame.IsObjectType and frame:IsObjectType("Frame")) and (frame.IsProtected and not frame:IsProtected())) then
		addonDock2.FrameName = name;
		SV.db.Dock.docklets.ExtraWindow = name;
		frame:ClearAllPoints()
		frame:SetParent(addonDock2)
		frame:SetAllPoints(addonDock2)
		frame.ToggleName = "Dock.RightToolBarAddonButton";
		tinsert(self.DockletWindows, frame);
		frame.listIndex = #self.DockletWindows;
		self.Right.ToolBar.AddonButton:SetAttribute("tipText", "")
		SV.CurrentlyDocked[name] = true;
		if not InCombatLockdown() and frame:IsShown() then frame:Hide() end
	end
end
--[[
##########################################################
BUILD/UPDATE
##########################################################
]]--
function Dock:UpdateDockBackdrops()
	if SV.db.Dock.rightDockBackdrop then
		Dock.Right.backdrop:Show()
		Dock.Right.backdrop:ClearAllPoints()
		Dock.Right.backdrop:WrapOuter(Dock.Right.Window, 4, 4)
	else
		Dock.Right.backdrop:Hide()
	end
	if SV.db.Dock.leftDockBackdrop then
		Dock.Left.backdrop:Show()
		Dock.Left.backdrop:ClearAllPoints()
		Dock.Left.backdrop:WrapOuter(Dock.Left.Window, 4, 4)
	else
		Dock.Left.backdrop:Hide()
	end
end

function Dock:BottomBorderVisibility()
	if SV.db.Dock.bottomPanel then
		self.Border.Bottom:Show()
	else
		self.Border.Bottom:Hide()
	end
end

function Dock:TopBorderVisibility()
	if SV.db.Dock.topPanel then
		self.Border.Top:Show()
	else
		self.Border.Top:Hide()
	end
end

function Dock:PLAYER_REGEN_ENABLED()
	self:UnregisterEvent('PLAYER_REGEN_ENABLED')
	self:LoadToolBarProfessions()
end

function Dock:Refresh()
	local leftWidth = SV.db.Dock.dockLeftWidth or 350;
	local leftHeight = SV.db.Dock.dockLeftHeight or 180;
	local rightWidth = SV.db.Dock.dockRightWidth or 350;
	local rightHeight = SV.db.Dock.dockRightHeight or 180;
	local buttonsize = SV.db.Dock.buttonSize or 22;
	local spacing = SV.db.Dock.buttonSpacing or 4;

	self.Left:Size(leftWidth, leftHeight)
	self.Left.Window:Size(leftWidth, leftHeight - (buttonsize + 4))
	self.Right:Size(rightWidth, rightHeight)
	self.Right.Window:Size(rightWidth, rightHeight - (buttonsize + 4))

	self:BottomBorderVisibility();
	self:TopBorderVisibility();
	self:UpdateDockBackdrops();
	self:ReloadDocklets()
end

function Dock:Initialize()
	SV.cache.Docks = SV.cache.Docks	or {}

	if(not SV.cache.Docks.IsFaded) then
		SV.cache.Docks.IsFaded = false
	end

	self:CreateDockPanels()
	self.Right.Window:SetScript("OnShow", Docklet_OnShow)

	if not InCombatLockdown()then
		CycleDocklets()
	end

	self:UpdateDockBackdrops()
	addonDock1:SetFrameLevel(self.Right.Window:GetFrameLevel() + 50)
	addonDock2:SetFrameLevel(self.Right.Window:GetFrameLevel() + 50)

	local size = self.Right.ToolBar:GetHeight();

	addonDock1:SetScript("OnShow", DockletFrame_OnShow)
	addonDock2:SetScript("OnShow", DockletFrame_OnShow)
	self:ReloadDocklets(true)

	SV.Timers:ExecuteTimer(self.LoadToolBarProfessions, 5)
end