Quantcast
local addonname, addon = ...
local L = addon.L

function addon:Initialize()
	local events = CreateFrame'Frame'
	events:SetScript('OnEvent', function(frame, e, ...)
		if type(self[e]) == 'function' then
			self[e](self, ...)
		end
	end)

	function self:RegisterEvent(...) events:RegisterEvent(...) end
	function self:UnregisterEvent(...) events:UnregisterEvent(...) end

	self:RegisterEvent'ADDON_LOADED'
	self:RegisterEvent'PLAYER_ROLES_ASSIGNED'
	self:RegisterEvent'PLAYER_ENTERING_WORLD'
end

function addon:ADDON_LOADED(name)
	if addonname ~= name then return end

	-- DB
	local defaults = {
		profile = {
			minthreat = 5000,
			dynamic_minthreat = true,
			enabled_in = { dungeon = true, raid = false },
			raid_icons = { 8, 7, 1, 2 },
		}
	}
	self.db = LibStub('AceDB-3.0'):New('KungalooshDB', defaults, true)

	self:CreateConfig()

	self:UnregisterEvent'ADDON_LOADED'

	self:EnableIfTank()
end

function addon:Print(...)
	print('|cFF33FF99Kungaloosh|r '..string.format(...))
end

function addon:PLAYER_ROLES_ASSIGNED()
	self:EnableIfTank()
end

function addon:PLAYER_ENTERING_WORLD()
	self:EnableIfTank()
end

function addon:PLAYER_REGEN_ENABLED()
	self:ResetState()
end

function addon:UNIT_THREAT_LIST_UPDATE(unit)
	if not unit then return end

	local guid = UnitGUID(unit)
	local icon = self:GetRaidIconByGUID(guid) or self:GetNextIcon()

	if icon and GetRaidTargetIndex(unit) == nil then
		local istanking, status, threatpct, rawthreatpct, threat = UnitDetailedThreatSituation('player', unit)

		if threat and threat > (self:GetMinThreat() * 100) then
			SetRaidTarget(unit, icon)
		end
	end
end

function addon:COMBAT_LOG_EVENT(timestamp, event, sguid, sname, sflags, dguid, dname, dflags)
	if event == 'UNIT_DIED' then
		local icon = self:GetRaidIconByGUID(dguid)
		if icon then
			self.iconguids[icon] = nil
		end
	end
end

local function CheckUnit(unit)
	if UnitExists(unit) then
		local icon = GetRaidTargetIndex(unit)
		local guid = UnitGUID(unit)

		if icon then
			local oldguid = addon:GetGUIDByRaidIcon(icon)
			local oldicon = addon:GetRaidIconByGUID(guid)

			if guid ~= oldguid then
				if oldicon then
					addon.iconguids[oldicon] = nil
				end

				addon.iconguids[icon] = guid
			end
		else
			local oldicon = addon:GetRaidIconByGUID(guid)

			if oldicon then
				addon.iconguids[oldicon] = nil
			end
		end
	end
end

function addon:RAID_TARGET_UPDATE()
	CheckUnit'player'
	CheckUnit'target'
	CheckUnit'pet'
	CheckUnit'pettarget'

	for i = 1,40 do
		if i <= 5 then
			CheckUnit('party'..i)
			CheckUnit('party'..i..'target')
		end

		CheckUnit('raid'..i)
		CheckUnit('raid'..i..'target')
	end
end

function addon:ResetState()
	self.iconguids = self.iconguids or {}
	table.wipe(self.iconguids)
end

function addon:GetRaidIconByGUID(guid)
	for icon, iguid in pairs(self.iconguids) do
		if guid == iguid then
			return icon
		end
	end
end

function addon:GetGUIDByRaidIcon(icon)
	return self.iconguids[icon]
end

function addon:GetNextIcon()
	for i, icon in ipairs(self.db.profile.raid_icons) do
		if not addon:GetGUIDByRaidIcon(icon) then
			return icon
		end
	end
end

function addon:GetMinThreat()
	if self.db.profile.dynamic_minthreat then
		local level = UnitLevel'player'

		return (level * level) * 1.2
	else
		return self.db.profile.minthreat
	end
end

function addon:EnableIfTank()
	if self.db.profile.enabled_in.dungeon then
		local istank, ishealer, isdamage = UnitGroupRolesAssigned'player'
		if istank then
			return self:Enable(L['is now enabled since you are assigned as a tank'])
		end
	end

	if self.db.profile.enabled_in.raid then
		if GetPartyAssignment('MAINTANK', 'player') then
			return self:Enable(L['is now enabled since you are assigned as a tank'])
		end
	end

	return self:Disable()
end

function addon:Enable(msg)
	if self.enabled then return end

	self:RegisterEvent'PLAYER_REGEN_ENABLED'
	self:RegisterEvent'UNIT_THREAT_LIST_UPDATE'
	self:RegisterEvent'RAID_TARGET_UPDATE'
	self:RegisterEvent'COMBAT_LOG_EVENT'
	self.enabled = true

	self:ResetState()

	if msg then self:Print(msg) end
end

function addon:Disable(msg)
	if not self.enabled then return end

	self:UnregisterEvent'PLAYER_REGEN_ENABLED'
	self:UnregisterEvent'UNIT_THREAT_LIST_UPDATE'
	self:UnregisterEvent'RAID_TARGET_UPDATE'
	self:UnregisterEvent'COMBAT_LOG_EVENT'
	self.enabled = false

	if msg then self:Print(msg) end
end

function addon:Toggle()
	if not self.enabled then
		self:Enable(L['is now enabled'])
	else
		self:Disable(L['is now disabled'])
	end
end

function SlashCmdList.KUNGALOOSH()
	addon:Toggle()
end

addon:Initialize()

_G['SLASH_KUNGALOOSH1'] = '/kungaloosh'
_G['SLASH_KUNGALOOSH2'] = '/kl'