-- 주문 타이머 모듈
local IRF2 = InvenRaidFrames2

local _G = _G
local type = _G.type
local pairs = _G.pairs
local select = _G.select
local max = _G.math.max
local ceil = _G.math.ceil
local tinsert = _G.table.insert
local UnitAura = _G.UnitAura
local UnitIsUnit = _G.UnitIsUnit
local GetSpellInfo = _G.GetSpellInfo
local GetTime = _G.GetTime

local L = IRF2.GetSpellLocale

local timerData = {
	["WARRIOR"] = { [L(50720)] = 1 },
	["ROGUE"] = { [L(57934)] = 1 },
	["PRIEST"] = { [L(139)] = 1, [L(33076)] = 2, [L(6788)] = 3, [L(17)] = 4 },
	["HUNTER"] = { [L(34477)] = 1 },
	["DRUID"] = { [L(33763)] = 1, [L(774)] = 2, [L(8936)] = 3, [L(48438)] = 4 },
	["SHAMAN"] = { [L(61295)] = 1, [L(52127)] = 2, [L(324)] = 2, [L(974)] = 3 },
	["PALADIN"] = { [L(53563)] = 1, [L(633)] = 2, [L(1022)] = 3, [L(1044)] = 3, [L(6940)] = 3, [L(1038)] = 3, [L(53601)] = 4 },
}
local auraFilter, auraFilterPlayer = {}, {}

timerData = timerData[select(2, UnitClass("player"))]

if timerData == nil then return end
timerData["*"] = nil

local timerSelfData = {
	["WARRIOR"] = { true, true, true, true },
	["ROGUE"] = { true, true, true, true },
	["PRIEST"] = { true, true, false, false },
	["HUNTER"] = { true, true, true, true },
	["DRUID"] = { true, true, true, true, true },
	["SHAMAN"] = { true, true, true, true },
	["PALADIN"] = { false, true, true, true },
}
local isDebuff = {
	[L(6788)] = true,
}

local spellTimerHandler = CreateFrame("Frame")

local initTimer, timerNames, ready = 0, {}, {}
local name, icon, count, timeLeft, isMine, pos
local iconSize = 13
local stackColor = { { 1, 1, 1 }, { 1, 1, 0 }, { 1, 0.5, 0 } }

for spell, loc in pairs(timerData) do
	timerNames[abs(loc)] = timerNames[abs(loc)] or {}
	tinsert(timerNames[abs(loc)], spell)
	initTimer = max(initTimer, abs(loc))
	auraFilter[spell] = isDebuff[spell] and "HARMFUL" or "HELPFUL"
	auraFilterPlayer[spell] = isDebuff[spell] and "HARMFUL|PLAYER" or "HELPFUL|PLAYER"
end

local function OnUpdate(self, timer)
	self.timer = self.timer + timer
	if self.timer >= 0.1 then
		self.timer = 0
		self.hideTime = self.timeLeft - GetTime()
		self.prev_timerLength = self.timerLength
		if self.hideTime > 0 and self.hideTime < 9 then
			-- 타이머 숫자 한 자
			self.timerLength = 9
			self.cooldown:SetText(ceil(self.hideTime))

		elseif self.hideTime > 9 and self.hideTime < 100 then
			-- 타이머 숫자 두 자
			self.timerLength = 18
			self.cooldown:SetText(ceil(self.hideTime))
		else
			-- 타이머 숫자 없음
			self.timerLength = 0
			self.cooldown:SetText("")
		end
		if self.prev_timerLength ~= self.timerLength then
			self:SetWidth((InvenRaidFrames2CharDB.spellTimer.showIcon[self:GetID()] and iconSize or 0.01) + self.timerLength)
		end
	end
end

local function OnHide(self)
	self.timeLeft = nil
	self.hideTime = nil
	self.prev_timerLength = nil
	self.timer = 0
end

local pos, showSelf

local function CreateSpellTimer(object, index)
	if not object.spellTimer[index] then
		object.spellTimer[index] = CreateFrame("Frame", nil, object)
		object.spellTimer[index]:Hide()
		object.spellTimer[index]:SetID(index)
		object.spellTimer[index]:SetScale(InvenRaidFrames2CharDB.spellTimer.size)
		object.spellTimer[index]:SetWidth(0.01)
		object.spellTimer[index]:SetHeight(iconSize)
		object.spellTimer[index]:SetFrameLevel(IRF2.db.frameLevel.spellTimer)
		object.spellTimer[index].timer = 0
		object.spellTimer[index].icon = object.spellTimer[index]:CreateTexture(nil, "ARTWORK")
		object.spellTimer[index].icon:SetPoint("LEFT", object.spellTimer[index], "LEFT")
		if InvenRaidFrames2CharDB.spellTimer.showIcon[index] then
			object.spellTimer[index].icon:SetWidth(iconSize)
		else
			object.spellTimer[index].icon:SetWidth(0.01)
		end
		object.spellTimer[index].icon:SetHeight(iconSize)
		object.spellTimer[index].count = object.spellTimer[index]:CreateFontString(nil, "OVERLAY", "NumberFontNormalSmall")
		object.spellTimer[index].count:SetPoint("CENTER", object.spellTimer[index].icon, "CENTER", 2, 0)
		object.spellTimer[index].cooldown = object.spellTimer[index]:CreateFontString(nil, "OVERLAY", "GameFontNormal")
		object.spellTimer[index].cooldown:SetTextColor(1, 1, 1)
		object.spellTimer[index].cooldown:SetPoint("LEFT", object.spellTimer[index].icon, "RIGHT", 0, 1)
		object.spellTimer[index]:SetScript("OnUpdate", OnUpdate)
		object.spellTimer[index]:SetScript("OnHide", OnHide)
		pos = IRF2:GetFramePoint(InvenRaidFrames2CharDB.spellTimer.pos[index])
		object.spellTimer[index]:SetPoint(pos[1], object, pos[2], pos[3])
	end
end

local function spellTimer(object)
	for i = 1, 4 do
		ready[i] = nil
	end
	for spell, value in pairs(timerData) do
		if InvenRaidFrames2CharDB.spellTimer.enable[value] then
			if ready[value] == nil then
				name, icon, count, timeLeft = nil
				-- 자신이 시전한 주문 검색
				name, _, icon, count, _, _, timeLeft, ownerUnit = UnitAura(object.vehicleUnit or object.unit, spell, nil, auraFilterPlayer[spell])
				if ownerUnit == 1 or (type(ownerUnit) == "string" and UnitIsUnit("player", ownerUnit)) then
					ownerUnit = true
				else
					ownerUnit = nil
				end
				if not(name and ownerUnit) then
					name = nil
					if not InvenRaidFrames2CharDB.spellTimer.showSelf[value] then
						-- 타인이 시전한 주문 검색
						name, _, icon, count, _, _, timeLeft = UnitAura(object.vehicleUnit or object.unit, spell, nil, auraFilter[spell])
					end
				end
				if name == spell then
					-- 검색된 주문을 프레임에 적용
					object.spellTimer = object.spellTimer or {}
					CreateSpellTimer(object, value)
					object.spellTimer[value].icon:SetTexture(icon)
					object.spellTimer[value].timeLeft = timeLeft or 0
					if InvenRaidFrames2CharDB.spellTimer.showIcon[value] then
						object.spellTimer[value].count:SetText((count and count > 1) and count or "")
						object.spellTimer[value].cooldown:SetTextColor(1, 1, 1)
					else
						if count == nil then
							count = 3
						elseif count == 0 then
							count = 1
						elseif count > 3 then
							count = 3
						end
						object.spellTimer[value].count:SetText("")
						object.spellTimer[value].cooldown:SetTextColor(unpack(stackColor[count]))
					end
					OnUpdate(object.spellTimer[value], 1)
					object.spellTimer[value]:Show()
					ready[value] = true
				end
			end
		end
	end
	if object.spellTimer then
		for i = 1, 4 do
			if ready[i] == nil and object.spellTimer[i] then
				object.spellTimer[i]:Hide()
			end
		end
	end
end

spellTimerHandler:SetScript("OnEvent", function(self, event, unit)
	IRF2:RunUnitFunction(unit, spellTimer)
end)

local function spellTimerMod(object)
	IRF2.objectModules["SpellTimer"] = nil
	spellTimerHandler:RegisterEvent("UNIT_AURA")
	IRF2:RegisterAuraEvent("SpellTimer", spellTimer)
end

IRF2:RegisterObjectModule("SpellTimer", spellTimerMod)

function IRF2:GetSpellTimerNames()
	return timerNames
end

function IRF2:GetSelfTimerData()
	return timerSelfData[select(2, UnitClass("player"))]
end

function IRF2:IsSpellTimer(name, debuff, mine)
	if InvenRaidFrames2CharDB.spellTimer and timerData then
		if timerData[name] and InvenRaidFrames2CharDB.spellTimer.enable[timerData[name]] and ((debuff and isDebuff[name]) or not debuff) then
			if mine then
				if InvenRaidFrames2CharDB.spellTimer.showSelf[timerData[name]] then
					return timerData[name]
				else
					return nil
				end
			else
				return timerData[name]
			end
		end
	end
	return nil
end