-- 직업별 버프 확인 모듈
local IRF2 = InvenRaidFrames2

local _G = _G
local type = _G.type
local unpack = _G.unpack
local select = _G.select
local max = _G.math.max
local UnitAura = _G.UnitAura
local UnitClass = _G.UnitClass
local UnitPowerMax = _G.UnitPowerMax	-- UnitPowerMax(unit, 0) == 0 (비마나 클래스)
local GetSpellInfo = _G.GetSpellInfo
local GetSpellTexture = _G.GetSpellTexture
local InCombatLockdown = _G.InCombatLockdown
local IsInInstance = _G.IsInInstance
local class = select(2, UnitClass("player")) or "*"
local L = IRF2.GetSpellLocale

local buffList = {
	PRIEST = { [L(21562)] = 1, [L(1243)] = 1, [L(27681)] = 2, [L(14752)] = 2, [L(27683)] = 3, [L(10957)] = 3 },
	MAGE = { [L(23028)] = 1, [L(1459)] = 1, [L(61316)] = 1, [L(61024)] = 1, [L(1267)] = 2, [L(1266)] = 3 },
	WARLOCK = { [L(20707)] = 1, [L(2972)] = 2, [L(5697)] = 3 },
	DRUID = { [L(21849)] = 1, [L(1126)] = 1, [L(467)] = 2 },
	SHAMAN = { [L(131)] = 1, [L(546)] = 2 },
	PALADIN = { [L(20217)] = 1, [L(25898)] = 2, [L(19740)] = 3, [L(25782)] = 4, [L(19742)] = 5, [L(25894)] = 6, [L(20911)] = 7, [L(25899)] = 8 },
}

local buffIcon = {
	PRIEST = { 21562, 27681, 27683 },
	MAGE = { 23028, 1267, 1266 },
	WARLOCK = { 20707, 2972, 5697 },
	DRUID = { 21849, 467 },
	SHAMAN = { 131, 546 },
	PALADIN = { 20217, 25898, 19740, 25782, 19742, 25894, 20911, 25899 },
}
local hasBuff = { false, false, false, false }

if not buffList[class] then return end

local buffCheckHandler = CreateFrame("Frame")

buffList = buffList[class]
buffIcon = buffIcon[class]

local getBuffName = {}

for i = 1, #buffIcon do
	getBuffName[i], _, buffIcon[i] = GetSpellInfo(buffIcon[i])
end

local stack, bless, spellNum, name, width, buffNum = {}, {}, 0

local function playerHasSpell(spell)
	if GetSpellTexture(spell == GetSpellInfo(20707) and GetSpellInfo(693) or spell) then
		return true
	else
		return false
	end
end

for spell, id in pairs(buffList) do
	buffNum = max(buffNum or 0, id)
	if not hasBuff[id] and playerHasSpell(spell) then
		hasBuff[id] = true
		spellNum = spellNum + 1
	end
end

local sefBuff, createBuffFrame, fullName, icon, instance, ownerUnit

local function combatShowCheck()
	if not InvenRaidFrames2CharDB.buffCheck.showInCombat and (IRF2.incombat or InCombatLockdown()) then
		return false
	else
		instance = select(2, IsInInstance())
		if InvenRaidFrames2CharDB.buffCheck.useField and instance == "none" then
			return true
		elseif InvenRaidFrames2CharDB.buffCheck.usePVP and (instance == "pvp" or instance == "arena") then
			return true
		elseif InvenRaidFrames2CharDB.buffCheck.useInstance and (instance == "party" or instance == "raid") then
			return true
		else
			return false
		end
	end
end

function IRF2:GetBuffCheckList()
	return unpack(getBuffName)
end

if class == "PALADIN" then
	function createBuffFrame(object)
		pos = IRF2:GetFramePoint(IRF2.db.buffCheck.pos)[1]
		object.buffFrame = CreateFrame("Frame", nil, object)
		object.buffFrame:SetFrameLevel(IRF2.db.frameLevel.buffCheck)
		object.buffFrame:SetPoint(pos, object, pos)
		object.buffFrame:SetWidth(0.001)
		object.buffFrame:SetHeight(IRF2.db.buffCheck.size)
		object.buffFrame.bless = object.buffFrame:CreateTexture(nil, "OVERLAY")
		object.buffFrame.bless:SetAllPoints(object.buffFrame)
		object.buffFrame.bless:SetTexCoord(0.07, 0.93, 0.07, 0.93)
		object.buffFrame.bless:SetAllPoints(object.buffFrame)
	end

	function setBuff(object)
		if IRF2.db.buffCheck.use and combatShowCheck() and object.unit and not object.vehicleUnit then
			fullName = GetUnitName(object.unit)
			stack[1] = false
			-- 자신이 시전한 축복 체크
			for spell, id in pairs(buffList) do
				name, _, icon, _, _, _, _, ownerUnit = UnitAura(object.unit, spell, nil, "HELPFUL|PLAYER")
				if ownerUnit == 1 then
					-- for Live Server (3.0.9)
					ownerUnit = true
				elseif type(ownerUnit) == "string" and UnitIsUnit("player", ownerUnit) then
					-- for Test Server (3.1.0)
					ownerUnit = true
				else
					ownerUnit = nil
				end
				if name and ownerUnit then
					bless[fullName] = id
					buffIcon[id] = icon
					stack[1] = true
					break
				end
			end
			if spellNum > 0 and InvenRaidFrames2CharDB.buffCheck.check and object.connected then
				if not object.buffFrame then
					createBuffFrame(object)
				end
				if InvenRaidFrames2CharDB.buffCheck.shownType == "버프가 있을 때 표시" then
					if stack[1] then
						object.buffFrame:SetWidth(IRF2.db.buffCheck.size)
						object.buffFrame.bless:SetTexture(buffIcon[bless[fullName]])
					else
						object.buffFrame:SetWidth(0.001)
					end
				elseif not stack[1] then
					object.buffFrame:SetWidth(IRF2.db.buffCheck.size)
					if bless[fullName] then
						-- 자신이 마지막으로 시전한 축복이 있을 때
						object.buffFrame.bless:SetTexture(buffIcon[bless[fullName]])
					else
						-- 자신이 마지막으로 시전한 축복이 없을 때 상급 왕의 축복 아이콘 표시
						object.buffFrame.bless:SetTexture(buffIcon[2])
					end
				else
					object.buffFrame:SetWidth(0.001)
				end
			elseif object.buffFrame then
				object.buffFrame:SetWidth(0.001)
			end
		elseif object.buffFrame then
			object.buffFrame:SetWidth(0.001)
		end
	end
else
	function createBuffFrame(object)
		pos = IRF2:GetFramePoint(IRF2.db.buffCheck.pos)[1]
		object.buffFrame = CreateFrame("Frame", nil, object)
		object.buffFrame:SetFrameLevel(IRF2.db.frameLevel.buffCheck)
		object.buffFrame:SetPoint(pos, object, pos)
		object.buffFrame:SetWidth(0.001)
		object.buffFrame:SetHeight(IRF2.db.buffCheck.size)
		for i = 1, buffNum do
			object.buffFrame[i] = object.buffFrame:CreateTexture(nil, "OVERLAY")
			object.buffFrame[i]:SetWidth(0.001)
			object.buffFrame[i]:SetHeight(IRF2.db.buffCheck.size)
			object.buffFrame[i]:SetTexture(buffIcon[i])
			object.buffFrame[i]:SetTexCoord(0.07, 0.93, 0.07, 0.93)
			if i == 1 then
				object.buffFrame[i]:SetPoint("LEFT", object.buffFrame, "LEFT")
			else
				object.buffFrame[i]:SetPoint("LEFT", object.buffFrame[i - 1], "RIGHT")
			end
		end
	end

	function setBuff(object)
		if IRF2.db.buffCheck.use and combatShowCheck() and object.unit and not object.vehicleUnit then
			for i = 1, buffNum do
				stack[i] = false
			end
			for spell, id in pairs(buffList) do
				if UnitAura(object.unit, spell, nil, "HELPFUL") then
					stack[id] = true
				end
			end
			if not object.buffFrame then
				createBuffFrame(object)
			end
			width = 0
			for i = 1, buffNum do
				if hasBuff[i] and object.connected and InvenRaidFrames2CharDB.buffCheck.check[i] then
					if class == "MAGE" and i == 1 and UnitPowerMax(object.unit, 0) == 0 then
						-- 마법사의 신비한 지능을 비지능 클래스에게 무시함
						object.buffFrame[i]:SetWidth(0.001)
					else
						if InvenRaidFrames2CharDB.buffCheck.shownType == "버프가 있을 때 표시" and stack[i] then
							width = width + IRF2.db.buffCheck.size
							object.buffFrame[i]:SetWidth(IRF2.db.buffCheck.size)
						elseif InvenRaidFrames2CharDB.buffCheck.shownType == "버프가 없을 때 표시" and not stack[i] then
							width = width + IRF2.db.buffCheck.size
							object.buffFrame[i]:SetWidth(IRF2.db.buffCheck.size)
						else
							object.buffFrame[i]:SetWidth(0.001)
						end
					end
				else
					object.buffFrame[i]:SetWidth(0.001)
				end
			end
			object.buffFrame:SetWidth(width == 0 and 0.001 or width)
		elseif object.buffFrame then
			for i = 1, buffNum do
				object.buffFrame[i]:SetWidth(0.001)
			end
			object.buffFrame:SetWidth(0.001)
		end
	end
end

buffCheckHandler:SetScript("OnEvent", function(self, event, unit)
	IRF2:RunUnitFunction(unit, setBuff)
end)

local function buffCheckMod(object)
	IRF2.objectModules["BuffCheck"] = nil
	buffCheckHandler:RegisterEvent("UNIT_AURA")
	IRF2:RegisterAuraEvent("BuffCheck", setBuff)
end

IRF2:RegisterObjectModule("BuffCheck", buffCheckMod)

if buffNum > spellNum then
	-- 배우지 못한 버프 스킬이 있을 때 버프 업데이트
	local spellUpdater = CreateFrame("Frame")
	spellUpdater:Hide()

	function spellUpdater:UpdateSpell()
		self.needUpdate = nil
		for spell, id in pairs(buffList) do
			if not hasBuff[id] and playerHasSpell(spell) then
				self.needUpdate = true
				hasBuff[id] = true
				spellNum = spellNum + 1
			end
		end
		if buffNum <= spellNum then
			self:UnregisterEvent("LEARNED_SPELL_IN_TAB")
			self:UnregisterEvent("PLAYER_ENTERING_WORLD")
			self:Hide()
		end
		if self.needUpdate then
			for _, object in pairs(IRF2.units) do
				setBuff(object)
			end
		end
	end

	spellUpdater:SetScript("OnUpdate", function(self, timer)
		self.timer = self.timer + timer
		if self.timer >= 0.15 then
			self:Hide()
			self:UpdateSpell()
		end
	end)

	spellUpdater:SetScript("OnEvent", function(self, event)
		if event == "PLAYER_ENTERING_WORLD" then
			self:UpdateSpell()
		else
			self.timer = 0
			if not self:IsShown() then
				self:Show()
			end
		end
	end)
	spellUpdater:RegisterEvent("LEARNED_SPELL_IN_TAB")
	spellUpdater:RegisterEvent("PLAYER_ENTERING_WORLD")
end