Quantcast
--[[-------------------------------------------------------------------------
  Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials provided
        with the distribution.
      * Neither the name of PerfectRaid nor the names of its contributors
        may be used to endorse or promote products derived from this software
        without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------]]

local Buffs = PerfectRaid:NewModule("PerfectRaid-Buffs")
local L = PerfectRaidLocals
local utils, frames

function Buffs:Initialize()
	PerfectRaid.defaults.profile.buffs = {}

	frames = PerfectRaid.frames
	utils = PerfectRaid.utils
	self:RegisterMessage("DONGLE_PROFILE_CREATED")
	self:RegisterMessage("PERFECTRAID_TAB_CHANGED")
end

function Buffs:Enable()
	self:RegisterEvent("UNIT_AURA")
	self:RegisterEvent("RAID_ROSTER_UPDATE")
	if GetNumRaidMembers() > 0 then
		self:RAID_ROSTER_UPDATE()
	end

	self:UpdateBuffTable()

	for unit in pairs(frames) do
		self:UNIT_AURA(nil, unit)
	end
end

function Buffs:DONGLE_PROFILE_CREATED(event, db, addon, svname, profileKey)
	if svname ~= "PerfectRaidDB" then return end
	self:PrintF(L["Adding default buffs to new profile \"%s\""], profileKey)
	local buffs = db.profile.buffs
	for k,v in ipairs(self.defaults) do
		if not v.disabled then
			self:AddDefaultBuff(buffs, v)
		end
	end
end

function Buffs:PERFECTRAID_TAB_CHANGED(old,new)
	if PROptions_Buffs_Edit and PROptions_Buffs_Edit:IsVisible() then
		self.options:FadeOut(PROptions_Buffs_Edit)
	end
end

local raidLookup = {}
for i=1,40 do
	raidLookup[i] = "raid"..i
end
function Buffs:RAID_ROSTER_UPDATE()
	if GetNumRaidMembers() > 0 then
		for i=1,GetNumRaidMembers() do
			local group = select(3, GetRaidRosterInfo(i))
			local unit = raidLookup[i]
			if UnitIsUnit(unit, "player") then raidLookup.player = group end
			raidLookup[unit] = group
		end
	end
end

function Buffs:ConfigureButton(button)
	local font = button:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	button.aura = font
end

local backdrop = {
	bgFile = "Interface\\AddOns\\PerfectRaid\\images\\bgFile",
	tile = true, tileSize = 32,
--	edgeFile = "Interface\\AddOns\\PerfectRaid\\images\\edgeFile",
--	edgeSize = 16,
	insets = {
		left = 6,
		right = 6,
--		top = 1,
--		bottom = 1
	},
}

local r,g,b,a
local function OnEnter(frame)
	if not PerfectRaid.db.profile.highlight.mouseover then return end

	if frame.backdropset then
		r,g,b,a = frame:GetBackdropColor()
	end

--	frame:SetBackdropColor(1, 0.84, 0, 0.3)
	frame:SetBackdropColor(0.9, 0.9, 0.9, 0.3)
	frame.backdropset = true
end

local function OnLeave(frame)
	if r then
		frame:SetBackdropColor(r,g,b,a)
	else
		frame:SetBackdropColor(0,0,0,0)
	end

	frame.backdropset = false
	r,g,b,a = nil,nil,nil,nil
end

function Buffs:UpdateButtonLayout(button, options)
	button.aura:ClearAllPoints()

	if options.alignright then
		button.aura:SetPoint("RIGHT", button.leftbox, "RIGHT", -2, 0)
	else
		button.aura:SetPoint("LEFT", button.rightbox, "LEFT", 2, 0)
	end

	button:SetBackdrop(backdrop)
	button:SetBackdropColor(0,0,0,0)

	button:SetScript("OnEnter", OnEnter)
	button:SetScript("OnLeave", OnLeave)
end

function Buffs:ShowButton(button)
	local unit = button:GetAttribute("unit")
	self:UNIT_AURA(nil, unit)
end

local buffs = {}
local buffcache = {}

local work = {}
function Buffs:UNIT_AURA(event, unit)
	if not frames[unit] then return end

	for k,v in pairs(buffcache) do buffcache[k] = nil end

	for i=1,40 do
		local name,rank,texture,count = UnitBuff(unit, i)
		if not name then break end
		buffcache[name] = (buffcache[name] or 0) + 1
	end

	local debuffType
	for i=1,40 do
		local name,rank,texture,count,type = UnitDebuff(unit, i)
		if not name and not type then break end
		buffcache[name] = (buffcache[name] or 0) + 1
		if type and name ~= type then
			buffcache[type] = (buffcache[type] or 0) + 1
			debuffType = type
		end
	end

	for k,v in pairs(work) do work[k] = nil end

	for i,entry in ipairs(buffs) do
		local checkcond = false
		local num = buffcache[entry.buffname]
		if entry.missing then
			if not buffcache[entry.buffname] and not buffcache[entry.groupname or "nil"] then
				checkcond = true
			end
		else
			if buffcache[entry.buffname] or buffcache[entry.groupname or "nil"] then
				checkcond = true
			end
		end

		local class = select(2, UnitClass(unit))
		local conds = self.conditions
		local group = raidLookup[unit]
		if checkcond then
			for i,name in pairs(entry.cond) do
				if conds[name] and conds[name](unit,class,group) then
					if num and num > 1 then
						table.insert(work, entry.colortext .. "(" .. num .. ")")
					else
						table.insert(work, entry.colortext)
					end
				end
			end
		end
	end

	-- Check to see if we need to change the backdrop
	local opt = PerfectRaid.db.profile.highlight
	local r,g,b,a
	if buffcache.Curse and opt.curse then
		r,g,b,a = 0.6,0,1,0.7
	elseif buffcache.Poison and opt.poison then
		r,g,b,a = 0,0.6,0,0.7
	elseif buffcache.Disease and opt.disease then
		r,g,b,a = 0.6,0.4,0,0.7
	elseif buffcache.Magic and opt.magic then
		r,g,b,a = 0.2,0.6,1,0.7
	end

	local status = strjoin(" ", unpack(work))
	for frame in pairs(frames[unit]) do
		frame.aura:SetText(status)
		if r then
			frame:SetBackdropColor(r,g,b,a)
			frame.backdropset = true
		elseif frame.backdropset then
			frame:SetBackdropColor(0,0,0,0)
		end
	end
end

function Buffs:CreateOptions(opt)

	-- Call the highlight options frame creation script
	self:CreateOptions_Highlight(opt)

	self.options = opt
	local options = CreateFrame("Frame", "PROptions_Buffs", PROptions)
	opt:AddOptionsTab(L["Buffs/Debuffs"], options)

	local num_entries = 15
	local scrollframe = opt:CreateListFrame(options, num_entries)

	local update = function()
		local list = PerfectRaid.db.profile.buffs

		local idx,button
		local offset = FauxScrollFrame_GetOffset(scrollframe)
		FauxScrollFrame_Update(scrollframe, #list, 15, 20)
		for i=1,num_entries do
			idx = offset + i
			button = scrollframe.entries[i]
			if idx <= #list then
				local entry = list[idx]
				local display = entry.buffname
				if entry.groupname then
					display = display .. "/"..entry.groupname
				end
				display = display .. " (|cFF"..entry.color..entry.disptext.."|r)"
				button.line1:SetText(display)
				button:Show()
				if options.selected == idx then
					button:SetChecked(true)
				else
					button:SetChecked(false)
				end
			else
				button:Hide()
			end
		end
	end

	scrollframe.update = update

	scrollframe:SetScript("OnVerticalScroll", function()
		FauxScrollFrame_OnVerticalScroll(20, update)
		self:EnableButtons()
	end)
	scrollframe:SetScript("OnShow", function()
		scrollframe.update()
		self:EnableButtons()
	end)

	local postClick = function()
		self:EnableButtons()
	end

	for i,frame in ipairs(scrollframe.entries) do
		frame:SetScript("PostClick", postClick)
	end

	local delete = CreateFrame("Button", "PRBuffs_Delete", options, "PRButtonTemplate")
	delete:SetText(L["Delete"])
	delete:SetPoint("BOTTOMRIGHT", 0, 5)
	delete:SetScript("OnClick", function() self:DeleteEntry() end)
	delete:Show()

	local edit = CreateFrame("Button", "PRBuffs_Edit", options, "PRButtonTemplate")
	edit:SetText(L["Edit"])
	edit:SetPoint("BOTTOMRIGHT", delete, "BOTTOMLEFT", -10, 0)
	edit:SetScript("OnClick", function() self:EditEntry() end)
	edit:Show()

	local add = CreateFrame("Button", "PRBuffs_Add", options, "PRButtonTemplate")
	add:SetText(L["Add"])
	add:SetPoint("BOTTOMRIGHT", edit, "BOTTOMLEFT", -10, 0)
	add:SetScript("OnClick", function() self:AddEntry() end)
	add:Show()

	self:CreateEditFrame(options)
end


function Buffs:CreateEditFrame(parent)
	local frame = CreateFrame("Frame", "PROptions_Buffs_Edit", PROptions)
	local name = "PROptions_Buffs_Edit"
--	frame:SetPoint("TOPLEFT", 15, -25)
--	frame:SetPoint("BOTTOMRIGHT", -15, 15)
	frame:SetAllPoints(PROptions_Buffs)
	frame:SetFrameLevel(frame:GetFrameLevel() + 1)
	frame:Hide()

	local buffname = CreateFrame("EditBox", name.."BuffName", frame, "InputBoxTemplate")
	local font = buffname:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	font:SetText(L["Buff Name:"])
	font:SetPoint("BOTTOMLEFT", buffname, "TOPLEFT", 0, 3)
	buffname:SetPoint("TOPLEFT", 0, -10)
	buffname:SetAutoFocus(nil)
	buffname:SetWidth(180)
	buffname:SetHeight(20)
	buffname:Show()
	frame.buffname = buffname

	local groupname = CreateFrame("EditBox", name.."GroupName", frame, "InputBoxTemplate")
	local font = groupname:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	font:SetText(L["Group Buff Name:"])
	font:SetPoint("BOTTOMLEFT", groupname, "TOPLEFT", 0, 3)
	groupname:SetPoint("TOPLEFT", 220, -10)
	groupname:SetAutoFocus(nil)
	groupname:SetWidth(180)
	groupname:SetHeight(20)
	groupname:Show()
	frame.groupname = groupname

	local disptext = CreateFrame("EditBox", name.."DispText", frame, "InputBoxTemplate")
	local font = disptext:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
	font:SetText(L["Display Text:"])
	font:SetPoint("BOTTOMLEFT", disptext, "TOPLEFT", 0, 3)
	disptext:SetPoint("TOPLEFT", 0, -50)
	disptext:SetAutoFocus(nil)
	disptext:SetWidth(180)
	disptext:SetHeight(20)
	disptext:Show()
	frame.disptext = disptext

	-- Color Swatch
	local function colorSwatchCancel()
		local self = ColorPickerFrame.object;
		local r, g, b = self.r, self.g, self.b;
		self.normalTexture:SetVertexColor(r, g, b);
	end

	local function colorSwatchColor()
		local self = ColorPickerFrame.object;
		local r, g, b = ColorPickerFrame:GetColorRGB();
		self.normalTexture:SetVertexColor(r, g, b);
		self.color[1] = r
		self.color[2] = g
		self.color[3] = b
		disptext:SetTextColor(r,g,b)
	end

	local function colorSwatchOpacity()
		local self = ColorPickerFrame.object;
		local a = OpacitySliderFrame:GetValue();
	end

	local function colorSwatchShow(self)
		local r, g, b, a;
		self.color = self.color or {1,1,1}

		local color = self.color;
		if ( color ) then
			r, g, b, a = unpack(color);
		end

		self.r, self.g, self.b = r, g, b
		self.opacityFunc = colorSwatchOpacity;
		self.swatchFunc = colorSwatchColor;
		self.cancelFunc = colorSwatchCancel;

		ColorPickerFrame.object = self;
		UIDropDownMenuButton_OpenColorPicker(self);
		ColorPickerFrame:SetFrameStrata("TOOLTIP");
		ColorPickerFrame:Raise();
	end

	local function colorSwatchOnClick(self)
		CloseMenus();
		colorSwatchShow(self);
	end

	local function colorSwatchOnEnter(self)
		self.bg:SetVertexColor(1, 0.82, 0);
	end

	local function colorSwatchOnLeave(self)
		self.bg:SetVertexColor(1, 1, 1);
	end

	local swatch = CreateFrame("Button", "PRColorSelect", frame);
	swatch:SetHeight(20) swatch:SetWidth(20)
	swatch:SetPoint("LEFT", disptext, "RIGHT", 5, 0)
	local bg = swatch:CreateTexture(nil, "BACKGROUND");
	local normalTexture = swatch:CreateTexture(nil, "ARTWORK");
	frame.color = swatch

	normalTexture:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch");
	normalTexture:SetAllPoints(swatch);
	swatch:SetNormalTexture(normalTexture);
	bg:SetTexture(.2,.2,.2);
	bg:SetPoint("TOPLEFT", swatch, 1, -1);
	bg:SetPoint("BOTTOMRIGHT", swatch, 0, 1);

	normalTexture:SetVertexColor(1,1,1)

	swatch.bg, swatch.normalTexture = bg, normalTexture;
	swatch.object, swatch.hasAlpha = self, 1

	swatch:SetScript("OnLeave", colorSwatchOnLeave);
	swatch:SetScript("OnEnter", colorSwatchOnEnter);
	swatch:SetScript("OnClick", colorSwatchOnClick);

	buffname:SetScript("OnTabPressed", function() if IsShiftKeyDown() then disptext:SetFocus() else groupname:SetFocus() end end)
	groupname:SetScript("OnTabPressed", function() if IsShiftKeyDown() then buffname:SetFocus() else disptext:SetFocus() end end)
	disptext:SetScript("OnTabPressed", function() if IsShiftKeyDown() then groupname:SetFocus() else buffname:SetFocus() end end)

	local function makeCheck(value)
		local button = CreateFrame("CheckButton", "PRBuffCond_"..value, PROptions_Buffs_Edit, "PRCheckTemplate")
		button.Label:SetText(value)
		button.value = value
		return button
	end

	PROptions_Buffs_Edit.checks = {}
	local checks = PROptions_Buffs_Edit.checks

	-- Build condition checkboxes

	checks[1] = makeCheck(self.conditions[1])
	checks[1]:SetPoint("TOPLEFT", disptext, "BOTTOMLEFT", 0, -20)
	checks[1]:Show()

	for i=2,6 do
		checks[i] = makeCheck(self.conditions[i])
		checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
		checks[i]:Show()
	end

	checks[7] = makeCheck(self.conditions[7])
	checks[7]:SetPoint("TOPLEFT", checks[1], "BOTTOMLEFT", 0, -10)
	checks[7]:Show()

	for i=8,12 do
		checks[i] = makeCheck(self.conditions[i])
		checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
		checks[i]:Show()
	end

	checks[13] = makeCheck(self.conditions[13])
	checks[13]:SetPoint("TOPLEFT", checks[7], "BOTTOMLEFT", 0, -10)
	checks[13]:Show()

	for i=14,18 do
		checks[i] = makeCheck(self.conditions[i])
		checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
		checks[i]:Show()
	end

	checks[19] = makeCheck(self.conditions[19])
	checks[19]:SetPoint("TOPLEFT", checks[13], "BOTTOMLEFT", 0, -10)
	checks[19]:Show()

	for i=20,21 do
		checks[i] = makeCheck(self.conditions[i])
		checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
		checks[i]:Show()
	end

	local cancel = CreateFrame("Button", "PRBuffs_EditCancel", PROptions_Buffs_Edit, "PRButtonTemplate")
	cancel:SetText(L["Cancel"])
	cancel:SetPoint("BOTTOMRIGHT", 0, 5)
	cancel:SetScript("OnClick", function() self:CancelEntry() end)
	cancel:Show()

	local save = CreateFrame("Button", "PRBuffs_EditSave", PROptions_Buffs_Edit, "PRButtonTemplate")
	save:SetText(L["Save"])
	save:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -10, 0)
	save:SetScript("OnClick", function() self:SaveEntry() end)
	save:Show()

	local missing = CreateFrame("CheckButton", "PRBuffs_Missing", PROptions_Buffs_Edit, "PRCheckTemplate")
	missing.Label:SetText(L["Only show if this buff is missing"])
	missing:SetPoint("BOTTOMLEFT", 0, 10)
	missing:Show()
	frame.missing = missing

	local disabled = CreateFrame("CheckButton", "PRBuffs_Disabled", PROptions_Buffs_Edit, "PRCheckTemplate")
	disabled.Label:SetText(L["Do not check this buff (Disable)"])
	disabled:SetPoint("BOTTOMLEFT", missing, "TOPLEFT", 0, 10)
	disabled:Show()
	frame.disabled = disabled

	local dropdown = CreateFrame("Frame", "PRBuffs_Dropdown", PROptions_Buffs_Edit, "UIDropDownMenuTemplate")
	dropdown:SetID(1)
	dropdown:SetPoint("BOTTOMRIGHT", -115, 30)
	dropdown:SetScript("OnShow", function() self:DropDown_OnShow() end)

	PRBuffs_DropdownButton:SetScript("OnClick", function() ToggleDropDownMenu(nil, nil, PRBuffs_Dropdown, "cursor") end)
	UIDropDownMenu_SetText(L["Auto-fill Default"], dropdown)
end

function Buffs:FillEntry(entry)
	local options = PROptions_Buffs_Edit
	options.buffname:SetText(entry.buffname)
	options.groupname:SetText(entry.groupname or "")
	options.disptext:SetText(entry.disptext)
	options.disptext:SetTextColor(utils.HexToRGBPerc(entry.color))
	PRColorSelect.normalTexture:SetVertexColor(utils.HexToRGBPerc(entry.color))

	local cond = {string.split(",", entry.conds)}
	for k,v in ipairs(cond) do
		cond[v] = true
	end
	for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
		if cond[button.value] then
			button:SetChecked(true)
		else
			button:SetChecked(false)
		end
	end

	options.missing:SetChecked(entry.missing)
	options.disabled:SetChecked(entry.disabled)
end

function Buffs:EditEntry()
	local scrollframe = PROptions_BuffsScrollFrame
	local offset = FauxScrollFrame_GetOffset(scrollframe)
	local selected = PROptions_Buffs.selected
	local entry = PerfectRaid.db.profile.buffs[selected]

	local options = PROptions_Buffs_Edit
	options.editEntry = entry
	self.options:FadeOut(PROptions_Buffs)
	self.options:FadeIn(options)
	self:FillEntry(entry)
end

function Buffs:AddEntry()
	local options = PROptions_Buffs_Edit
	self.options:FadeOut(PROptions_Buffs)
	self.options:FadeIn(options)
	options.buffname:SetText("")
	options.groupname:SetText("")
	options.disptext:SetText("")
	options.disptext:SetTextColor(1,1,1)
	PRColorSelect.normalTexture:SetVertexColor(1,1,1)

	for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
		button:SetChecked(false)
	end
	options.missing:SetChecked(false)
	options.disabled:SetChecked(false)
	options.buffname:SetFocus()
end

function Buffs:DeleteEntry()
	local scrollframe = PROptions_BuffsScrollFrame
	local offset = FauxScrollFrame_GetOffset(scrollframe)
	local selected = PROptions_Buffs.selected
	local idx = offset + selected
	table.remove(PerfectRaid.db.profile.buffs, idx)
	PROptions_Buffs.selected = nil
	scrollframe.update()
	self:EnableButtons()
	self:UpdateBuffTable()
end

function Buffs:UpdateBuffTable()
	for k,v in pairs(buffs) do buffs[k] = nil end

	for idx,entry in ipairs(PerfectRaid.db.profile.buffs) do
		if not entry.disabled then
			local tbl = {}
			tbl.buffname = entry.buffname
			tbl.groupname = entry.groupname
			tbl.colortext = "|cFF"..entry.color..entry.disptext.."|r"
			tbl.missing = entry.missing
			tbl.cond = {string.split(",", entry.conds)}
			table.insert(buffs, tbl)
		end
	end

	for unit in pairs(frames) do
		self:UNIT_AURA(nil, unit)
	end
end

function Buffs:SaveEntry()
	local frame = PROptions_Buffs_Edit

	local buffname = frame.buffname:GetText()
	local groupname = frame.groupname:GetText()
	local disptext = frame.disptext:GetText()

	local err
	if buffname == "" then
		err = "You must supply a buff name"
	elseif disptext == "" then
		err = "You must supply a display text"
	end

	if err then
		StaticPopupDialogs["PR_BUFF_SAVE_ERROR"].text = err
		StaticPopup_Show("PR_BUFF_SAVE_ERROR")
		return
	end

	if groupname == "" then
		groupname = nil
	end

	local options = PROptions_Buffs_Edit
	local entry = options.editEntry or {}

	entry.buffname = buffname
	entry.groupname = groupname
	entry.disptext = disptext

	local work = {}
	for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
		if button:GetChecked() then
			table.insert(work, button.value)
		end
	end

	local conds = strjoin(",", unpack(work))
	entry.conds = conds
	entry.missing = frame.missing:GetChecked()
	entry.disabled = frame.disabled:GetChecked()

	local color = utils.RGBPercToHex(frame.disptext:GetTextColor())
	entry.color = color
	if not options.editEntry then
		table.insert(PerfectRaid.db.profile.buffs, entry)
	end

	options.editEntry = nil

	self:CancelEntry()
	PROptions_BuffsScrollFrame.update()
	self:UpdateBuffTable()
end

function Buffs:CancelEntry()
	local options = PROptions_Buffs_Edit
	self.options:FadeOut(options)
	options.editEntry = nil
	self.options:FadeIn(PROptions_Buffs)
end

function Buffs:EnableButtons()
	local selected = PROptions_Buffs.selected
	if selected then
		PRBuffs_Edit:Enable()
		PRBuffs_Delete:Enable()
	else
		PRBuffs_Edit:Disable()
		PRBuffs_Delete:Disable()
	end
end

Buffs.conditions = {
	["All"] = function(u,c,g) return true end,
	["Warrior"] = function(u,c,g) return c == "WARRIOR" end,
	["Priest"] = function(u,c,g) return c == "PRIEST" end,
	["Druid"] = function(u,c,g) return c == "DRUID" end,
	["Paladin"] = function(u,c,g) return c == "PALADIN" end,
	["Shaman"] = function(u,c,g) return c == "SHAMAN" end,
	["Hunter"] = function(u,c,g) return c == "HUNTER" end,
	["Rogue"] = function(u,c,g) return c == "ROGUE" end,
	["Warlock"] = function(u,c,g) return c == "WARLOCK" end,
	["Mage"] = function(u,c,g) return c == "MAGE" end,
	["Mana"] = function(u,c,g) return c == "DRUID" or c == "PRIEST" or c == "PALADIN" or c == "SHAMAN" or c == "MAGE" or c == "WARLOCK" or c == "HUNTER" end,
	["Healer"] = function(u,c,g) return c == "PRIEST" or c == "SHAMAN" or c == "DRUID" or c == "PALADIN" end,
	["Group 1"] = function(u,c,g) return g == 1 end,
	["Group 2"] = function(u,c,g) return g == 2 end,
	["Group 3"] = function(u,c,g) return g == 3 end,
	["Group 4"] = function(u,c,g) return g == 4 end,
	["Group 5"] = function(u,c,g) return g == 5 end,
	["Group 6"] = function(u,c,g) return g == 6 end,
	["Group 7"] = function(u,c,g) return g == 7 end,
	["Group 8"] = function(u,c,g) return g == 8 end,
	["MyGroup"] = function(u,c,g) return g == raidLookup.player end,
}

local work = {}
for k,v in pairs(Buffs.conditions) do
	table.insert(work, k)
end
table.sort(work)

for k,v in ipairs(work) do
	Buffs.conditions[k] = v
end

StaticPopupDialogs["PR_BUFF_SAVE_ERROR"] = {
	text = "",
	button1 = TEXT(OKAY),
	OnAccept = function()
	end,
	timeout = 0,
	hideOnEscape = 1
}

local click_func = function() Buffs:DropDown_OnClick() end
local init_func = function() Buffs:DropDown_Initialize() end

function Buffs:DropDown_Initialize()
    local info = {}

    for k,v in pairs(self.defaults) do
        info = {}
        info.text = string.format("%s (|cFF%s%s|r)", v.buffname, v.color, v.disptext)
        info.value = v
        info.func = click_func
        UIDropDownMenu_AddButton(info)
	end
end

function Buffs:DropDown_OnClick()
	local entry = this.value
	self:FillEntry(entry)
end

function Buffs:DropDown_OnShow(this)
	table.sort(self.defaults, function(a,b) return a.buffname < b.buffname end)
	UIDropDownMenu_Initialize(PRBuffs_Dropdown, init_func);
end

function Buffs:AddDefaultBuff(profile, entry)
	local tbl = {}
	for k,v in pairs(entry) do tbl[k] = v end
	tbl.disabled = nil
	table.insert(profile, tbl)
end

local options
function Buffs:CreateOptions_Highlight(opt)
	options = CreateFrame("Frame", "PROptions_Highlight", PROptions)

	opt:AddOptionsTab("Highlight", options)

	options.widgets = {}

	local check = CreateFrame("CheckButton", "PRHighlight_Mouseover", options, "PRCheckTemplate")
	check.Label:SetText(L["Highlight on mouseover"])
	table.insert(options.widgets, check)

	local check = CreateFrame("CheckButton", "PRHighlight_Disease", options, "PRCheckTemplate")
	check.Label:SetText(L["Highlight when diseased"])
	table.insert(options.widgets, check)

	local check = CreateFrame("CheckButton", "PRHighlight_Curse", options, "PRCheckTemplate")
	check.Label:SetText(L["Highlight when cursed"])
	table.insert(options.widgets, check)

	local check = CreateFrame("CheckButton", "PRHighlight_Magic", options, "PRCheckTemplate")
	check.Label:SetText(L["Highlight when magic debuffed"])
	table.insert(options.widgets, check)

	local check = CreateFrame("CheckButton", "PRHighlight_Poison", options, "PRCheckTemplate")
	check.Label:SetText(L["Highlight when poisoned"])
	table.insert(options.widgets, check)

	local cancel = CreateFrame("Button", "PRHighlight_Cancel", options, "PRButtonTemplate")
	cancel:SetText(L["Cancel"])
	cancel:SetPoint("BOTTOMRIGHT", 0, 5)
	cancel:SetScript("OnClick", function() options:CancelOptions() end)
	cancel:Show()

	local save = CreateFrame("Button", "PRHighlight_Save", options, "PRButtonTemplate")
	save:SetText(L["Save"])
	save:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -10, 0)
	save:SetScript("OnClick", function() options:SaveOptions() end)
	save:Show()

	function options:SaveOptions()
		local mouseover = PRHighlight_Mouseover:GetChecked()
		local disease = PRHighlight_Disease:GetChecked()
		local curse = PRHighlight_Curse:GetChecked()
		local magic = PRHighlight_Magic:GetChecked()
		local poison = PRHighlight_Poison:GetChecked()

		PerfectRaid.db.profile.highlight.mouseover = mouseover
		PerfectRaid.db.profile.highlight.disease = disease
		PerfectRaid.db.profile.highlight.curse = curse
		PerfectRaid.db.profile.highlight.magic = magic
		PerfectRaid.db.profile.highlight.poison = poison
		-- Trigger update here
		for unit in pairs(frames) do
			Buffs:UNIT_AURA(nil, unit)
		end
	end

	function options:CancelOptions()
		local opt = PerfectRaid.db.profile.highlight

		PRHighlight_Mouseover:SetChecked(opt.mouseover)
		PRHighlight_Disease:SetChecked(opt.disease)
		PRHighlight_Curse:SetChecked(opt.curse)
		PRHighlight_Magic:SetChecked(opt.magic)
		PRHighlight_Poison:SetChecked(opt.poison)

		-- Trigger update here
		for unit in pairs(frames) do
			Buffs:UNIT_AURA(nil, unit)
		end
	end

	-- Force an update when tab is clicked
	options:SetScript("OnShow", options.CancelOptions)

	for idx,widget in ipairs(options.widgets) do
		widget:Show()
		if idx == 1 then
			widget:SetPoint("TOPLEFT", 0, 0)
		else
			widget:SetPoint("TOPLEFT", options.widgets[idx - 1], "BOTTOMLEFT", 0, -15)
		end
	end
end

local class = select(2, UnitClass("player"))
local race = select(2, UnitRace("player"))

Buffs.defaults = {
	{
		conds = "All",
		buffname = L["Power Word: Fortitude"],
		groupname = L["Prayer of Fortitude"],
		disptext = L["STATUS_FORT"],
		color = "FFFFFF",
		missing = true,
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Power Word: Shield"],
		disptext = L["STATUS_PWS"],
		color = "FFD800",
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Weakened Soul"],
		disptext = L["STATUS_WEAKENEDSOUL"],
		color = "FF5500",
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Renew"],
		disptext = L["STATUS_RENEW"],
		color = "00FF10",
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Shadow Protection"],
		groupname = L["Prayer of Shadow Protection"],
		disptext = L["STATUS_SHADOWPROT"],
		missing = true,
		color = "9900FF",
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Divine Spirit"],
		groupname = L["Prayer of Spirit"],
		disptext = L["STATUS_DIVINESPIRIT"],
		missing = true,
		color = "9900FF",
		disabled = (class ~= "PRIEST"),
	},
	{
		conds = "All",
		buffname = L["Power Infusion"],
		disptext = L["STATUS_POWERINFUSION"],
		color = "00FF33",
	},
	{
		conds = "All",
		buffname = L["Fear Ward"],
		disptext = L["STATUS_FEARWARD"],
		color = "9900FF",
		disabled = (class ~= "PRIEST" and race == "Dwarf"),
	},
	{
		conds = "All",
		buffname = L["Prayer of Mending"],
		disptext = L["STATUS_PRAYERMEND"],
		color = "FFCF7F",
		disabled = (class ~= "PRIEST"),
	},
	-- Druid specific spells
	{
		conds = "All",
		buffname = L["Mark of the Wild"],
		groupname = L["Gift of the Wild"],
		disptext = L["STATUS_MOTW"],
		color = "BC64AA",
		missing = true,
		disabled = (class ~= "DRUID"),
	},
	{
		conds = "All",
		buffname = L["Rejuvenation"],
		disptext = L["STATUS_REJUV"],
		color = "bc64aa",
		disabled = (class ~= "DRUID"),
	},
	{
		conds = "All",
		buffname = L["Lifebloom"],
		disptext = L["STATUS_LIFEBLOOM"],
		color = "50fe37",
		disabled = (class ~= "DRUID"),
	},
	{
		conds = "All",
		buffname = L["Regrowth"],
		disptext = L["STATUS_REGROWTH"],
		color = "00FF10",
		disabled = (class ~= "DRUID"),
	},
	{
		conds = "All",
		buffname = L["Thorns"],
		disptext = L["STATUS_THORNS"],
		color = "aa6644",
		disabled = (class ~= "DRUID"),
	},
	{
		conds = "Mana",
		buffname = L["Innervate"],
		disptext = L["STATUS_INNERVATE"],
		color = "00FF33",
	},
	-- Paladin Buffs
	{
		conds = "Melee",
		buffname = L["Blessing of Might"],
		groupname = L["Greater Blessing of Might"],
		disptext = L["STATUS_BLESSINGMIGHT"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	{
		conds = "Mana",
		buffname = L["Blessing of Wisdom"],
		groupname = L["Greater Blessing of Wisdom"],
		disptext = L["STATUS_BLESSINGWISDOM"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	{
		conds = "NonTank",
		buffname = L["Blessing of Salvation"],
		groupname = L["Greater Blessing of Salvation"],
		disptext = L["STATUS_BLESSINGSALVATION"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	{
		conds = "All",
		buffname = L["Blessing of Light"],
		groupname = L["Greater Blessing of Light"],
		disptext = L["STATUS_BLESSINGLIGHT"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	{
		conds = "All",
		buffname = L["Blessing of Sanctuary"],
		groupname = L["Greater Blessing of Sanctuary"],
		disptext = L["STATUS_BLESSINGSANCTUARY"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	{
		conds = "All",
		buffname = L["Blessing of Kings"],
		groupname = L["Greater Blessing of Kings"],
		disptext = L["STATUS_BLESSINGKINGS"],
		color = "F48CBA",
		missing = true,
		disabled = (class ~= "PALADIN"),
	},
	-- Mage Buffs
	{
		conds = "Mana",
		buffname = L["Arcane Intellect"],
		groupname = L["Arcane Brilliance"],
		disptext = L["STATUS_ARCANEINT"],
		color = "3399FF",
		missing = true,
		disabled = (class ~= "MAGE"),
	},
	-- Warlock Buffs
	{
		conds = "All",
		buffname = L["Soulstone Resurrection"],
		disptext = L["STATUS_SOULSTONE"],
		color = "CA21FF",
	},
	-- Misc Debuffs
	{
		conds = "All",
		buffname = L["Mortal Strike"],
		disptext = L["STATUS_MORTALSTRIKE"],
		color = "FF1111",
	},
	-- Debuffs.  These should not be localized.
	{
		conds = "All",
		buffname = "Curse",
		disptext = L["STATUS_CURSE"],
		color = "9900FF",
		disabled = (class ~= "MAGE" and class ~= "DRUID")
	},
	{
		conds = "All",
		buffname = "Poison",
		disptext = L["STATUS_POISON"],
		color = "009900",
		disabled = (class ~= "PALADIN" and class ~= "DRUID" and class ~= "SHAMAN")
	},
	{
		conds = "All",
		buffname = "Disease",
		disptext = L["STATUS_DISEASE"],
		color = "996600",
		disabled = (class ~= "PRIEST" and class ~= "PALADIN" and class ~= "SHAMAN")
	},
	{
		conds = "All",
		buffname = "Magic",
		disptext = L["STATUS_MAGIC"],
		color = "3399FF",
		disabled = (class ~= "PRIEST" and class ~= "PALADIN")
	},
}