if not ShockAndAwe then return end

local L = LibStub("AceLocale-3.0"):GetLocale("ShockAndAwe")
local media = LibStub:GetLibrary("LibSharedMedia-3.0");
local LBF = LibStub("LibButtonFacade", true)
local LBFgroup = nil
local C = ShockAndAwe.constants -- Defined in ShockAndAwe LUA no locale needed.
local _, _, _, clientVersion = GetBuildInfo()

--if LBF then
--	local LBFgroup = LBF:Group("ShockAndAwe")
--end
ShockAndAwe.PriorityFrame = CreateFrame("Button", "SAA_PriorityFrame", UIParent)
ShockAndAwe.PriorityFrame.cooldown = CreateFrame("Cooldown", "SAA_PriorityFrameCooldown", ShockAndAwe.PriorityFrame)

---------------------------
-- Local Variables
---------------------------

ShockAndAwe.priorityTable = {}
ShockAndAwe.priorityTable.name = {}
ShockAndAwe.priorityTable.icon = {}
ShockAndAwe.priorityTable.test = {}

--------------------------
--  Helper Functions
--------------------------
-- returns : true if spellname is available in less than priority.cooldown
--                 or if spellname is currently activated
--           , remaining cooldown, 0 if ready to be cast
function ShockAndAwe:SpellAvailable(spellname)
	if self.db.char.priority.hideImmune and self:IsTargetImmune(spellname) then
		return false
	end
	local start, duration = GetSpellCooldown(spellname)
	if start then
		local timeleft = start + duration - GetTime()
		return timeleft <= self.db.char.priority.cooldown, duration, timeleft
	end
	return false, 999
end

function ShockAndAwe:GCDAvailable()
	local startTime, gcdDuration = GetSpellCooldown(C["Lightning Shield"])
	local gcdTime = startTime + gcdDuration - GetTime()
	return gcdTime <= ShockAndAwe.db.char.priority.cooldown 
end

function ShockAndAwe:GetDebuffInfo(debuff)
	local index = 1
	while UnitDebuff("target", index) do
		local name, _, _, count, _, _, debuffExpires, unitCaster = UnitDebuff("target", index)
		local isMine = unitCaster == "player" 
		if name == debuff and isMine then 
			local duration = debuffExpires - GetTime()
			return duration > ShockAndAwe.db.char.priority.cooldown, duration, count, debuffExpires
		end
		index = index + 1
	end
	return false, 0, 0, 0
end

function ShockAndAwe:GetBuffInfo(buff)
	local index = 1
	while UnitBuff("player", index) do
		local name, _, _, count, _, _, buffExpires = UnitBuff("player", index)
		if name == buff then 
			local duration = buffExpires - GetTime()
			return duration > ShockAndAwe.db.char.priority.cooldown, duration, count
		end
		index = index + 1
	end
	return false, 0, 0
end

function ShockAndAwe:IsTargetImmune(spell)
	target = UnitName("target") or ""
	if self.db.char.immuneTargets[target.."_"..spell] then
		return true
	end
	return false
end

function ShockAndAwe:FireTotemNeeded(spell)
	if ShockAndAwe:GCDAvailable() then
		-- only bother checking for totem availabilty if we have a GCD
		local _, totemname, start, duration = GetTotemInfo(1)
		if totemname == nil or totemname == "" then -- no fire totem deployed so recommend it be dropped
			return true
		end
		if start and strmatch(totemname, spell) then
			local timeleft = start + duration - GetTime()
			return timeleft <= ShockAndAwe.db.char.priority.cooldown, duration
		end
	end
	return false, 999
end

------------------
-- Priorities
------------------

ShockAndAwe.priorityTable.name["sr"] = C["Shamanistic Rage"]
ShockAndAwe.priorityTable.icon["sr"] = C["Shamanistic Rage Icon"]
ShockAndAwe.priorityTable.test["sr"] = 
	function () 
		return ShockAndAwe:SpellAvailable(C["Shamanistic Rage"])
	end 

ShockAndAwe.priorityTable.name["sr_boss"] = L["Shamanistic Rage on Boss"]
ShockAndAwe.priorityTable.icon["sr_boss"] = C["Shamanistic Rage Icon"]
ShockAndAwe.priorityTable.test["sr_boss"] = 
	function () 
		return ShockAndAwe:SpellAvailable(C["Shamanistic Rage"]) and UnitClassification("target") == "worldboss"
	end 

ShockAndAwe.priorityTable.name["sw"] = C["Feral Spirit"]
ShockAndAwe.priorityTable.icon["sw"] = C["Feral Spirit Icon"]
ShockAndAwe.priorityTable.test["sw"] = 
	function () 
		return ShockAndAwe:SpellAvailable(C["Feral Spirit"])
	end 

ShockAndAwe.priorityTable.name["sw_boss"] = L["Feral Spirit on Boss"]
ShockAndAwe.priorityTable.icon["sw_boss"] = C["Feral Spirit Icon"]
ShockAndAwe.priorityTable.test["sw_boss"] = 
	function () 
		return ShockAndAwe:SpellAvailable(C["Feral Spirit"]) and UnitClassification("target") == "worldboss"
	end 

ShockAndAwe.priorityTable.name["mw5_lb"] = L["MW5 Lightning Bolt"]
ShockAndAwe.priorityTable.icon["mw5_lb"] = C["Lightning Bolt Icon"]
ShockAndAwe.priorityTable.test["mw5_lb"] = 
	function () 
		return ShockAndAwe.db.char.msstacks == 5 
	end 

ShockAndAwe.priorityTable.name["mw4_lb"] = L["MW4 Lightning Bolt"]
ShockAndAwe.priorityTable.icon["mw4_lb"] = C["Lightning Bolt Icon"]
ShockAndAwe.priorityTable.test["mw4_lb"] = 
	function () 
		return ShockAndAwe.db.char.msstacks >= 4 
	end 

ShockAndAwe.priorityTable.name["mw3_lb"] = L["MW3 Lightning Bolt"]
ShockAndAwe.priorityTable.icon["mw3_lb"] = C["Lightning Bolt Icon"]
ShockAndAwe.priorityTable.test["mw3_lb"] = 
	function () 
		return ShockAndAwe.db.char.msstacks >= 3 
	end 

ShockAndAwe.priorityTable.name["mw5_cl"] = L["MW5 Chain Lightning"]
ShockAndAwe.priorityTable.icon["mw5_cl"] = C["Chain Lightning Icon"]
ShockAndAwe.priorityTable.test["mw5_cl"] = 
	function () 
		return ShockAndAwe.db.char.msstacks == 5 and ShockAndAwe:SpellAvailable(C["Chain Lightning"])
	end 

ShockAndAwe.priorityTable.name["mw4_cl"] = L["MW4 Chain Lightning"]
ShockAndAwe.priorityTable.icon["mw4_cl"] = C["Chain Lightning Icon"]
ShockAndAwe.priorityTable.test["mw4_cl"] = 
	function () 
		return ShockAndAwe.db.char.msstacks >= 4 and ShockAndAwe:SpellAvailable(C["Chain Lightning"])
	end 

ShockAndAwe.priorityTable.name["mw3_cl"] = L["MW3 Chain Lightning"]
ShockAndAwe.priorityTable.icon["mw3_cl"] = C["Chain Lightning Icon"]
ShockAndAwe.priorityTable.test["mw3_cl"] = 
	function () 
		return ShockAndAwe.db.char.msstacks >= 3 and ShockAndAwe:SpellAvailable(C["Chain Lightning"])
	end 

ShockAndAwe.priorityTable.name["ss"] = C["Stormstrike"]
ShockAndAwe.priorityTable.icon["ss"] = C["Stormstrike Icon"]
ShockAndAwe.priorityTable.test["ss"] =  
	function () 
		return ShockAndAwe:SpellAvailable(C["Stormstrike"])
	end 

ShockAndAwe.priorityTable.name["ss_0"] = L["Stormstrike if no debuff"]
ShockAndAwe.priorityTable.icon["ss_0"] = C["Stormstrike Icon"]
ShockAndAwe.priorityTable.test["ss_0"] =  
	function () 
		return ShockAndAwe:SpellAvailable(C["Stormstrike"]) and not ShockAndAwe:GetDebuffInfo(C["Stormstrike"])
	end 

ShockAndAwe.priorityTable.name["es"] = C["Earth Shock"]
ShockAndAwe.priorityTable.icon["es"] = C["Earth Shock Icon"]
ShockAndAwe.priorityTable.test["es"] =  
	function () 
		return ShockAndAwe:SpellAvailable(C["Earth Shock"])
	end 

ShockAndAwe.priorityTable.name["es_ss"] = L["Earth Shock if SS"]
ShockAndAwe.priorityTable.icon["es_ss"] = C["Earth Shock Icon"]
ShockAndAwe.priorityTable.test["es_ss"] =  
	function () 
		return ShockAndAwe:GetDebuffInfo(C["Stormstrike"]) and ShockAndAwe:SpellAvailable(C["Earth Shock"])
	end 

ShockAndAwe.priorityTable.name["fs"] = C["Flame Shock"]
ShockAndAwe.priorityTable.icon["fs"] = C["Flame Shock Icon"]
ShockAndAwe.priorityTable.test["fs"] =  
	function () 
		local debuffPresent, duration = ShockAndAwe:GetDebuffInfo(C["Flame Shock"])
		local ticksLeft = 6 * duration / (ShockAndAwe.db.char.priority.FSDotMax or 18)
		return (not debuffPresent or ticksLeft <= ShockAndAwe.db.char.priority.fsticksleft) and ShockAndAwe:SpellAvailable(C["Flame Shock"]) 
	end

ShockAndAwe.priorityTable.name["fs_boss"] = L["Flame Shock on Boss"]
ShockAndAwe.priorityTable.icon["fs_boss"] = C["Flame Shock Icon"]
ShockAndAwe.priorityTable.test["fs_boss"] =  
	function () 
		local debuffPresent, duration = ShockAndAwe:GetDebuffInfo(C["Flame Shock"])
		local ticksLeft = 6 * duration / (ShockAndAwe.db.char.priority.FSDotMax or 18)
		return (not debuffPresent or ticksLeft <= ShockAndAwe.db.char.priority.fsticksleft) and ShockAndAwe:SpellAvailable(C["Flame Shock"]) and UnitClassification("target") == "worldboss"
	end 

ShockAndAwe.priorityTable.name["fn"] = C["Fire Nova"]
ShockAndAwe.priorityTable.icon["fn"] = C["Fire Nova Icon"]
ShockAndAwe.priorityTable.test["fn"] =  
	function () 
		local _, totemname = GetTotemInfo(1)
		if not totemname or totemname == "" then -- no fire totem deployed so cannot use Fire Nova
			return false
		end
		return ShockAndAwe:SpellAvailable(C["Fire Nova"])
	end 

ShockAndAwe.priorityTable.name["fe"] = C["Fire Elemental Totem"]
ShockAndAwe.priorityTable.icon["fe"] = C["Fire Elemental Totem Icon"]
ShockAndAwe.priorityTable.test["fe"] =  
	function () 
		return ShockAndAwe:FireTotemNeeded(C["Fire Elemental Totem"]) and ShockAndAwe:SpellAvailable(C["Fire Elemental Totem"]) 
	end 

ShockAndAwe.priorityTable.name["fe_boss"] = L["Fire Elemental on Boss"]
ShockAndAwe.priorityTable.icon["fe_boss"] = C["Fire Elemental Totem Icon"]
ShockAndAwe.priorityTable.test["fe_boss"] =  
	function () 
		return ShockAndAwe:FireTotemNeeded(C["Fire Elemental Totem"]) and ShockAndAwe:SpellAvailable(C["Fire Elemental Totem"]) and UnitClassification("target") == "worldboss"
	end 
	
ShockAndAwe.priorityTable.name["ll"] = C["Lava Lash"]
ShockAndAwe.priorityTable.icon["ll"] = C["Lava Lash Icon"]
ShockAndAwe.priorityTable.test["ll"] =  
	function () 
		return ShockAndAwe:SpellAvailable(C["Lava Lash"])
	end 
	
ShockAndAwe.priorityTable.name["ll_qe"] = L["Lava Lash if no QE"]
ShockAndAwe.priorityTable.icon["ll_qe"] = C["Lava Lash Icon"]
ShockAndAwe.priorityTable.test["ll_qe"] =  
	function () 
		return not ShockAndAwe:GetBuffInfo(C["Volcanic Fury"]) and ShockAndAwe:SpellAvailable(C["Lava Lash"]) and ShockAndAwe:QuakingEarthEquipped()
	end 
	
ShockAndAwe.priorityTable.name["st"] = C["Searing Totem"]
ShockAndAwe.priorityTable.icon["st"] = C["Searing Totem Icon"]
ShockAndAwe.priorityTable.test["st"] =  
	function () 
		return ShockAndAwe:FireTotemNeeded(C["Searing Totem"]) and ShockAndAwe:SpellAvailable(C["Searing Totem"])
	end 

ShockAndAwe.priorityTable.name["mt"] = C["Magma Totem"]
ShockAndAwe.priorityTable.icon["mt"] = C["Magma Totem Icon"]
ShockAndAwe.priorityTable.test["mt"] =  
	function () 
		local timeleft = ShockAndAwe.db.char.priority.magmatime - GetTime()
		return (ShockAndAwe:FireTotemNeeded(C["Magma Totem"]) and (ShockAndAwe:SpellAvailable(C["Magma Totem"])) or timeleft < 2 * ShockAndAwe.db.char.priority.magmaticks)
	end 

ShockAndAwe.priorityTable.name["mt_0"] = L["Magma Totem if expired"]
ShockAndAwe.priorityTable.icon["mt_0"] = C["Magma Totem Icon"]
ShockAndAwe.priorityTable.test["mt_0"] =  
	function () 
		return ShockAndAwe:FireTotemNeeded(C["Magma Totem"]) and ShockAndAwe:SpellAvailable(C["Magma Totem"])
	end

ShockAndAwe.priorityTable.name["ls_0"] = L["Lightning Shield if expired"]
ShockAndAwe.priorityTable.icon["ls_0"] = C["Lightning Shield Icon"]
ShockAndAwe.priorityTable.test["ls_0"] =  
	function () 
		local orbs = ShockAndAwe:GetShieldInfo()
		return orbs == 0 and ShockAndAwe:SpellAvailable(C["Lightning Shield"])
	end

ShockAndAwe.priorityTable.name["mw5_hw"] = L["MW5 Healing Wave"]
ShockAndAwe.priorityTable.test["mw5_hw"] = 
	function () 
		if ShockAndAwe.db.char.priority.chingroup == true and GetNumPartyMembers() > 0 then
			ShockAndAwe.priorityTable.icon["mw5_hw"] = C["Chain Heal Icon"]
		else
			ShockAndAwe.priorityTable.icon["mw5_hw"] = C["Healing Wave Icon"]
		end
		local healthpercent = 100 * UnitHealth("player") / UnitHealthMax("player")
		return ShockAndAwe.db.char.msstacks == 5 and healthpercent <= ShockAndAwe.db.char.priority.hwhealth
	end
	
ShockAndAwe.priorityTable.name["mw4_hw"] = L["MW5 Healing Wave"]
ShockAndAwe.priorityTable.test["mw4_hw"] = 
	function () 
		if ShockAndAwe.db.char.priority.chingroup == true and GetNumPartyMembers() > 0 then
			ShockAndAwe.priorityTable.icon["mw4_hw"] = C["Chain Heal Icon"]
		else
			ShockAndAwe.priorityTable.icon["mw4_hw"] = C["Healing Wave Icon"]
		end
		local healthpercent = 100 * UnitHealth("player") / UnitHealthMax("player")
		return ShockAndAwe.db.char.msstacks >= 4 and healthpercent <= ShockAndAwe.db.char.priority.hwhealth
	end
	
ShockAndAwe.priorityTable.name["shield"] = C["Water Shield"] .. "/" .. C["Lightning Shield"]
ShockAndAwe.priorityTable.test["shield"] = 
	function ()
		local orbs, shield, shieldExpires = ShockAndAwe:GetShieldInfo()
		local timeleft = shieldExpires - GetTime()
		if timeleft <= ShockAndAwe.db.char.priority.cooldown or orbs <= ShockAndAwe.db.char.priority.shieldorbs then
			local manapercent = 100 * UnitMana("player") / UnitManaMax("player")
			if manapercent <= ShockAndAwe.db.char.priority.wsmana then
				ShockAndAwe.priorityTable.icon["shield"] = C["Water Shield Icon"]
				return true
			else
				ShockAndAwe.priorityTable.icon["shield"] = C["Lightning Shield Icon"]
				return true
			end
		else
			return false
		end 
	end

ShockAndAwe.priorityTable.name["none"] = L["None"]
_, _, ShockAndAwe.priorityTable.icon["none"] = "Interface/Tooltips/UI-Tooltip-Background"
ShockAndAwe.priorityTable.test["none"] = function () return false end 

-------------------------------
-- Priority Frame functions
-------------------------------

function ShockAndAwe:SetPriorityBackdrop(icon)
--	self.PriorityFrame.Icon:SetTexture(icon)
	self.PriorityFrame:SetBackdrop({ bgFile = icon,
		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
		tile = false, tileSize = 0, edgeSize = 12,
		insets = { left = 2, right = 2, top = 2, bottom = 2 }
	})
end

function ShockAndAwe:CreatePriorityFrame()
	self.updatePriority = false
	self.PriorityFrame:SetScale(self.db.char.priority.scale)
	self.PriorityFrame:SetFrameStrata("BACKGROUND")
	self.PriorityFrame:SetWidth(self.db.char.priority.fWidth)
	self.PriorityFrame:SetHeight(self.db.char.priority.fHeight)
	self.PriorityFrame.Icon = getglobal("SAA_PriorityFrameIcon")
	self:SetPriorityBackdrop("Interface/Tooltips/UI-Tooltip-Background")
	self.PriorityFrame:SetBackdropColor(0, 0, 0, self.db.char.priority.alpha);
	self.PriorityFrame:SetMovable(true);
	self.PriorityFrame:RegisterForDrag("LeftButton");
	self.PriorityFrame:EnableMouse(false)
	self.PriorityFrame:SetPoint(self.db.char.priority.point, self.db.char.priority.relativeTo, self.db.char.priority.relativePoint, self.db.char.priority.xOffset, self.db.char.priority.yOffset)
	self.PriorityFrame:SetScript("OnDragStart", 
		function()
			self.PriorityFrame:StartMoving();
		end );
	self.PriorityFrame:SetScript("OnDragStop",
		function()
			self.PriorityFrame:StopMovingOrSizing();
			self.PriorityFrame:SetScript("OnUpdate", nil);
			self:FinishedMoving(self.db.char.priority, self.PriorityFrame);
		end );
	self:SetPriorityUpdateScript()
	if not self.PriorityFrame.topText then
		self.PriorityFrame.topText = self.PriorityFrame:CreateFontString(nil, "OVERLAY")
	end
	self.PriorityFrame.topText:SetTextColor(1,1,1,1)
	self.PriorityFrame.topText:SetFont(media:Fetch("font", self.db.char.barfont), self.db.char.barfontsize)
	self.PriorityFrame.topText:SetPoint("TOP", self.PriorityFrame, "TOP", 0, self.db.char.barfontsize + 2)
	self.PriorityFrame.topText:SetText(string.format(L["Next Priority (Set %s)"], self.db.char.priority.groupnumber))
	self.PriorityFrame.cooldown:SetAllPoints(self.PriorityFrame)
	self:CreateComboPointFrames()
	self:CreateInterruptPurgeFrames()
	
	if self.db.char.priority.show and InCombatLockdown() then
		self.PriorityFrame:Show()
	else
		self.PriorityFrame:Hide()
	end
	if self.db.char.priority.titleshow then
		self.PriorityFrame.topText:Show()
	else
		self.PriorityFrame.topText:Hide()
	end
	if LBF and LBFgroup then
		LBFgroup:AddButton(self.PriorityFrame)
	end
end

function ShockAndAwe:ResetPriority()
	self.PriorityFrame:ClearAllPoints()
	self.db.char.priority.point = self.defaults.char.priority.point
	self.db.char.priority.relativeTo = self.defaults.char.priority.relativeTo 
	self.db.char.priority.relativePoint = self.defaults.char.priority.relativePoint
	self.db.char.priority.xOffset = self.defaults.char.priority.xOffset
	self.db.char.priority.yOffset = self.defaults.char.priority.yOffset
	self.db.char.priority.fWidth = self.defaults.char.priority.fWidth
	self.db.char.priority.fHeight = self.defaults.char.priority.fHeight
	self.db.char.priority.scale = self.defaults.char.priority.scale
	self.db.char.priority.option = self.defaults.char.priority.option
	self.PriorityFrame:SetPoint(self.db.char.priority.point, self.db.char.priority.relativeTo, self.db.char.priority.relativePoint, self.db.char.priority.xOffset, self.db.char.priority.yOffset)
	self:CreatePriorityFrame()
	self:Print(L["priority_reset"])
end

function ShockAndAwe:SetPriorityUpdateScript()
	self.PriorityFrame:SetScript("OnUpdate", 
		function()
			if self.updatePriority then
				ShockAndAwe.db.char.priority.previous = ShockAndAwe.db.char.priority.next
				ShockAndAwe:SetNextPriority()
--				if ShockAndAwe.db.char.priority.next ~= ShockAndAwe.db.char.priority.previous or ShockAndAwe:CheckShamanisticRage() then
				ShockAndAwe:SetPriorityIcon(ShockAndAwe.db.char.priority.next) -- always set icon to fix the times where it was getting stuck
--				end
				if ShockAndAwe.db.char.priority.showcooldown then
					local startTime, duration = GetSpellCooldown(C["Lightning Shield"])
					if startTime then
						ShockAndAwe.PriorityFrame.cooldown:SetCooldown(startTime, duration)
					end
				end
			end
		end );
end

function ShockAndAwe:SetPriorityIcon(priority)
	--self:DebugPrint("setting icon to "..priority)
	if InCombatLockdown() or priority == "none" then
		local icon = self.priorityTable.icon[priority]
		if self:CheckWindShear() then
			icon = C["Wind Shear Icon"]
			self.db.char.priority.next = "wind"
		end
		if self:CheckShamanisticRage() then
			icon = C["Shamanistic Rage Icon"]
			self.db.char.priority.next = "mana"
		end
		-- check if we should show shamanistic rage icon
		self:SetPriorityBackdrop(icon)
	end
end

function ShockAndAwe:CheckWindShear()
	if not self.db.char.priority.worldbossonly or (self.db.char.priority.worldbossonly and UnitClassification("target") == "worldboss") then
		if self.db.char.windshearshow and (GetNumPartyMembers()>=4 or GetNumRaidMembers()>=4) then
			-- don't use windshear option if soloing
			local _, state, _, raw = UnitDetailedThreatSituation("player", "target")
			-- state 2 or 3 = tanking which is not what an Enh Shammy should be doing
			-- state 0 threat < 100%, state 1 threat >=100%
			if not state then state = 0 end
			if not raw then raw = 0 end
			if  state > 1 or raw > self.db.char.threatThreshold then
				-- we have exceeded threshold or have already started tanking so wind shear needed.
				local startTime, duration = GetSpellCooldown(C["Wind Shear"])
				if startTime then -- extra check in case player hasn't learned Wind Shear
					local timeleft = startTime + duration - GetTime()
					if timeleft <= ShockAndAwe.db.char.priority.cooldown then -- check its off cooldown
						return true
					end
				end
			end
		end
	end
	return false
end

function ShockAndAwe:CheckShamanisticRage()
	local srtalent
	_, _, _, _, srtalent = GetTalentInfo(2,26)
	if srtalent == 1 then
		local startTime, duration = GetSpellCooldown(C["Shamanistic Rage"])
		if startTime then 
			local timeleft = startTime + duration - GetTime()
			local manapercent = 100 * UnitMana("player") / UnitManaMax("player")
			if manapercent < self.db.char.priority.srmana and timeleft <= self.db.char.priority.cooldown then
				return true
			end
		end
	end
	return false
end

function ShockAndAwe:QuakingEarthEquipped()
	local rangedLink = GetInventoryItemLink("player",GetInventorySlotInfo("RangedSlot")) or "0:0"
    local _, itemID = strsplit(":", rangedLink)
	return itemID == "47667" -- returns if ranged slot has Totem of Quaking Earth
end

function ShockAndAwe:SetNextPriority()
	-- force update of stacks count to ensure priority shown correctly
	self.db.char.msstacks = ShockAndAwe:GetMaelstromInfo()
	if self.db.char.priority.combopoints then
		self:ShowComboPoints()
	end
	self.db.char.priority.next = "none"
	self:VerifyOptions()
	for index = 1, 16 do
		if self.db.char.priority.option[index] and self.priorityTable.test[self.db.char.priority.option[index]] then  -- verify that the option actually exists
			if self.priorityTable.test[self.db.char.priority.option[index]]() then
				self.db.char.priority.next = self.db.char.priority.option[index]
				return -- we need to break out of the routine as we have found the top priority
			end
		end
	end
end

function ShockAndAwe:ShowComboPoints()
	local col = self.db.char.colours.maelstrom
	for index = 1, 5 do
		if self.PriorityFrame.combo[index].frame then
			if self.db.char.msstacks >= index then
				self.PriorityFrame.combo[index].frame:SetBackdropColor(1, 0, 0, 1)
			else
				self.PriorityFrame.combo[index].frame:SetBackdropColor(col.r, col.g, col.b, 0)
			end
		else
			self:Print("Error could not find combo frame "..index)
		end
	end
end

function ShockAndAwe:CreateComboPointFrames()
	self.PriorityFrame.combo = {}
	for index = 1, 5 do 
		self:CreateComboPoint(index)
	end
end
	
function ShockAndAwe:CreateComboPoint(index)
	if not self.PriorityFrame.combo[index] or not self.PriorityFrame.combo[index].frame then
		self.PriorityFrame.combo[index] = {}
		self.PriorityFrame.combo[index].frame = CreateFrame("Frame", "SAA_PriorityComboFrame"..index, self.PriorityFrame)
	end
	local comboFrame = self.PriorityFrame.combo[index].frame
	local width = self.db.char.priority.fWidth / 5
	local height = self.db.char.priority.fHeight / 5
	comboFrame:SetScale(self.db.char.priority.scale)
	comboFrame:SetFrameStrata("BACKGROUND")
	comboFrame:SetWidth(width)
	comboFrame:SetHeight(height)
	comboFrame:SetBackdrop({ bgFile = "Interface/Tooltips/UI-Tooltip-Background",
		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
		tile = false, tileSize = 0, edgeSize = 4,
		insets = { left = 2, right = 2, top = 2, bottom = 2 }
	})	
	comboFrame:SetBackdropColor(0, 0, 0, 0);
	comboFrame:SetPoint("BOTTOMLEFT",  self.PriorityFrame, "BOTTOMLEFT", (index - 1) * width , - height)

	if self.db.char.priority.combopoints then
		comboFrame:Show()
	else
		comboFrame:Hide()
	end
end

function ShockAndAwe:CreateInterruptPurgeFrames()
	if not self.PriorityFrame.interrupt then
		self.PriorityFrame.interrupt = {}
		self.PriorityFrame.interrupt.frame = CreateFrame("Frame", "SAA_PriorityInterruptFrame", self.PriorityFrame)
	end
	local interruptFrame = self.PriorityFrame.interrupt.frame
	local width = self.db.char.priority.fWidth / 2
	local height = self.db.char.priority.fHeight / 2
	interruptFrame:SetScale(self.db.char.priority.scale)
	interruptFrame:SetFrameStrata("BACKGROUND")
	interruptFrame:SetWidth(width)
	interruptFrame:SetHeight(height)
	self:SetSubFrameBackdrop(interruptFrame, "Interface/Tooltips/UI-Tooltip-Background", 4)	
	interruptFrame:SetBackdropColor(0, 0, 0, 0);
	interruptFrame:SetPoint("BOTTOMLEFT",  self.PriorityFrame, "BOTTOMRIGHT", 0 , 0)
	if self.db.char.priority.showinterrupt then
		interruptFrame:Show()
	else
		interruptFrame:Hide()
	end

	if not self.PriorityFrame.purge then
		self.PriorityFrame.purge = {}
		self.PriorityFrame.purge.frame = CreateFrame("Frame", "SAA_PrioritypurgeFrame", self.PriorityFrame)
	end
	local purgeFrame = self.PriorityFrame.purge.frame
	purgeFrame:SetScale(self.db.char.priority.scale)
	purgeFrame:SetFrameStrata("BACKGROUND")
	purgeFrame:SetWidth(width)
	purgeFrame:SetHeight(height)
	self:SetSubFrameBackdrop(purgeFrame, "Interface/Tooltips/UI-Tooltip-Background", 4)	
	purgeFrame:SetBackdropColor(0, 0, 0, 0);
	purgeFrame:SetPoint("BOTTOMLEFT",  self.PriorityFrame, "BOTTOMRIGHT", 0 , height)	
	if self.db.char.priority.showpurge then
		purgeFrame:Show()
	else
		purgeFrame:Hide()
	end
end

function ShockAndAwe:SetSubFrameBackdrop(subFrame, icon, edgeSize)
	subFrame:SetBackdrop({ bgFile = icon,
		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
		tile = false, tileSize = 0, edgeSize = edgeSize,
		insets = { left = 2, right = 2, top = 2, bottom = 2 }
	})	
end