--[[---------------------------------------------------------------------------------
 Detox
 written by Maia/Proudmoore, 
 code based on the Decursive 1.9.7 core code by Archarodim and Quu.
 The name 'Detox' was provided by Tem.
------------------------------------------------------------------------------------]]

local vmajor,vminor = "0.2", tonumber(string.sub("$Revision: 9976 $", 12, -3))

--[[---------------------------------------------------------------------------------
 locals
------------------------------------------------------------------------------------]]

local compost           = AceLibrary("Compost-2.0")
local aura              = AceLibrary("SpecialEvents-Aura-2.0")
local L                 = AceLibrary("AceLocale-2.0"):new("Detox")
local BS                = AceLibrary("Babble-Spell-2.0")
local BC                = AceLibrary("Babble-Class-2.0")
local RL                = AceLibrary("RosterLib-2.0")
local tablet            = AceLibrary("Tablet-2.0")

local last_DemonType    = nil
local curr_DemonType    = nil
local castTarget        = nil
local alreadyCleaning   = false
local blacklist         = {}
local outofrange        = {}
local priorityIndex     = {} -- this table references name to index of the priority table
local priority          = {} -- this integer keyed table will hold subtables containing name, unitid and priority for each unit in our roster

local hasSpells         = false
local canCureMagic      = false
local canCureEnemyMagic = false
local canCureDisease    = false
local canCurePoison     = false
local canCureCurse      = false
local spellMagic1       = {0, "", ""}
local spellMagic2       = {0, "", ""}
local spellEnemyMagic1  = {0, "", ""}
local spellEnemyMagic2  = {0, "", ""}
local spellDisease1     = {0, "", ""}
local spellDisease2     = {0, "", ""}
local spellPoison1      = {0, "", ""}
local spellPoison2      = {0, "", ""}
local spellCurse        = {0, "", ""}
local spellCooldown     = {0, "", ""}

local DebuffTypeColor      = {}
DebuffTypeColor["none"]    = { r = 0.80, g = 0, b = 0 }
DebuffTypeColor["Magic"]   = { r = 0.20, g = 0.60, b = 1.00 }
DebuffTypeColor["Curse"]   = { r = 0.60, g = 0.00, b = 1.00 }
DebuffTypeColor["Disease"] = { r = 0.60, g = 0.40, b = 0 }
DebuffTypeColor["Poison"]  = { r = 0.00, g = 0.60, b = 0 }

local invisible = {
    [BS["Prowl"]]                 = true,
    [BS["Stealth"]]               = true,
    [BS["Shadowmeld"]]            = true,
}

local ignore = {
    [BS["Banish"]]                = true,
    [BS["Phase Shift"]]           = true,
}

local skip = {
    [L["Dreamless Sleep"]]        = true,
    [L["Greater Dreamless Sleep"]] = true,
--    [BS["Mind Vision"]] = true,
}

local skipByClass = {
    ["WARRIOR"] = {
		[L["Ancient Hysteria"]]   = true,
		[L["Ignite Mana"]]        = true,
		[L["Tainted Mind"]]       = true,
    };
    ["ROGUE"] = {
		[BS["Silence"]]           = true,
		[L["Ancient Hysteria"]]   = true,
		[L["Ignite Mana"]]        = true,
		[L["Tainted Mind"]]       = true,
    };
   	["HUNTER"] = {
		[L["Magma Shackles"]]     = true,
    };
   	["MAGE"] = {
		[L["Magma Shackles"]]     = true,
    }
}

local cleaningSpells = {
	[BS["Cure Disease"]]          = true,
	[BS["Abolish Disease"]]       = true,
	[BS["Purify"]]                = true,
	[BS["Cleanse"]]               = true,
	[BS["Dispel Magic"]]          = true,
	[BS["Cure Poison"]]           = true,
	[BS["Abolish Poison"]]        = true,
	[BS["Remove Lesser Curse"]]   = true,
	[BS["Remove Curse"]]          = true,
	[BS["Purge"]]                 = true,
	[BS["Devour Magic"]]          = true,
}


--[[---------------------------------------------------------------------------------
 defaults and AceOptions table
------------------------------------------------------------------------------------]]

local defaults = {
	ignoreStealthed = true,
	blacklistTime = 5,
	checkAbolish = true,
	scanPets = true,
	liveDisplay = 5,
	filter = false,
	updateSpeed = 0.5,
	priorityNames = {},
}

local options = {
	type = 'group',
	args = {
		clean = {
			type = 'execute',
			name = "Clean group", 
		    desc = "Will attempt to clean a player in your raid/party",
		    func = function()
		        Detox:Clean()
		    end,
			order = 101
		},
		stealth = {
			type = 'toggle',
			name = "Ignore stealthed units",
			desc = "It is recommended not to cure stealthed units.",
			get = function() return Detox.db.profile.ignoreStealthed end,
			set = function()
				Detox.db.profile.ignoreStealthed = not Detox.db.profile.ignoreStealthed
			end,
			order = 110
		},
		abolish = {
			type = 'toggle',
			name = "Skip units that have 'Abolish' buff",
			desc = "Skip units that have an active abolish buff.",
			get = function() return Detox.db.profile.checkAbolish end,
			set = function()
				Detox.db.profile.checkAbolish = not Detox.db.profile.checkAbolish
			end,
			order = 130
		},
		pets = {
			type = 'toggle',
			name = "Scan pets",
			desc = "Pets are your friends.",
			get = function() return Detox.db.profile.scanPets end,
			set = function()
				Detox.db.profile.scanPets = not Detox.db.profile.scanPets
				Detox:UpdatePriority()
			end,
			order = 140
		},
		filter = {
			type = 'toggle',
			name = "Filter display",
			desc = "Only show debuffs you can cure.",
			get = function() return Detox.db.profile.filter end,
			set = function()
				Detox.db.profile.filter = not Detox.db.profile.filter
			end,
			order = 150
		},
		blacklist = {
			type = 'range',
			name = "Seconds to blacklist",
			desc = "Units that are out of LoS will be blacklisted.",
			get = function() return Detox.db.profile.blacklistTime end,
			set = function(v) 
				Detox.db.profile.blacklistTime = v
			end,
			min = 1,
			max = 20,
			step = 1,
			isPercent = false,
			order = 200
		},
		live = {
			type = 'range',
			name = "Max live display unit debuffs",
			desc = "Defines the max number of unit debuffs to display in the tooltip.",
			get = function() return Detox.db.profile.liveDisplay end,
			set = function(v) 
				Detox.db.profile.liveDisplay = v
			end,
			min = 0,
			max = 20,
			step = 1,
			isPercent = false,
			order = 300
		},
		speed = {
			type = 'range',
			name = "Live display update speed",
			desc = "Defines the speed the live list is updated.",
			get = function() return Detox.db.profile.updateSpeed end,
			set = function(v) 
				Detox.db.profile.updateSpeed = v
				Detox:CancelScheduledEvent("liveList")
				Detox:ScheduleRepeatingEvent("liveList", Detox.Update, v, Detox)
			end,
			min = 0.2,
			max = 2,
			step = 0.1,
			isPercent = false,
			order = 350
		},
		priority = {
			type = 'group',
			name = "units to priorize",
			desc = "These units will be priorized.",
			order = 400,
			args = {}
		}
	}
}



--[[---------------------------------------------------------------------------------
 Initialization
------------------------------------------------------------------------------------]]

Detox = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceDB-2.0", "AceConsole-2.0", "AceDebug-2.0", "FuBarPlugin-2.0")

-- stuff for FuBar:
Detox.OnMenuRequest = options
Detox.name = "Detox"  -- should be auto provided if using AceAddon-2.0
Detox.hasIcon = true
Detox.defaultPosition = "LEFT"
Detox.defaultMinimapPosition = 250
Detox.cannotDetachTooltip = false
Detox.hideWithoutStandby = true
Detox.clickableTooltip = true -- XXX now do what?
Detox.independentProfile = true

function Detox:OnInitialize()
	self:RegisterDB("DetoxDB")
	self:RegisterDefaults('profile', defaults )
	self:RegisterChatCommand({'/detox'}, options )
end

function Detox:OnEnable()
	self:RegisterEvent("SPELLCAST_STOP")
	self:RegisterEvent("UNIT_PET",1)
	self:RegisterEvent("SPELLS_CHANGED","RescanSpellbook",1)
	self:RegisterEvent("LEARNED_SPELL_IN_TAB","RescanSpellbook",1)
	self:RegisterEvent("UI_ERROR_MESSAGE")
	self:RegisterEvent("RosterLib_RosterChanged")
	self:ParseSpellbook()
	self:ScheduleRepeatingEvent(self.OnUpdate, 1, self)
	self:ScheduleRepeatingEvent("liveList", self.Update, Detox.db.profile.updateSpeed or 0.5, self)	-- this is the FuBar live list update!
	self.debugging = self:IsDebugging()
end

function Detox:OnDisable()
end

function Detox:OnClick()  -- FuBarPlugin
	self:Clean()
end

function Detox:IsDebugging() return self.db.profile.debugging end
function Detox:SetDebugging(debugging) self.db.profile.debugging = debugging; self.debugging = debugging; end

--[[---------------------------------------------------------------------------------
 Events
------------------------------------------------------------------------------------]]

function Detox:OnUpdate()
	self:UpdateBlacklist()
end


function Detox:UpdateBlacklist()
	for unit in blacklist do
		blacklist[unit] = blacklist[unit] - 1
		if blacklist[unit] < 0 then
			blacklist[unit] = nil
		end
	end
end


function Detox:RosterLib_RosterChanged(tbl)
	for name in tbl do
		local u = tbl[name]
		if not u.name then -- someone left the raid
			for i = table.getn(priority), 1, -1 do
				if not RL.roster[priority[i].name] then
					priorityIndex[priority[i].name] = nil
					compost:Reclaim(priority[i])
					priority[i] = nil
					table.remove(priority, i)
				end
			end
		end
	end
	self:UpdatePriority()
end


function Detox:SPELLCAST_STOP()
	castTarget = nil
end


function Detox:UNIT_PET(unit)
	if unit == "player" then
		self:ScheduleEvent(self.CheckPet, 2, self)
	end
end


function Detox:UI_ERROR_MESSAGE(arg1)
	if arg1 == SPELL_FAILED_LINE_OF_SIGHT then
		if castTarget and not UnitIsUnit(castTarget, "player") then
			blacklist[castTarget] = Detox.db.profile.blacklistTime
	    end
	end
end


--[[---------------------------------------------------------------------------------
 Spellbook
------------------------------------------------------------------------------------]]

-- use compost to clean spell tables
function Detox:ParseSpellbook()
	hasSpells         = false
	canCureMagic      = false
	canCureEnemyMagic = false
	canCureDisease    = false
	canCurePoison     = false
	canCureCurse      = false
	spellMagic1       = {0,"", ""}
	spellMagic2       = {0,"", ""}
	spellEnemyMagic1  = {0,"", ""}
	spellEnemyMagic2  = {0,"", ""}
	spellDisease1     = {0,"", ""}
	spellDisease2     = {0,"", ""}
	spellPoison1      = {0,"", ""}
	spellPoison2      = {0,"", ""}
	spellCurse        = {0,"", ""}
	local BookType    = BOOKTYPE_SPELL
	local break_flag  = false
	local i = 1
    while not break_flag do
		while (true) do --  HUH?
		    local name, rank = GetSpellName(i, BookType)
		    if not name then
				if BookType == BOOKTYPE_PET then
			    	break_flag = true
			    	break
				end
				BookType = BOOKTYPE_PET
				i = 1
				break
		    end
		    if cleaningSpells[name] then
				hasSpells = true
				spellCooldown[1] = i
				spellCooldown[2] = BookType
				if name == BS["Cure Disease"] or name == BS["Purify"] then
					canCureDisease = true
					spellDisease1 = { i, BookType, name }
				end
				if name == BS["Abolish Disease"] or name == BS["Cleanse"] then
					canCureDisease = true
					spellDisease2 = { i, BookType, name }
				end		
				if name == BS["Cure Poison"] or name == BS["Purify"] then
					canCurePoison = true
					spellPoison1 = { i, BookType, name }
				end			
				if name == BS["Abolish Poison"] or name == BS["Cleanse"] then
					canCurePoison = true
					spellPoison2 = { i, BookType, name }
				end
				if name == BS["Remove Curse"] or name == BS["Remove Lesser Curse"] then
				    canCureCurse = true
				    spellCurse = { i, BookType, name }
				end
				if name == BS["Cleanse"] then
					canCureMagic = true
					spellMagic1 = { i, BookType, name }
				end
				if name == BS["Dispel Magic"] or name == BS["Devour Magic"] then
				    canCureMagic = true
					if rank == "Rank 1" then
						spellMagic1 = { i, BookType, name }
					else
					    spellMagic2 = { i, BookType, name }
					end
				end
				if name == BS["Dispel Magic"] or name == BS["Purge"] or name == BS["Devour Magic"] then
				    canCureEnemyMagic = true
				    if rank == "Rank 1" then
						spellEnemyMagic1 = { i, BookType, name }
				    else
						spellEnemyMagic2 = { i, BookType, name }
				    end
				end
	    	end
	    	i = i + 1
		end
    end
end


function Detox:RescanSpellbook()
	if not hasSpells then return end
	local spellValid = true
	spellValid = self:CheckSpellName(spellMagic1[1], spellMagic1[2], spellMagic1[3])
	spellValid = self:CheckSpellName(spellMagic2[1], spellMagic2[2], spellMagic2[3])
	spellValid = self:CheckSpellName(spellEnemyMagic1[1], spellEnemyMagic1[2], spellEnemyMagic1[3])
	spellValid = self:CheckSpellName(spellEnemyMagic2[1], spellEnemyMagic2[2], spellEnemyMagic2[3])
	spellValid = self:CheckSpellName(spellDisease1[1], spellDisease1[2], spellDisease1[3])
	spellValid = self:CheckSpellName(spellDisease2[1], spellDisease2[2], spellDisease2[3])
	spellValid = self:CheckSpellName(spellPoison1[1], spellPoison1[2], spellPoison1[3])
	spellValid = self:CheckSpellName(spellPoison2[1], spellPoison2[2], spellPoison2[3])
	spellValid = self:CheckSpellName(spellCurse[1], spellCurse[2], spellCurse[3])
	if not spellValid then
		self:ParseSpellbook()
		return
    end
end


function Detox:CheckSpellName(id,booktype,spellname)
	if id ~= 0 then
		if GetSpellName(id, booktype) ~= spellname then return false end
	end
	return true
end


function Detox:CheckPet()
	curr_DemonType = UnitCreatureFamily("pet")
	if last_DemonType ~= curr_DemonType then
		last_DemonType = curr_DemonType
		self:ParseSpellbook()
	end
end


--[[---------------------------------------------------------------------------------
 Cleaning
------------------------------------------------------------------------------------]]


function Detox:Clean()
    if not hasSpells then
		self:ParseSpellbook()
		if not hasSpells then
			return false
		end
    end
    if alreadyCleaning then return false end
	alreadyCleaning = true
	-- check for cooldown
	local _, cooldown = GetSpellCooldown(spellCooldown[1], spellCooldown[2])
	if cooldown ~= 0 then
		alreadyCleaning = false
		return false
	end
	-- save target
	local targetEnemy = false
	local targetName = nil
	local cleaned = false
	castTarget = nil
	-- try to clean target first
	if UnitExists("target") then
		if UnitIsFriend("target", "player") and not UnitIsCharmed("target") then
			cleaned = self:CureUnit("target")
			targetName = UnitName("target")
		else
	 		targetEnemy = true
	 		if UnitIsCharmed("target") then
  				cleaned = self:CureUnit("target")
			end
	 	end
	end
	-- couldn't clean target, check for MCd units
	if not cleaned and canCureEnemyMagic then
		for k,v in ipairs(priority) do
			if v.pri == 0 then break end
			local unit = v.unitid
			if      UnitIsCharmed(unit) 
			and not blacklist[unit] then
				if self:CureUnit(unit) then
   					cleaned = true
   					break
				end
			end
		end
	end
	-- now do the rest (this is duplicated code, gah!)
	if not cleaned then
		for k,v in ipairs(priority) do
			if v.pri == 0 then break end
			local unit = v.unitid
			if  not blacklist[unit] 
			and not UnitIsCharmed(unit) then
				if self:CureUnit(unit) then
					cleaned = true
					break
				end
			end
		end	
	end	
	-- now try blacklist
	if not cleaned then
		for unit in blacklist do
			if self:CureUnit(unit) then
    			blacklist[unit] = nil
				cleaned = true
	   			break
			end
		end
	end
	-- restore target
	if targetEnemy then
		if not UnitIsEnemy("target", "player") then
			TargetUnit("playertarget")
		end
	elseif targetName then
		if targetName ~= UnitName("target") then
			TargetByName(targetName)
		end
	elseif UnitExists("target") then
		ClearTarget()
	end
	alreadyCleaning = false
	return cleaned
end


function Detox:UnitCurable(unit)
	if not UnitExists(unit) then return false end
	if not UnitIsVisible(unit) then return false end
	if not ( curr_DemonType or CheckInteractDistance(unit, 4) ) then return false end
	-- check if unit is stealthed
	if Detox.db.profile.ignoreStealthed then
		for buff in invisible do
			if aura:UnitHasBuff(unit, buff) then return false end
		end
	end
	-- check if we need to ignore unit
	for debuff in ignore do
		if aura:UnitHasDebuff(unit, debuff) then return false end
	end
	-- check for debuffs that are buffs
	for debuff in skip do
		if aura:UnitHasDebuff(unit, debuff) then return false end
	end
	-- check for debuffs we want to skip for specific classes when in combat
	if UnitAffectingCombat("player") then
		local _, class = UnitClass(unit)
		if skipByClass[class] then
			for debuff in skipByClass[class] do
				if aura:UnitHasDebuff(unit, debuff) then return false end
			end
		end
	end
	if Detox.db.profile.checkAbolish and aura:UnitHasBuff(unit, BS["Abolish Poison"]) then return false end
	if Detox.db.profile.checkAbolish and aura:UnitHasBuff(unit, BS["Abolish Disease"]) then return false end
	return true
end


function Detox:CureUnit(unit)
	if not self:UnitCurable(unit) then return false end
	local cleaned = false
	local skip
	-- check if we can clean a magic debuff
	if (canCureMagic or canCureEnemyMagic) and aura:UnitHasDebuffType(unit, "Magic") then
		-- check for MC
		if canCureEnemyMagic and UnitIsCharmed(unit) and UnitCanAttack("player", unit) then
			if spellEnemyMagic2[1] ~= 0 or spellMagic1[1] == 0 then
				cleaned = self:CastCuringSpell(spellEnemyMagic2, unit, "Charm", true)
			else
				cleaned = self:CastCuringSpell(spellEnemyMagic1, unit, "Charm", true)
			end
		elseif canCureMagic and not UnitCanAttack("player", unit) then
			if spellMagic2[1] ~= 0 or spellMagic1[1] == 0 then
				cleaned = self:CastCuringSpell(spellMagic2, unit, "Magic", canCureEnemyMagic)
			else
				cleaned = self:CastCuringSpell(spellMagic1, unit, "Magic", canCureEnemyMagic)
			end
		end	
	end
	if cleaned then return true end
	-- check if we can clean a curse
	if canCureCurse and not UnitIsCharmed(unit) and aura:UnitHasDebuffType(unit, "Curse") then
		cleaned = self:CastCuringSpell(spellCurse, unit, "Curse", false)
	end
	if cleaned then return true end
	-- check if we can clean poison
	skip = ( Detox.db.profile.checkAbolish and aura:UnitHasBuff(unit, BS["Abolish Poison"]) ) or false
	if canCurePoison and not UnitIsCharmed(unit) and not skip and aura:UnitHasDebuffType(unit, "Poison") then
		if spellPoison2[1] ~= 0 and not aura:UnitHasBuff(unit, BS["Abolish Poison"]) then
			cleaned = self:CastCuringSpell(spellPoison2, unit, "Poison", false)
		else
			cleaned = self:CastCuringSpell(spellPoison1, unit, "Poison", false)
		end
	end
	if cleaned then return true end
	-- check if we can clean disease
	skip = ( Detox.db.profile.checkAbolish and aura:UnitHasBuff(unit, BS["Abolish Disease"]) ) or false
	if canCureDisease and not UnitIsCharmed(unit) and not skip and aura:UnitHasDebuffType(unit, "Disease") then
		if spellDisease2[1] ~= 0 and not aura:UnitHasBuff(unit, BS["Abolish Disease"]) then
			cleaned = self:CastCuringSpell(spellDisease2, unit, "Disease", false)
	    else
			cleaned = self:CastCuringSpell(spellDisease1, unit, "Disease", false)
	    end
	end
	return cleaned
end


function Detox:CastCuringSpell(spellID, unit, AfflictionType, ClearCurrentTarget)
	if spellID[1] == 0 then return false end
	if spellID[2] ~= BOOKTYPE_PET and not CheckInteractDistance(unit, 4) then return false end
	if ClearCurrentTarget then
		if not UnitIsUnit("target", unit) then ClearTarget() end
	elseif UnitIsFriend("player", "target") and not UnitIsUnit("target", unit) then
		ClearTarget()
	end
	if spellID[2] == BOOKTYPE_PET then TargetUnit(unit) end
	if SpellIsTargeting() then SpellStopTargeting() end
	castTarget = unit
	CastSpell(spellID[1], spellID[2])
	if spellID[2] == BOOKTYPE_PET then
		TargetUnit("playertarget")
	elseif SpellIsTargeting() then
		SpellTargetUnit(unit)
	end
	if SpellIsTargeting() then 
		SpellStopTargeting()
		return false
	else
		return true
	end
end


--[[---------------------------------------------------------------------------------
 Priority
------------------------------------------------------------------------------------]]

local function sortPri(a,b) 
	return a.pri > b.pri 
end


function Detox:UpdatePriority()
	self:CreateOptionsTable()
	-- update and sort all units. this task has a few steps:
	local datasubtable, index
	for name, u in pairs(RL.roster) do
		-- see if that unit is in our priorityIndex table
		index = priorityIndex[name]
		-- either use the existing subtable or create a new one
		datasubtable = index and priority[index] or compost:Acquire()
		datasubtable.pri = self:GetPriority(name)
		datasubtable.unitid = u.unitid
		if not index then
			-- our subtable still needs a name
			datasubtable.name = name
			-- add that subtable to the priority table
			table.insert(priority, datasubtable)
			priorityIndex[name] = table.getn(priority)  -- maybe not needed, but for safety reasons it can't hurt.
		end
	end
	-- now re-sort the priority table
	table.sort(priority, sortPri)
	-- save the current index for all names
	for k,v in ipairs(priority) do
		priorityIndex[v.name] = k
	end
end


function Detox:CreateOptionsTable()
	-- we need to update the dewdrop menu, so lets clear the old one and inject new stuff:
	for class in options.args.priority.args do
		for unit in options.args.priority.args[class].args do
			compost:Reclaim(options.args.priority.args[class].args[unit])
			options.args.priority.args[class].args[unit] = nil
		end
		compost:Reclaim(options.args.priority.args[class])
		options.args.priority.args[class] = nil
	end
	-- create subgroups
	for name, unit in pairs(RL.roster) do
		local n = name
		local u = unit
		if not options.args.priority.args[u.class] then
			options.args.priority.args[u.class] = compost:Acquire()
			options.args.priority.args[u.class].type = 'group'
			-- convert class name. gah.
			-- we need this as Babble-Class doesnt know capitalized class names, nor does it know "PET"
			local c = strupper(strsub(u.class, 1, 1)) .. strlower(strsub(u.class, 2))
			if c ~= "Pet" then c = BC[c] end
			options.args.priority.args[u.class].name = c
			options.args.priority.args[u.class].desc = c
			options.args.priority.args[u.class].order = 101
			options.args.priority.args[u.class].args = compost:Acquire()
		end
		options.args.priority.args[u.class].args[n] = compost:Acquire()
		options.args.priority.args[u.class].args[n].type = 'toggle'
		options.args.priority.args[u.class].args[n].name = n
		options.args.priority.args[u.class].args[n].desc = 'priorize '..n
		options.args.priority.args[u.class].args[n].order = 101
		options.args.priority.args[u.class].args[n].get = 
			function() return Detox.db.profile.priorityNames[n] end
		options.args.priority.args[u.class].args[n].set = 
			function() 
				Detox.db.profile.priorityNames[n] = not Detox.db.profile.priorityNames[n]
				Detox:UpdatePriority()
			end
	end
end


function Detox:GetPriority(name)
	local playergroup = (RL.roster[UnitName("player")] and RL.roster[UnitName("player")].subgroup) or 1
	local pri
	local grp = RL.roster[name].subgroup
	-- priority range 1000 - 0.
	if     name == UnitName("player") then  pri = 800
	elseif playergroup == grp         then  pri = 700
	elseif playergroup < grp          then  pri = 700 - (grp - playergroup)*10
	else                                    pri = 700 - (grp + 8 - playergroup)*10
	end
	if RL.roster[name].class == "PET" then 
		if self.db.profile.scanPets then pri = pri - 200 else pri = 0 end
	end
	if Detox.db.profile.priorityNames[name] then pri = pri + 200 end  -- unit in priority list
	return pri
end


--[[---------------------------------------------------------------------------------
 Live display
------------------------------------------------------------------------------------]]


function Detox:OnTooltipUpdate()
	local cat = tablet:AddCategory("columns", 2, "text", "", "text2", "", "showWithoutChildren", true, "hideBlankLine", false)
	local lines = 0
	for k,v in ipairs(priority) do
		if v.pri == 0 then break end
		if lines > Detox.db.profile.liveDisplay then break end
		local unit = v.unitid
		if not blacklist[unit] and self:UnitCurable(unit) then
			for debuffname, count, type, texture in aura:DebuffIter(unit) do
				if ( not Detox.db.profile.filter and ( type == "Magic" or type == "Poison" or type == "Disease" or type == "Curse" ) )
				or ( canCureMagic and type == "Magic" )
				or ( canCurePoison and type == "Poison" )
				or ( canCureDisease and type == "Disease" )
				or ( canCureCurse and type == "Curse" )
				then
					local r,g,b = self:GetRaidColors(unit)
					if count == 0 then count = 1 end
					lines = lines + 1
					cat:AddLine(
						"text", string.format("%s (%dx)", debuffname, count), 
						"textR", DebuffTypeColor[type].r,
						"textG", DebuffTypeColor[type].g,
						"textB", DebuffTypeColor[type].b,
						"text2", UnitName(unit),
						"text2R", r,
						"text2G", g,
						"text2B", b,
						"hasCheck", true, 
						"checked", true, 
						"checkIcon", texture,
						"func", function(unit) Detox:CureUnit(unit) end,
						"arg1", unit,
						"justify", "LEFT",
						"justify2", "LEFT"
					)
				end
			end
		end
	end
end


function Detox:GetRaidColors(unit)
	local _,class = UnitClass(unit)
	if RAID_CLASS_COLORS[class] then
		return RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b
	else
		return 0.5, 0.5, 0.5
	end
end


--[[

TODO:

- let SE-Aura cache debuff text while in combat to reduce tooltip parsing
- listen to SE-Aura for MC debuff, might be faster than looping through everyone everytime.
- priorize MTs
- hide tooltip when empty
- option to skip range check
- show highest priority unit in fubar, clickable
- messaging cures (chat?)
- audio-alert new debuffs

]]
