SpellCountdown = LibStub("AceAddon-3.0"):NewAddon("SpellCountdown", "AceConsole-3.0", "AceHook-3.0")

local L = LibStub("AceLocale-3.0"):GetLocale("SpellCountdown", true)
local g_config = LibStub("AceConfig-3.0")
local g_sharedMedia = LibStub("LibSharedMedia-3.0")
local g_dialog = LibStub("AceConfigDialog-3.0")
local g_frameBlacklist = { "TargetFrame", "PetAction", "TotemFrame" }

function SpellCountdown:OnInitialize()

	self.db = LibStub("AceDB-3.0"):New("SpellCountdownDB")

	g_config:RegisterOptionsTable("SpellCountdown", {
		name = "SpellCountdown",
		handler = SpellCountdown,
		type = "group",
		args = {
			description = {
				type = "description",
				name = L["SpellCountdownTitle"],
			},
		},
		{"scd"}
	})

	-- SpellCountdown:Print("SpellCountdown loaded")

end


function SpellCountdown:OnEnable()
	self.font = g_sharedMedia:Fetch('font', g_sharedMedia:GetDefault("font"))
	self:SecureHook(getmetatable(CreateFrame('Cooldown', nil, nil, 'CooldownFrameTemplate')).__index, "SetCooldown")
end

function SpellCountdown:OnDisable()
end

function SpellCountdown:SetCooldown(frame, start, duration)
	
	if SpellCountdown:IsIgnoredFrame(frame:GetName()) then
		return
	end

	if start > 0 and duration > 3 then
		local f = frame.textFrame or SpellCountdown:CreateCountdown(frame, start, duration)
		f.start = start
		f.duration = duration
		f.timeToNextUpdate = 0
		if not f:IsShown() then
			f:Show()
		end
	else
		local f = frame.textFrame
		if f and f:IsShown() then
			f:Hide()
		end
	end
end

function SpellCountdown:CreateCountdown(frame, start, duration)
	frame.textFrame = CreateFrame("Frame", nil, frame:GetParent())
	local textFrame = frame.textFrame

	local cf = CreateFrame("Frame", nil, frame)
	cf:SetScript("OnShow", SpellCountdown.ChildShow)
	cf:SetScript("OnHide", SpellCountdown.ChildHide)

	textFrame:SetAllPoints(frame:GetParent())
	textFrame:SetFrameLevel(textFrame:GetFrameLevel() + 5)
	textFrame:SetToplevel(true)

	textFrame.text = textFrame:CreateFontString(nil, "OVERLAY")
	textFrame.text:SetPoint("CENTER", textFrame, "CENTER", 0, -1)

	textFrame.icon = _G[frame:GetParent():GetName() .. "Icon"] or _G[frame:GetParent():GetName() .. "IconTexture"]

	if textFrame.icon then
		textFrame:SetScript("OnUpdate", SpellCountdown.TextUpdate)
	end

	textFrame:Hide()

	return textFrame
end

function SpellCountdown:ChildShow()
	local f = self:GetParent().textFrame
	if f and not f:IsShown() then
		f:Show()
	end
end

function SpellCountdown:ChildHide()
	local f = self:GetParent().textFrame
	if f and f:IsShown() then
		f:Hide()
	end
end

function SpellCountdown:TextUpdate(...)

	local arg1 = ...
	
	if self.timeToNextUpdate <= 0 or not self.icon:IsVisible() then
		if GetTime() < self.start then
			return
		end

		local remain = self.duration - (GetTime() - self.start)

		if floor(remain + 0.5) > 0 and self.icon:IsVisible() then
			local text, toNextUpdate, size, altcolor = SpellCountdown:GetTimeDetails(remain)

			self.text:SetFont(SpellCountdown.font, size, "OUTLINE")

			color = {r=1, g=1, b=0.2, a=1}
			if altcolor then
				if self.altcolor then
					color = {r=1, g=0, b=0, a=1}
					self.altcolor = nil
				else
					self.altcolor = true
				end
			end
			self.text:SetTextColor(color.r, color.g, color.b)
			self.text:SetText(text)
			self.timeToNextUpdate = toNextUpdate
		else
			self.altcolor = nil
			self:Hide()
		end
	else
		self.timeToNextUpdate = self.timeToNextUpdate - arg1
	end
end

function SpellCountdown:GetTimeDetails(secs)
	-- return time text, time till next textupdate, font size, flag to use alt color
	if secs >= 86400 then
		return ceil(secs / 86400) .. L["d"], mod(secs, 86400), 18
	elseif secs >= 3600 then
		return ceil(secs / 3600) .. L["h"], mod(secs, 3600), 18
	elseif secs >= 600 then
		return ceil(secs / 60) .. L["m"], mod(secs, 60), 18
	elseif secs >= 60 then
		return ceil(secs / 60) .. L["m"], mod(secs, 60), 24
	elseif secs >= 10 then
		return floor(secs + 0.5), secs - floor(secs), 28
	else	
		return floor(secs + 0.5), 0.5, 34, true
	end
end

function SpellCountdown:IsIgnoredFrame(frameName)
	if not frameName or _G[frameName].disableSpellCountdown then
		return true
	end
	for _, v in ipairs(g_frameBlacklist) do
		if strfind(frameName, v) then
			_G[frameName].disableSpellCountdown=1
			return true
		end
	end
end
