local _AddonName, _EchoRaidTools = ...
local _Cooldowns = _EchoRaidTools:GetModule("cooldowns")

local LibSharedMedia = LibStub:GetLibrary ("LibSharedMedia-3.0")
local LibCustomGlow = LibStub:GetLibrary("LibCustomGlow-1.0")

EchoCooldownBaseTemplateMixin = {}
function EchoCooldownBaseTemplateMixin:SetTextFontAndSize(textType)
    local text = self[textType]
    text:SetFont(
        _Cooldowns.GetFontPath(_Cooldowns["Get"..textType.."Font"](self.groupIndex)),
        _Cooldowns["Get"..textType.."Size"](self.groupIndex),
        _Cooldowns["Get"..textType.."FontStyle"](self.groupIndex)
    )
end
function EchoCooldownBaseTemplateMixin:SetTextShadowColor(textType)
    local c = _Cooldowns["Get"..textType.."TextShadowColor"]()
    self[textType]:SetShadowColor(c:GetRGBA())
end
function EchoCooldownBaseTemplateMixin:SetShadowOffsets(textType)
    local x, y = _Cooldowns["Get"..textType.."TextShadowOffsetX"](), _Cooldowns["Get"..textType.."TextShadowOffsetY"]()
    self[textType]:SetShadowOffset(x, y)
end
function EchoCooldownBaseTemplateMixin:SetSpellNameText()
    local spellName = self.spellName
    local type, text = _Cooldowns.GetSpellNameTextAbbreviateType(self.groupIndex)
    if type == "none" then
        text = spellName
    elseif type == "first" then 
        text = spellName:match("^%w+")
    elseif type == "last" then
        text = spellName:match("%w+$")
    elseif type == "ABC" then
        text = spellName:gsub("(%S+) ",function(t) return t:sub(1,1).."." end)
    end
    self.SpellNameText:SetText(text)
end
function EchoCooldownBaseTemplateMixin:SetUnitNameText()
    if _Cooldowns["GetUnitNameTextUseAbbreviate"](self.groupIndex) then
        self.UnitNameText:SetText(_EchoRaidTools.Utf8Sub(self.UnitName, _Cooldowns["GetUnitNameTextAbbreviateNumber"](self.groupIndex)))
    else
        self.UnitNameText:SetText(self.UnitName)
    end
end
function EchoCooldownBaseTemplateMixin:SetAnchor(textType)
    local anchorTo = _Cooldowns["Get"..textType.."AnchorTo"](self.groupIndex)
    anchorTo = anchorTo == "bar" and self.StatusBar or anchorTo == "icon" and self.Icon or self
    self[textType]:ClearAllPoints()
    self[textType]:SetPoint(
        _Cooldowns["Get"..textType.."TextAnchor"](self.groupIndex),
        anchorTo,
        _Cooldowns["Get"..textType.."DisplayAnchor"](self.groupIndex),
        _Cooldowns["Get"..textType.."OffsetX"](self.groupIndex),
        _Cooldowns["Get"..textType.."OffsetY"](self.groupIndex)
    )
end
function EchoCooldownBaseTemplateMixin:SetBorderRegion()
    local region = _Cooldowns.GetBorderRegion(self.groupIndex)
    region = region == "bar" and self.StatusBar or region == "icon" and self.Icon or self
    local x, y = _Cooldowns.GetBorderOffsetX(self.groupIndex), _Cooldowns.GetBorderOffsetY(self.groupIndex)
    self.Border:ClearAllPoints()
    self.Border:SetPoint("TOPLEFT", region,  0-x, y)
    self.Border:SetPoint("BOTTOMRIGHT", region, x, 0 - y)
end
function EchoCooldownBaseTemplateMixin:SetUpBorder()
    local groupIndex = self.groupIndex
    local edgeFile = LibSharedMedia:Fetch("border", _Cooldowns.GetBorder(groupIndex))
    local backDrop = {edgeFile = edgeFile, edgeSize = _Cooldowns.GetBorderSize(groupIndex), bgFile = nil}
    self.Border:SetBackdrop(backDrop)
    local col
    if _Cooldowns.GetBorderUseClassColor(groupIndex) then
        col = self.ClassColor
    elseif _Cooldowns.GetBorderUseFilterColor(groupIndex) then
        col = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, groupIndex)
    else
        col = _Cooldowns.GetBorderColor(groupIndex)
    end
    self.Border:SetBackdropBorderColor(col:GetRGBA())
    self.Border:SetBackdropColor(0,0,0,0)

    self:SetBorderRegion()

    if _Cooldowns.GetUseBorders(groupIndex) then
        self.Border:Show()
    else
        self.Border:Hide()
    end
end

EchoCooldownDisplayTemplateMixin = {}
function EchoCooldownDisplayTemplateMixin:OnLoad()
    self.IconTexture = self.Icon.IconTexture
    self.UnitNameText = self.TextFrame.UnitNameText
    self.DurationText = self.TextFrame.DurationText
    self.SpellNameText = self.TextFrame.SpellNameText
    self.ChargesText = self.TextFrame.ChargesText
    self.isDisplay = true
    self.StatusBar.Spark:ClearAllPoints()
    local height = self:GetHeight()
    self.StatusBar.Spark:SetPoint("TOP", self.StatusBar.BarTexture, "TOPRIGHT", 0, -floor(height/10))
    self.StatusBar.Spark:SetPoint("BOTTOM", self.StatusBar.BarTexture, "BOTTOMRIGHT", 0, floor(height/10))
end
function EchoCooldownDisplayTemplateMixin:RegisterElvUI()
    if not OmniCC and ElvUI and ElvUI[1] and ElvUI[1].CooldownEnabled and ElvUI[1].RegisterCooldown and ElvUI[1]:CooldownEnabled() then
        ElvUI[1]:RegisterCooldown(self.Icon.Cooldown, "EchoRaidTools");
    end
end
function EchoCooldownDisplayTemplateMixin:ShowCooldownNumbers(bool)
    if OmniCC and OmniCC.Cooldown and OmniCC.Cooldown.SetNoCooldownCount then
        OmniCC.Cooldown.SetNoCooldownCount(self.Icon.Cooldown, not bool)
        self.Icon.Cooldown:SetHideCountdownNumbers(true)
    elseif ElvUI and ElvUI[1] and ElvUI[1].CooldownEnabled and ElvUI[1].ToggleCooldown and ElvUI[1]:CooldownEnabled() then
        ElvUI[1]:ToggleCooldown(self.Icon.Cooldown, bool);
        self.Icon.Cooldown:SetHideCountdownNumbers(true)
    else
        self.Icon.Cooldown:SetHideCountdownNumbers(not bool)
    end
end
function EchoCooldownDisplayTemplateMixin:ShowCooldownSwipe()
    self.Icon.Cooldown:SetDrawSwipe(_Cooldowns.GetCooldownSwipe(self.groupIndex))
end
function EchoCooldownDisplayTemplateMixin:ShowCooldownEdge()
    self.Icon.Cooldown:SetDrawEdge(_Cooldowns.GetCooldownEdge(self.groupIndex))
end
function EchoCooldownDisplayTemplateMixin:ShowBar(bool)
    if bool then
        self.StatusBar:Show()
    else
        self.StatusBar:Hide()
    end
    self:SetIconSide()
end
function EchoCooldownDisplayTemplateMixin:SetBarInverse()
    local invert = _Cooldowns.GetBarInverse(self.groupIndex)
    self.StatusBar.invert = invert
end
function EchoCooldownDisplayTemplateMixin:SetBarReverse()
    local reverse = _Cooldowns.GetBarReverse(self.groupIndex)
    self.StatusBar:SetFillStyle(reverse and "REVERSE" or "STANDARD")
    local height = self:GetHeight()
    if reverse then
        self.StatusBar.Spark:ClearAllPoints()
        self.StatusBar.Spark:SetPoint("TOP", self.StatusBar.BarTexture, "TOPLEFT", 0, -floor(height/10))
        self.StatusBar.Spark:SetPoint("BOTTOM", self.StatusBar.BarTexture, "BOTTOMLEFT", 0, floor(height/10))
    else
        self.StatusBar.Spark:ClearAllPoints()
        self.StatusBar.Spark:SetPoint("TOP", self.StatusBar.BarTexture, "TOPRIGHT", 0, -floor(height/10))
        self.StatusBar.Spark:SetPoint("BOTTOM", self.StatusBar.BarTexture, "BOTTOMRIGHT", 0, floor(height/10))
    end
end
function EchoCooldownDisplayTemplateMixin:SetSparkEnable()
    self.sparkEnabled = _Cooldowns.GetBarSpark(self.groupIndex)
    if not self.sparkEnabled then
        if self.StatusBar.Spark:IsShown() then
            self.StatusBar.Spark:Hide()
        end
    else
        if self.OnCD then
            self.StatusBar.Spark:Show()
        end
    end
end
function EchoCooldownDisplayTemplateMixin:ShowSpark()
    if self.sparkEnabled then
        self.StatusBar.Spark:Show()
    end
end
function EchoCooldownDisplayTemplateMixin:ShowIcon(bool)
    if bool then
        self.Icon:Show()
    else
        self.Icon:Hide()
    end
    self:SetIconSide()
end
function EchoCooldownDisplayTemplateMixin:SetIconSide()
    local side = _Cooldowns.GetIconSide(self.groupIndex)
    if side == "left" then
        self.Icon:ClearAllPoints()
        self.Icon:SetPoint("TOPLEFT")
        self.StatusBar:ClearAllPoints()
        if self.Icon:IsShown() then
            self.StatusBar:SetPoint("LEFT", self.Icon, "RIGHT")
            self.StatusBar:SetPoint("RIGHT", self)
        else
            self.StatusBar:SetPoint("LEFT", self)
            self.StatusBar:SetPoint("RIGHT", self)
        end
    else
        self.Icon:ClearAllPoints()
        self.Icon:SetPoint("TOPRIGHT")
        self.StatusBar:ClearAllPoints()
        if self.Icon:IsShown() then
            self.StatusBar:SetPoint("RIGHT", self.Icon, "LEFT")
            self.StatusBar:SetPoint("LEFT", self)
        else
            self.StatusBar:SetPoint("RIGHT", self)
            self.StatusBar:SetPoint("LEFT", self)
        end
    end
end
function EchoCooldownDisplayTemplateMixin:SetDisplayHeight(height)
    self.Icon:SetSize(height, height)
    self.StatusBar:SetHeight(height)
    self:SetHeight(height)
end
function EchoCooldownDisplayTemplateMixin:SetDisplayWidth(width)
    self:SetWidth(width)
end
function EchoCooldownDisplayTemplateMixin:SetDisplayAlpha()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Alpha", self.groupIndex) then
            local stateAlpha = _Cooldowns.GetStateValue(stateDetails.state, "Alpha", "Alpha", self.groupIndex)
            if stateAlpha then
                self:SetAlpha(stateAlpha/100)
                return
            end
        end
    end
    local alpha = _Cooldowns.GetAlpha(self.groupIndex)/100
    self:SetAlpha(alpha)
end
function EchoCooldownDisplayTemplateMixin:UpdateBarForegroundAlpha()
    local alpha = _Cooldowns.BarGetForegroundAlpha(self.groupIndex)/100
    self.StatusBar.BarTexture:SetAlpha(alpha)
end
function EchoCooldownDisplayTemplateMixin:UpdateBarBackgroundAlpha()
    local alpha = _Cooldowns.BarGetBackgroundAlpha(self.groupIndex)/100
    self.StatusBar.Background:SetAlpha(alpha)
end

function EchoCooldownDisplayTemplateMixin:SetDisplayHide()
    if self.states.subGroup and not _Cooldowns.GetGroupSetting(self.states.subGroup, self.groupIndex) then
        self.toBeShown = nil
        self.toBeHidden = true
        _Cooldowns.UpdatePositions(self.groupIndex, nil, true)
        return
    end
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Hide", self.groupIndex) then
            local stateHide = _Cooldowns.GetStateValue(stateDetails.state, "Hide", "Hide", self.groupIndex)
            if stateHide ~= nil then
                if stateHide and (self:IsShown() or self.toBeShown) then
                    self.toBeShown = nil
                    self.toBeHidden = true
                    _Cooldowns.UpdatePositions(self.groupIndex, nil, true)
                elseif (not stateHide) and (not self:IsShown()) then
                    self.toBeShown = true
                    _Cooldowns.UpdatePositions(self.groupIndex, nil, true)
                end
                return
            end
        end
    end
    if not self:IsShown() then
        self.toBeShown = true
        _Cooldowns.UpdatePositions(self.groupIndex)
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateBarColor()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "BarColor", self.groupIndex) then
            if _Cooldowns.GetStateValue(stateDetails.state, "BarColor", "useClassColor", self.groupIndex) then
                self.StatusBar:SetStatusBarColor(self.ClassColor:GetRGB())
                return
            elseif _Cooldowns.GetStateValue(stateDetails.state, "BarColor", "useFilterColor", self.groupIndex) then
                local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
                self.StatusBar:SetStatusBarColor(filterCol:GetRGB())
                return
            else
                local col = _Cooldowns.GetStateValue(stateDetails.state, "BarColor", "barColor", self.groupIndex)
                if col then
                    self.StatusBar:SetStatusBarColor(col:GetRGB())
                    return
                end
            end
        end
    end
    if _Cooldowns.BarGetUseClassColor(self.groupIndex) then
        self.StatusBar:SetStatusBarColor(self.ClassColor:GetRGB())
    elseif _Cooldowns.BarGetUseFilterColor(self.groupIndex) then
        local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
        self.StatusBar:SetStatusBarColor(filterCol:GetRGB())
    else
        self.StatusBar:SetStatusBarColor(_Cooldowns.BarGetBarColor(self.groupIndex):GetRGB())
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateBarBackgroundColor()
    if _Cooldowns.BarGetBackgroundUseClassColor(self.groupIndex) then
        self.StatusBar.Background:SetVertexColor(self.ClassColor:GetRGB())
    elseif _Cooldowns.BarGetBackgroundUseFilterColor(self.groupIndex) then
        local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
        self.StatusBar.Background:SetVertexColor(filterCol:GetRGB())
    else
        self.StatusBar.Background:SetVertexColor(_Cooldowns.BarGetBarBackgroundColor(self.groupIndex):GetRGB())
    end
end

function EchoCooldownDisplayTemplateMixin:SetStatusBarTexture()
    self.StatusBar:SetStatusBarTexture(_Cooldowns.GetStatusBarTexture(_Cooldowns.BarGetBarTexture(self.groupIndex)))
end
function EchoCooldownDisplayTemplateMixin:SetStatusBarBackgroundTexture()
    self.StatusBar.Background:SetTexture(_Cooldowns.GetStatusBarTexture(_Cooldowns.BarGetBarBackgroundTexture(self.groupIndex)))
end

function EchoCooldownBaseTemplateMixin:SetTextColor(textType) -- delete later
    if _Cooldowns["Get"..textType.."ClassColor"](self.groupIndex) then
        self[textType]:SetTextColor(self.ClassColor:GetRGBA())
    elseif _Cooldowns["Get"..textType.."FilterColor"](self.groupIndex) then
        local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
        self[textType]:SetTextColor(filterCol:GetRGBA())
    else
        self[textType]:SetTextColor(_Cooldowns["Get"..textType.."Color"](self.groupIndex):GetRGBA())
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateTextColors(textType)
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, textType.." Color", self.groupIndex) then
            if _Cooldowns.GetStateValue(stateDetails.state, textType.." Color", textType.."ClassColor", self.groupIndex) then
                self[textType]:SetTextColor(self.ClassColor:GetRGBA())
                return
            elseif _Cooldowns.GetStateValue(stateDetails.state, textType.." Color", textType.."FilterColor", self.groupIndex) then
                local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
                self[textType]:SetTextColor(filterCol:GetRGBA())
                return
            else
                local col = _Cooldowns.GetStateValue(stateDetails.state, textType.." Color", textType.."Color", self.groupIndex)
                if col then
                    self[textType]:SetTextColor(col:GetRGBA())
                    return
                end
            end
        end
    end
    if _Cooldowns["Get"..textType.."ClassColor"](self.groupIndex) then
        self[textType]:SetTextColor(self.ClassColor:GetRGBA())
    elseif _Cooldowns["Get"..textType.."FilterColor"](self.groupIndex) then
        local filterCol = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
        self[textType]:SetTextColor(filterCol:GetRGBA())
    else
        self[textType]:SetTextColor(_Cooldowns["Get"..textType.."Color"](self.groupIndex):GetRGBA())
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateAllTextColors()
    for _, textType in pairs(_Cooldowns.types.textTypes) do
        self:UpdateTextColors(textType)
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateTextEnable(textType)
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, textType.." Enable", self.groupIndex) then
            local textEnable = _Cooldowns.GetStateValue(stateDetails.state, textType.." Enable", textType.."Enable", self.groupIndex)
            if textEnable ~= nil then
                if textEnable then
                    self[textType]:Show()
                else
                    self[textType]:Hide()
                end
                return
            end
        end
    end
    if _Cooldowns["Get"..textType.."Enable"](self.groupIndex) then
        if textType == "DurationText" then
            if self.OnCD then
                self[textType]:Show()
            end
        elseif textType == "ChargesText" then
            if self.count > 1 or (self.count > 0 and self.OnCD) then
                self[textType]:Show()
            end
        else
            self[textType]:Show()
        end
    elseif self[textType]:IsShown() then
        self[textType]:Hide()
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateAllTextEnable()
    for _, textType in pairs(_Cooldowns.types.textTypes) do
        self:UpdateTextEnable(textType)
    end
end
function EchoCooldownDisplayTemplateMixin:SetDurationPrecision()
    self.durationThreshold = _Cooldowns.GetDurationTextThreshold(self.groupIndex)
    self.durationDecimals = _Cooldowns.GetDurationTextDecimals(self.groupIndex)
end

function EchoCooldownDisplayTemplateMixin:UpdateBarEnable()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Enable Bars", self.groupIndex) then
            local barEnable = _Cooldowns.GetStateValue(stateDetails.state, "Enable Bars", "enableBar", self.groupIndex)
            if barEnable then
                if not self.StatusBar:IsShown() then
                    self.StatusBar:Show()
                    if self.Icon:IsShown() then
                        self.StatusBar:SetPoint("LEFT", self.Icon, "RIGHT")
                    else
                        self.StatusBar:SetPoint("LEFT", self)
                    end
                end
            else
                if self.StatusBar:IsShown() then
                    self.StatusBar:Hide()
                end
            end
            return
        end
    end
    if _Cooldowns.GetEnableBar(self.groupIndex) then
        if not self.StatusBar:IsShown() then
            self.StatusBar:Show()
            if self.Icon:IsShown() then
                self.StatusBar:SetPoint("LEFT", self.Icon, "RIGHT")
            else
                self.StatusBar:SetPoint("LEFT", self)
            end
        end
    else
        if self.StatusBar:IsShown() then
            self.StatusBar:Hide()
        end
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateIconEnable()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Enable Icons", self.groupIndex) then
            local iconEnable = _Cooldowns.GetStateValue(stateDetails.state, "Enable Icons", "enableIcon", self.groupIndex)
            if iconEnable then
                if not self.Icon:IsShown() then
                    self.Icon:Show()
                    self.Icon:SetSize(self:GetHeight(), self:GetHeight())
                    self.StatusBar:SetPoint("LEFT", self.Icon, "RIGHT")
                end
            else
                if self.Icon:IsShown() then
                    self.Icon:Hide()
                    self.StatusBar:SetPoint("LEFT", self)
                end
            end
            return
        end
    end
    if _Cooldowns.GetEnableIcon(self.groupIndex) then
        if not self.Icon:IsShown() then
            self.Icon:Show()
            self.Icon:SetSize(self:GetHeight(), self:GetHeight())
            self.StatusBar:SetPoint("LEFT", self.Icon, "RIGHT")
        end
    else
        if self.Icon:IsShown() then
            self.Icon:Hide()
            self.StatusBar:SetPoint("LEFT", self)
        end
    end
end

function EchoCooldownDisplayTemplateMixin:UpdateIconColor()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "IconColor", self.groupIndex) then
            local col = _Cooldowns.GetStateValue(stateDetails.state, "IconColor", "iconColor", self.groupIndex)
            if col then
                self.Icon.IconTexture:SetVertexColor(col:GetRGBA())
                return
            end
        end
    end
    self.Icon.IconTexture:SetVertexColor(_Cooldowns.GetIconColor(self.groupIndex):GetRGBA())
end

function EchoCooldownDisplayTemplateMixin:UpdateBorderColor()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "BorderColor", self.groupIndex) then
            local col
            if _Cooldowns.GetStateValue(stateDetails.state, "BorderColor", "useBorderClassColor", self.groupIndex) then
                col = self.ClassColor
            elseif _Cooldowns.GetStateValue(stateDetails.state, "BorderColor", "useBorderFilterColor", self.groupIndex) then
                col = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
            else
                col = _Cooldowns.GetStateValue(stateDetails.state, "BorderColor", "BorderColor", self.groupIndex)
            end
            self.Border:SetBackdropBorderColor(col:GetRGBA())
            self.Border:SetBackdropColor(0,0,0,0)
            return
        end
    end
    local col
    if _Cooldowns.GetBorderUseClassColor(self.groupIndex) then
        col = self.ClassColor
    elseif _Cooldowns.GetBorderUseFilterColor(self.groupIndex) then
        col = self.filter <= _Cooldowns.numFilters and _Cooldowns.filters.GetColor(self.filter, self.groupIndex) or _Cooldowns.customFilters.GetColor(self.filter - _Cooldowns.numFilters, self.groupIndex)
    else
        col = _Cooldowns.GetBorderColor(self.groupIndex)
    end
    self.Border:SetBackdropBorderColor(col:GetRGBA())
    self.Border:SetBackdropColor(0,0,0,0)
end
function EchoCooldownDisplayTemplateMixin:UpdateBorderShow()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Enable Borders", self.groupIndex) then
            local borderEnable = _Cooldowns.GetStateValue(stateDetails.state, "Enable Borders", "UseBorder", self.groupIndex)
            if borderEnable ~= nil then
                if borderEnable then
                    self.Border:Show()
                else
                    self.Border:Hide()
                end
                return
            end
        end
    end
    if _Cooldowns.GetUseBorders(self.groupIndex) then
        self.Border:Show()
    else
        self.Border:Hide()
    end
end
function EchoCooldownBaseTemplateMixin:StartFlash()
    if self:IsShown() then
        self.Flash:Play()
    end
end
function EchoCooldownBaseTemplateMixin:StopFlash()
    if self.Flash:IsPlaying() then
        self.Flash:Stop()
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateFlashShow()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Enable Flash", self.groupIndex) then
            local flashEnable = _Cooldowns.GetStateValue(stateDetails.state, "Enable Flash", "UseFlash", self.groupIndex)
            if flashEnable ~= nil then
                if flashEnable then
                    self:StartFlash()
                else
                    self:StopFlash()
                end
                return
            end
        end
    end
    if _Cooldowns.GetUseFlash(self.groupIndex) then
        self:StartFlash()
    else
        self:StopFlash()
    end
end
function EchoCooldownBaseTemplateMixin:ShowGlow()
    LibCustomGlow.PixelGlow_Start(self.Glow)
    self.Glow:Show()
end
function EchoCooldownBaseTemplateMixin:HideGlow()
    LibCustomGlow.PixelGlow_Stop(self.Glow)
    self.Glow:Hide()
end
function EchoCooldownBaseTemplateMixin:SetGlowRegion()
    local region = _Cooldowns.GetGlowRegion(self.groupIndex)
    region = region == "bar" and self.StatusBar or region == "icon" and self.Icon or self
    local x, y = 0,0
    self.Glow:ClearAllPoints()
    self.Glow:SetPoint("TOPLEFT", region,  0-x, y)
    self.Glow:SetPoint("BOTTOMRIGHT", region, x, 0 - y)
end
function EchoCooldownDisplayTemplateMixin:UpdateGlowShow()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Enable Glow", self.groupIndex) then
            local glowEnable = _Cooldowns.GetStateValue(stateDetails.state, "Enable Glow", "UseGlow", self.groupIndex)
            if glowEnable ~= nil then
                if glowEnable then
                    self:ShowGlow()
                else
                    self:HideGlow()
                end
                return
            end
        end
    end
    if _Cooldowns.GetUseGlow(self.groupIndex) then
        self:ShowGlow()
    else
        self:HideGlow()
    end
end

function EchoCooldownDisplayTemplateMixin:UpdateDesaturateIcon()
    for _, stateDetails in ipairs(_Cooldowns.types.availableStates) do
        if self.states[stateDetails.state] and _Cooldowns.GetPropertyOverridden(stateDetails.state, "Desaturate Icons", self.groupIndex) then
            local Desat = _Cooldowns.GetStateValue(stateDetails.state, "Desaturate Icons", "desaturateIcon", self.groupIndex)
            if Desat ~= nil then
                if Desat then
                    self.Icon.IconTexture:SetDesaturated(true)
                else
                    self.Icon.IconTexture:SetDesaturated(false)
                end
                return
            end
        end
    end
    if _Cooldowns.GetDesaturateIcon(self.groupIndex) then
        self.Icon.IconTexture:SetDesaturated(true)
    else
        self.Icon.IconTexture:SetDesaturated(false)
    end
end
function EchoCooldownDisplayTemplateMixin:UpdateStates()
    self:SetDisplayAlpha()
    self:SetDisplayHide()
    self:UpdateBarEnable()
    self:UpdateIconEnable()
    self:UpdateIconColor()
    self:UpdateBarColor()
    self:UpdateBorderShow()
    self:UpdateBorderColor()
    self:UpdateAllTextColors()
    self:UpdateAllTextEnable()
    self:UpdateDesaturateIcon()
    self:UpdateGlowShow()
    self:UpdateFlashShow()

end
function EchoCooldownDisplayTemplateMixin:SetCurrentStates(bool)
    if not _Cooldowns.unitFlags[self.unit] then
        _Cooldowns.UpdateUnitFlags(self.unit)
    end
    local update = false
    if self.states.UnitDead == nil or self.states.UnitDead ~=  _Cooldowns.unitFlags[self.unit].dead then
        self.states.UnitDead = _Cooldowns.unitFlags[self.unit].dead
        update = true
    end
    if self.states.UnitAway == nil or self.states.UnitAway ~= _Cooldowns.unitFlags[self.unit].away then
        self.states.UnitAway = _Cooldowns.unitFlags[self.unit].away
        update = true
    end
    if self.states.subGroup == nil or self.states.subGroup ~= _Cooldowns.unitFlags[self.unit].subGroup then
        self.states.subGroup = _Cooldowns.unitFlags[self.unit].subGroup
        update = true
    end
    if self.states.OnCD == nil or self.states.OnCD ~= self.OnCD then
        self.states.OnCD = self.OnCD
        update = true
    end
    if self.states.buffUp == nil or self.states.buffUp ~= self.buffUp then
        self.states.buffUp = self.buffUp
        update = true
    end
    if self.states.outOfRange == nil or self.states.outOfRange ~= _Cooldowns.unitFlags[self.unit].outOfRange then
        self.states.outOfRange = _Cooldowns.unitFlags[self.unit].outOfRange
        update = true
    end
    self.flagged = self.states.UnitDead and 4 or self.states.UnitAway and 3 or 0
    if update or bool then
       self:UpdateStates()
    end
end
function EchoCooldownDisplayTemplateMixin:StartBuff()
    if self.uptimeCallback then self.uptimeCallback:Cancel() end
    self.uptimeCallback = C_Timer.NewTimer(self.buffExpirationTime - GetTime(), function() self:EndBuff() end)
    if _Cooldowns.GetEnableUptimes(self.groupIndex) then
        self.overrideDuration = true
        self.Icon.Cooldown:SetCooldown(self.start, self.buffDuration)
        self.Icon.Cooldown:SetReverse()
        self.StatusBar:SetMinMaxValues(self.start, self.buffExpirationTime)
    end
end
function EchoCooldownDisplayTemplateMixin:EndBuff()
    if self.uptimeCallback then self.uptimeCallback:Cancel() end
    self.overrideDuration = false
    self.buffExpirationTime = nil
    self.buffUp = nil
    self.Icon.Cooldown:SetCooldown(self.start, self.duration)
    self.StatusBar:SetMinMaxValues(self.start, self.expirationTime)
    self:SetCurrentStates()
end

local getRemainingTimeString = function(self, expirationTime)
    local t = GetTime()
    if expirationTime > t then
        local remaining = expirationTime - GetTime()
        local mins, secs = floor(remaining/60), floor(remaining % 60)
        if remaining < self.durationThreshold then
            if self.durationDecimals == 0 then
                return secs
            else
                local formatString = format("%%.%df", self.durationDecimals)
                return format(formatString, remaining)
            end
        else
            return mins > 0 and format("%d:%02.0f", mins, secs) or secs
        end
    end
end

function EchoCooldownDisplayTemplateMixin:durationUpdate()
    if not self:IsShown() then return end
    local expirationTime = self.expirationTime
    local invert = self.StatusBar.invert
    if self.overrideDuration then
        expirationTime = self.buffExpirationTime
        invert = not invert
    end
    if _Cooldowns.GetDurationTextEnable(self.groupIndex) then
        local timeString = getRemainingTimeString(self, expirationTime)
        self.DurationText:SetText(timeString)
    end
    if self.StatusBar:IsShown() then
        local value
        if invert then
            local remaining = expirationTime - GetTime()
            value = self.start + remaining
        else
            value = GetTime()
        end

        self.StatusBar:SetValue(value)
    end
end


EchoCooldownsDraggableAnchorMixin = {}
function EchoCooldownsDraggableAnchorMixin:OnLoad()
    self:RegisterForDrag("LeftButton")
    self.IsLocked = true
    self:SetAlpha(0)
    self:SetClampRectInsets(15, -15, -15, 15)
end
function EchoCooldownsDraggableAnchorMixin:OnDragStart()
    if not self.isLocked then
        self:StartMoving()
    end
end
function EchoCooldownsDraggableAnchorMixin:OnDragStop()
    self:StopMovingOrSizing()
    local left, bottom, w,h = self:GetRect()
    local x = Round((left + w/2) - (GetScreenWidth()/2))
    local y = Round((bottom + h/2) - (GetScreenHeight()/2))
    _Cooldowns.SetAnchorOffsetX(x, self.groupIndex)
    _Cooldowns.SetAnchorOffsetY(y, self.groupIndex)
    _Cooldowns.controls.MainOffsetX:Update()
    _Cooldowns.controls.MainOffsetY:Update()
end
function EchoCooldownsDraggableAnchorMixin:Unlock()
    self:EnableMouse(true)
    self:SetAlpha(1)
    self.IsLocked = false
    self.Background.AnimationGroup:Play()
end
function EchoCooldownsDraggableAnchorMixin:Lock()
    self.Background.AnimationGroup:Stop()
    self:EnableMouse(false)
    self:SetAlpha(0)
    self.IsLocked = true
end
function EchoCooldownsDraggableAnchorMixin:OnEnter()
    self.GroupName:Show()
end
function EchoCooldownsDraggableAnchorMixin:OnLeave()
    self.GroupName:Hide()
end

EchoCooldownsOutlineMixin = {}
function EchoCooldownsOutlineMixin:OnShow()
    self.AnimationGroup:Play()
end
function EchoCooldownsOutlineMixin:OnHide()
    self.AnimationGroup:Stop()
end