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 pairs 	= _G.pairs;
local type 		= _G.type;
local tinsert 	= _G.tinsert;
local string 	= _G.string;
local math 		= _G.math;
local table 	= _G.table;
--[[ STRING METHODS ]]--
local format,find = string.format, string.find;
--[[ MATH METHODS ]]--
local floor = math.floor;
--[[ TABLE METHODS ]]--
local twipe, tcopy = table.wipe, table.copy;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local PLUGIN = select(2, ...)
local Schema = PLUGIN.Schema;
local VERSION = PLUGIN.Version;

local SV = _G.SVUI
local L = SV.L
local NewHook = hooksecurefunc;
--[[
##########################################################
CORE DATA
##########################################################
]]--
PLUGIN.DockedParent = {}
PLUGIN.AddOnQueue = {};
PLUGIN.AddOnEvents = {};
PLUGIN.CustomQueue = {};
PLUGIN.EventListeners = {};
PLUGIN.OnLoadAddons = {};
PLUGIN.StyledAddons = {};
PLUGIN.Debugging = false
--[[
##########################################################
CORE FUNCTIONS
##########################################################
]]--
local charming = {"Spiffy", "Pimped Out", "Fancy", "Awesome", "Bad Ass", "Sparkly", "Gorgeous", "Handsome", "Shiny"}
local errorMessage = '%s: |cffff0000There was an error in the|r |cff0affff%s|r |cffff0000skin|r. |cffFF0000[[|r%s|cffFF0000]]|r'
local styleMessage = '|cff00FF77%s|r Is Now %s!'

local function SendAddonMessage(msg, prefix)
	if(type(msg) == "table") then
        msg = tostring(msg)
    end

    if(not msg) then return end

    if(prefix) then
    	local outbound = ("%s %s"):format(prefix, msg);
    	print(outbound)
    else
    	print(msg)
    end
end

function PLUGIN:AddonMessage(msg)
    local outbound = ("|cffFF2F00%s:|r"):format("Style-O-Matic")
    SendAddonMessage(msg, outbound)
end

function PLUGIN:LoadAlert(MainText, Function)
	self.Alert.Text:SetText(MainText)
	self.Alert.Accept:SetScript('OnClick', Function)
	self.Alert:Show()
end

function PLUGIN:Style(style, fn, ...)
	local pass, error = pcall(fn, ...)
	if(self.Debugging and error) then
		SV:Debugger(errorMessage:format(VERSION, style, error))
		return
	end
	if(pass and (not style:find("Blizzard")) and not self.StyledAddons[style]) then
		self.StyledAddons[style] = true
		local verb = charming[math.random(1,#charming)]
		self:AddonMessage(styleMessage:format(style, verb))
	end
	self.Debugging = false
end

function PLUGIN:IsAddonReady(addon, ...)
	if not SV.db[Schema].addons then return end
	for i = 1, select('#', ...) do
		local a = select(i, ...)
		if not a then break end
		if not IsAddOnLoaded(a) then return false end
	end

	return SV.db[Schema].addons[addon]
end

function PLUGIN:SaveAddonStyle(addon, fn, force, passive, ...)
	self:DefineEventFunction("PLAYER_ENTERING_WORLD", addon)
	if(passive) then
		self:DefineEventFunction("ADDON_LOADED", addon)
	end
	for i=1, select("#",...) do
		local event = select(i,...)
		if(event) then
			self:DefineEventFunction(event, addon)
		end
	end
	if(SV.db[Schema].addons and SV.db[Schema].addons[addon] == nil) then
		SV.db[Schema].addons[addon] = true
	end

	if force then
		fn()
	else
		self.AddOnQueue[addon] = fn
	end
end

function PLUGIN:SaveBlizzardStyle(addon, fn, force)
	if force then
		if(not IsAddOnLoaded(addon)) then
			LoadAddOn(addon)
		end
		fn()
	else
		self.OnLoadAddons[addon] = fn
	end
end

function PLUGIN:SaveCustomStyle(fn)
	tinsert(PLUGIN.CustomQueue, fn)
end

function PLUGIN:DefineEventFunction(addonEvent, addon)
	if(not addon) then return end
	if(not self.EventListeners[addonEvent]) then
		self.EventListeners[addonEvent] = {}
	end
	self.EventListeners[addonEvent][addon] = true
	if(not self[addonEvent]) then
		self[addonEvent] = function(self, event, ...)
			for name,fn in pairs(self.AddOnQueue) do
				if self:IsAddonReady(name) and self.EventListeners[event] and self.EventListeners[event][name] then
					self:Style(name, fn, event, ...)
				end
			end
		end
		self:RegisterEvent(addonEvent);
	end
end

function PLUGIN:SafeEventRemoval(addon, event)
	if not self.EventListeners[event] then return end
	if not self.EventListeners[event][addon] then return end
	self.EventListeners[event][addon] = nil;
	local defined = false;
	for name,_ in pairs(self.EventListeners[event]) do
		if name then
			defined = true;
			break
		end
	end
	if not defined then
		self:UnregisterEvent(event)
	end
end

function PLUGIN:RefreshAddonStyles()
	for addon,fn in pairs(self.AddOnQueue) do
		if(self:IsAddonReady(addon)) then
			self:Style(addon, fn)
		end
	end
end

function PLUGIN:PLAYER_ENTERING_WORLD(event, ...)
	for addonName,fn in pairs(self.OnLoadAddons) do
		if(SV.db[Schema].blizzard[addonName] == nil) then
			SV.db[Schema].blizzard[addonName] = true
		end
		if(IsAddOnLoaded(addonName) and (SV.db[Schema].blizzard[addonName] or SV.db[Schema].addons[addonName])) then
			self:Style(addonName, fn, event, ...)
			self.OnLoadAddons[addonName] = nil
		end
	end

	for _,fn in pairs(self.CustomQueue)do
		fn(event, ...)
	end

	twipe(self.CustomQueue)

	local listener = self.EventListeners[event]
	for addonName,fn in pairs(self.AddOnQueue)do
		if(not SV.Options.args.plugins.args.pluginOptions.args[Schema].args["addons"].args[addonName]) then
			SV.Options.args.plugins.args.pluginOptions.args[Schema].args["addons"].args[addonName] = {
				type = "toggle",
				name = addonName,
				desc = L["Addon Styling"],
				get = function(key) return PLUGIN:IsAddonReady(key[#key]) end,
				set = function(key,value) PLUGIN:ChangeDBVar(value, key[#key], "addons"); SV:StaticPopup_Show("RL_CLIENT") end,
				disabled = function()
					if addonName then
						 return not IsAddOnLoaded(addonName)
					else
						 return false
					end
				end
			}
		end
		if(SV.db[Schema].addons[addonName] == nil) then
			SV.db[Schema].addons[addonName] = true
		end
		if(listener[addonName] and self:IsAddonReady(addonName)) then
			self:Style(addonName, fn, event, ...)
		end
	end
end

function PLUGIN:ADDON_LOADED(event, addon)
	-- print(addon)
	for name, fn in pairs(self.OnLoadAddons) do
		if(addon:find(name)) then
			self:Style(name, fn, event, addon)
			self.OnLoadAddons[name] = nil
		end
	end

	local listener = self.EventListeners[event]
	if(listener) then
		for name, fn in pairs(self.AddOnQueue) do
			if(listener[name] and self:IsAddonReady(name)) then
				self:Style(name, fn, event, addon)
			end
		end
	end
end
--[[
##########################################################
OPTIONS CREATION
##########################################################
]]--
local RegisterAddonDocklets = function()
	local MAIN = _G["SuperDockletMain"];
	local EXTRA = _G["SuperDockletExtra"];
	local main = SV.db.SVDock.docklets.DockletMain;
  	local alternate = SV.db.SVDock.docklets.enableExtra and SV.db.SVDock.docklets.DockletExtra or "";
  	local tipLeft, tipRight = "", "";
  	if main == nil or main == "None" then return end

	if find(main, "Skada") or find(alternate, "Skada") then
		if SV:IsDockletReady("Skada") then
			PLUGIN:Docklet_Skada()
			if find(alternate, "Skada") and EXTRA.FrameName  ~= "SkadaHolder2" then
				tipRight = "and Skada";
				SV:RegisterExtraDocklet("SkadaHolder2")
				--PLUGIN.DockedParent["Skada"] = EXTRA
			end
			if find(main, "Skada") and MAIN.FrameName  ~= "SkadaHolder" then
				tipLeft = "Skada";
				SV:RegisterMainDocklet("SkadaHolder")
				--PLUGIN.DockedParent["Skada"] = MAIN
			end
		end
	end
	if main == "Omen" or alternate == "Omen" then
		if SV:IsDockletReady("Omen") then
			if alternate == "Omen" and EXTRA.FrameName ~= "OmenAnchor" then
				tipRight = "and Omen";
				SV:RegisterExtraDocklet("OmenAnchor")
				PLUGIN:Docklet_Omen(EXTRA)
				PLUGIN.DockedParent["Omen"] = EXTRA
			elseif MAIN.FrameName ~= "OmenAnchor" then
				tipLeft = "Omen";
				SV:RegisterMainDocklet("OmenAnchor")
				PLUGIN:Docklet_Omen(MAIN)
				PLUGIN.DockedParent["Omen"] = MAIN
			end
		end
	end
	if main == "Recount" or alternate == "Recount" then
		if SV:IsDockletReady("Recount") then
			if alternate == "Recount" and EXTRA.FrameName ~= "Recount_MainWindow" then
				tipRight = "and Recount";
				SV:RegisterExtraDocklet("Recount_MainWindow")
				PLUGIN:Docklet_Recount(EXTRA)
				PLUGIN.DockedParent["Recount"] = EXTRA
			elseif MAIN.FrameName ~= "Recount_MainWindow" then
				tipLeft = "Recount";
				SV:RegisterMainDocklet("Recount_MainWindow")
				PLUGIN:Docklet_Recount(MAIN)
				PLUGIN.DockedParent["Recount"] = MAIN
			end
		end
	end
	if main == "TinyDPS" or alternate == "TinyDPS" then
		if SV:IsDockletReady("TinyDPS") then
			if alternate == "TinyDPS" and EXTRA.FrameName ~= "tdpsFrame" then
				tipRight = "and TinyDPS";
				SV:RegisterExtraDocklet("tdpsFrame")
				PLUGIN:Docklet_TinyDPS(EXTRA)
				PLUGIN.DockedParent["TinyDPS"] = EXTRA
			elseif MAIN.FrameName ~= "tdpsFrame" then
				tipLeft = "TinyDPS";
				SV:RegisterMainDocklet("tdpsFrame")
				PLUGIN:Docklet_TinyDPS(MAIN)
				PLUGIN.DockedParent["TinyDPS"] = MAIN
			end
		end
	end
	if main == "alDamageMeter" or alternate == "alDamageMeter" then
		if SV:IsDockletReady("alDamageMeter") then
			if alternate == "alDamageMeter" and EXTRA.FrameName ~= "alDamagerMeterFrame" then
				tipRight = "and alDamageMeter";
				SV:RegisterExtraDocklet("alDamagerMeterFrame")
				PLUGIN:Docklet_alDamageMeter(EXTRA)
				PLUGIN.DockedParent["alDamageMeter"] = EXTRA
			elseif MAIN.FrameName ~= "alDamagerMeterFrame" then
				tipLeft = "alDamageMeter";
				SV:RegisterMainDocklet("alDamagerMeterFrame")
				PLUGIN:Docklet_alDamageMeter(MAIN)
				PLUGIN.DockedParent["alDamageMeter"] = MAIN
			end
		end
	end

	if(_G["SVUI_AddonDocklet"]) then
		_G["SVUI_AddonDocklet"].TText = ("%s%s"):format(tipLeft, tipRight)
	end
end
--[[
##########################################################
BUILD FUNCTION
##########################################################
]]--
function PLUGIN:Load()
	if(not SV.db[Schema].enable) then return end

	local alert = CreateFrame('Frame', nil, UIParent);
	alert:SetFixedPanelTemplate('Transparent');
	alert:SetSize(250, 70);
	alert:SetPoint('CENTER', UIParent, 'CENTER');
	alert:SetFrameStrata('DIALOG');
	alert.Text = alert:CreateFontString(nil, "OVERLAY");
	alert.Text:SetFont(SV.Media.font.default, 12);
	alert.Text:SetPoint('TOP', alert, 'TOP', 0, -10);
	alert.Accept = CreateFrame('Button', nil, alert);
	alert.Accept:SetSize(70, 25);
	alert.Accept:SetPoint('RIGHT', alert, 'BOTTOM', -10, 20);
	alert.Accept.Text = alert.Accept:CreateFontString(nil, "OVERLAY");
	alert.Accept.Text:SetFont(SV.Media.font.default, 10);
	alert.Accept.Text:SetPoint('CENTER');
	alert.Accept.Text:SetText(YES);
	alert.Close = CreateFrame('Button', nil, alert);
	alert.Close:SetSize(70, 25);
	alert.Close:SetPoint('LEFT', alert, 'BOTTOM', 10, 20);
	alert.Close:SetScript('OnClick', function(this) this:GetParent():Hide() end);
	alert.Close.Text = alert.Close:CreateFontString(nil, "OVERLAY");
	alert.Close.Text:SetFont(SV.Media.font.default, 10);
	alert.Close.Text:SetPoint('CENTER');
	alert.Close.Text:SetText(NO);
	alert.Accept:SetButtonTemplate();
	alert.Close:SetButtonTemplate();
	alert:Hide();
	self.Alert = alert;

	NewHook(SV, "ReloadDocklets", RegisterAddonDocklets);
	SV:ReloadDocklets();

	self:RegisterEvent("PLAYER_ENTERING_WORLD");
	self:RegisterEvent("ADDON_LOADED");
end