local _, ns = ...
local B, C, L, DB = unpack(ns)
local UF = B:GetModule("UnitFrames")


local castTimeFormatter = C_StringUtil.CreateSecondsFormatter()
castTimeFormatter:SetDefaultAbbreviation(Enum.SecondsFormatterAbbreviation.OneLetter)
castTimeFormatter:SetMinInterval(Enum.SecondsFormatterInterval.Seconds)
castTimeFormatter:SetMillisecondsThreshold(60)

function UF.CreateCastbarTimeBinding()
	local binding = C_DurationUtil.CreateDurationTextBinding()
	binding:SetTextFormat("{}/{}", {
		{
			property = Enum.DurationTextBindingProperty.ElapsedDuration,
			formatter = castTimeFormatter,
		},
		{
			property = Enum.DurationTextBindingProperty.TotalDuration,
			formatter = castTimeFormatter,
		},
	})
	return binding
end

local function HideInterruptReadyHint(self)
	if self.interruptReadyHint then self.interruptReadyHint:Hide() end
	if self.interruptReadyLabel then self.interruptReadyLabel:Hide() end
	self.interruptHintActive = nil
end

local function UpdateInterruptReadyHint(self, notInterruptible)
	if not self.interruptReadyHint then
		HideInterruptReadyHint(self)
		return
	end

	local tracker = B:GetModule("InterruptTracker")
	if not tracker or not tracker.GetPlayerInterruptCooldown then
		HideInterruptReadyHint(self)
		return
	end

	local _, duration, isOnGCD = tracker:GetPlayerInterruptCooldown()
	if not duration or isOnGCD then
		HideInterruptReadyHint(self)
		return
	end

	self.interruptReadyHint.binding:SetDuration(duration)
	self.interruptReadyHint:Show()
	self.interruptReadyLabel:Show()
	self.interruptReadyHint:SetAlphaFromBoolean(notInterruptible, 0, 1)
	self.interruptReadyLabel:SetAlphaFromBoolean(notInterruptible, 0, 1)
	self.interruptHintActive = true
end

function UF:UpdateCastbarGlow(spellID)
	if self.barGlow then
		local isImportant = C.db["Nameplate"]["CastbarGlow"] and C_Spell.IsSpellImportant(spellID)
		self.barGlow:SetAlphaFromBoolean(isImportant, .7, 0)
	end
end

function UF:UpdateSpellTarget(unit)
	if not C.db["Nameplate"]["CastTarget"] then return end
	if self.spellTarget then
		local isTargetingYou = UnitIsSpellTarget(unit, "player")
		if self.isYou then
			self.isYou:SetAlphaFromBoolean(isTargetingYou, 1, 0)
		end
		self.spellTarget:SetAlphaFromBoolean(isTargetingYou, 0, 1)

		if UnitShouldDisplaySpellTargetName(unit) then
			self.spellTarget:SetText(UnitSpellTargetName(unit))
			local classColor = C_ClassColor.GetClassColor(UnitSpellTargetClass(unit))
			if classColor then
				self.spellTarget:SetTextColor(classColor:GetRGB())
			else
				self.spellTarget:SetTextColor(1, 1, 1)
			end
		else
			self.spellTarget:SetText("")
			self.spellTarget:SetTextColor(1, 1, 1)
		end
	end
end

function UF:UpdateCastBarColors()
	local castingColor = C.db["UFs"]["CastingColor"]
	local ownCastColor = C.db["UFs"]["OwnCastColor"]
	local notInterruptColor = C.db["UFs"]["NotInterruptColor"]

	UF.CastingColor = UF.CastingColor or CreateColor(0, 0, 0)
	UF.OwnCastColor = UF.OwnCastColor or CreateColor(0, 0, 0)
	UF.NotInterruptColor = UF.NotInterruptColor or CreateColor(0, 0, 0)

	UF.CastingColor:SetRGB(castingColor.r, castingColor.g, castingColor.b)
	UF.OwnCastColor:SetRGB(ownCastColor.r, ownCastColor.g, ownCastColor.b)
	UF.NotInterruptColor:SetRGB(notInterruptColor.r, notInterruptColor.g, notInterruptColor.b)
end

function UF:UpdateCastBarColor(unit, spellID, notInterruptible)
	if unit == "player" then
		self:SetStatusBarColor(UF.OwnCastColor:GetRGB())
	elseif not UnitIsUnit(unit, "player") then
		self:GetStatusBarTexture():SetVertexColorFromBoolean(notInterruptible, UF.NotInterruptColor, UF.CastingColor)
	else
		self:SetStatusBarColor(UF.CastingColor:GetRGB())
	end
	UF.UpdateSpellTarget(self, unit)
	UF.UpdateCastbarGlow(self, spellID)
	if unit ~= "player" then
		UpdateInterruptReadyHint(self, notInterruptible)
	else
		HideInterruptReadyHint(self)
	end
end

function UF:Castbar_FailedColor(unit)
	self:SetStatusBarColor(1, .1, 0)
	HideInterruptReadyHint(self)
end

function UF:Castbar_UpdateInterrupted(unit, spellID, interruptedBy)
	self:SetStatusBarColor(1, .1, 0)
	HideInterruptReadyHint(self)

	if not C.db["Nameplate"]["Interruptor"] or not self.spellTarget or not B:NotSecretValue(interruptedBy) then return end
	if not interruptedBy then return end

	local sourceName = UnitNameFromGUID(interruptedBy)
	if not B:NotSecretValue(sourceName) or not sourceName then return end

	local _, class = GetPlayerInfoByGUID(interruptedBy)
	class = class or "PRIEST"
	local classColor = C_ClassColor.GetClassColor(class)
	self.Text:SetText(INTERRUPTED.." > "..classColor:WrapTextInColorCode(sourceName))
	self.Time:SetText("")
end

-- Empower Pips
UF.PipColors = {
	[1] = {.08, 1, 0, .5},
	[2] = {1, .1, .1, .5},
	[3] = {1, .5, 0, .5},
	[4] = {.1, .7, .7, .5},
	[5] = {0, 1, 1, .5},
	[6] = {0,.5, 1, .5},
}

function UF:CreatePip(stage)
	local _, height = self:GetSize()

	local pip = CreateFrame("Frame", nil, self, "CastingBarFrameStagePipTemplate")
	pip.BasePip:SetTexture(DB.bdTex)
	pip.BasePip:SetVertexColor(0, 0, 0)
	pip.BasePip:SetWidth(C.mult)
	pip.BasePip:SetHeight(height)
	pip.tex = pip:CreateTexture(nil, "ARTWORK", nil, 2)
	pip.tex:SetTexture(DB.normTex)
	pip.tex:SetVertexColor(unpack(UF.PipColors[stage]))

	return pip
end

function UF:PostUpdatePips(numStages)
	if not numStages then return end

	local pips = self.Pips
	local num = #numStages

	for stage = 1, num do
		local pip = pips[stage]
		if stage == num then
			local firstPip = pips[1]
			local anchor = pips[num]
			firstPip.tex:SetPoint("BOTTOMRIGHT", self)
			firstPip.tex:SetPoint("TOPLEFT", anchor.BasePip, "TOPRIGHT")
		end

		if stage ~= 1 then
			local anchor = pips[stage-1]
			pip.tex:SetPoint("BOTTOMRIGHT", pip.BasePip, "BOTTOMLEFT")
			pip.tex:SetPoint("TOPLEFT", anchor.BasePip, "TOPRIGHT")
		end
	end
end

