local T, C, L, _ = unpack(select(2, ...))

local _, ns = ...
local oUF = ns.oUF or oUF

local ignorePetSpells = {
    115746, -- Felbolt  (Green Imp)
    3110, -- firebolt (imp)
    31707,  -- waterbolt (water elemental)
    85692,  -- Doom Bolt
}

local DUF = {}

------------------------------------------------------------------
--  enter ui test mode       --
------------------------------------------------------------------
SlashCmdList["TESTUI"] = function()
    for _, frames in pairs({"DarkUITargetFrame", "superUIToTFrame", "superUIPetFrame", "superUIFocusFrame", "superUIFocusTargetFrame"}) do
        _G[frames].oldunit = _G[frames].unit
        _G[frames]:SetAttribute("unit", "player")
    end

    for i = 1, MAX_BOSS_FRAMES do
        _G["superUIBossFrame"..i].oldunit = _G["superUIBossFrame"..i].unit
        _G["superUIBossFrame"..i]:SetAttribute("unit", "player")
	end
end

SLASH_TESTUI1 = "/testui"

------------------------------------------------------------------
--  Channeling ticks, based on Castbars by Xbeeps       --
------------------------------------------------------------------
local CastingBarFrameTicksSet
do
    local GetSpellInfo, GetCombatRatingBonus = GetSpellInfo, GetCombatRatingBonus
    local _, class = UnitClass("player")

    -- Negative means not modified by haste
    local BaseTickDuration = { }
    if class == "WARLOCK" then
        BaseTickDuration[GetSpellInfo(689) or ""] = 1 -- Drain Life
        BaseTickDuration[GetSpellInfo(1120) or ""] = 2 -- Drain Soul
        BaseTickDuration[GetSpellInfo(755) or ""] = 1 -- Health Funnel
        BaseTickDuration[GetSpellInfo(5740) or ""] = 2 -- Rain of Fire
        BaseTickDuration[GetSpellInfo(1949) or ""] = 1 -- Hellfire
        BaseTickDuration[GetSpellInfo(103103) or ""] = 1 -- Malefic Grasp
        BaseTickDuration[GetSpellInfo(108371) or ""] = 1 -- Harvest Life
    elseif class == "DRUID" then
        BaseTickDuration[GetSpellInfo(740) or ""] = 2 -- Tranquility
        BaseTickDuration[GetSpellInfo(16914) or ""] = 1 -- Hurricane
        BaseTickDuration[GetSpellInfo(106996) or ""] = 1 -- Astral STORM
        BaseTickDuration[GetSpellInfo(127663) or ""] = -1 -- Astral Communion
    elseif class == "PRIEST" then
        local mind_flay_TickTime = 1
        if IsSpellKnown(157223) then --Enhanced Mind Flay
              mind_flay_TickTime = 2/3
        end
        BaseTickDuration[GetSpellInfo(47540) or ""] = 1 -- Penance
        BaseTickDuration[GetSpellInfo(15407) or ""] =  mind_flay_TickTime -- Mind Flay
        BaseTickDuration[GetSpellInfo(129197) or ""] = mind_flay_TickTime -- Mind Flay (Insanity)
        BaseTickDuration[GetSpellInfo(48045) or ""] = 1 -- Mind Sear
        BaseTickDuration[GetSpellInfo(179337) or ""] = 1 -- Searing Insanity
        BaseTickDuration[GetSpellInfo(64843) or ""] = 2 -- Divine Hymn
        BaseTickDuration[GetSpellInfo(64901) or ""] = 2 -- Hymn of Hope
    elseif class == "MAGE" then
        BaseTickDuration[GetSpellInfo(10) or ""] = 1 -- Blizzard
        BaseTickDuration[GetSpellInfo(5143) or ""] = 0.4 -- Arcane Missiles
        BaseTickDuration[GetSpellInfo(12051) or ""] = 2 -- Evocation
    elseif class == "MONK" then
        BaseTickDuration[GetSpellInfo(117952) or ""] = 1 -- Crackling Jade Lightning
        BaseTickDuration[GetSpellInfo(115175) or ""] = 1 -- Soothing Mist
        BaseTickDuration[GetSpellInfo(113656) or ""] = 1 -- Fists of Fury
        BaseTickDuration[GetSpellInfo(115294) or ""] = -1 -- Mana Tea
    end

    function CastingBarFrameTicksSet(Castbar, unit, name, stop)
        Castbar.ticks = Castbar.ticks or {}
        local function CreateATick()
            local spark = Castbar:CreateTexture(nil, 'OVERLAY', nil, 1)
            spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
            spark:SetVertexColor(1, 1, 1, 1)
            spark:SetBlendMode('ADD')
            spark:SetWidth(10)
            table.insert(Castbar.ticks, spark)
            return spark
        end
        for _,tick in ipairs(Castbar.ticks) do
          tick:Hide()
        end
        if (stop) then return end
        if (Castbar) then
            local baseTickDuration = BaseTickDuration[name]
            local tickDuration
            if (baseTickDuration) then
                if (baseTickDuration > 0) then
                    local castTime = select(7, GetSpellInfo(2060))
                    if (not castTime or (castTime == 0)) then
                        castTime = 2500 / (1 + (GetCombatRatingBonus(CR_HASTE_SPELL) or 0) / 100)
                    end
                    tickDuration = (castTime / 2500) * baseTickDuration
                else
                    tickDuration = -baseTickDuration
                end
            end
            if (tickDuration) then
                local width = Castbar:GetWidth()
                local delta = (tickDuration * width / Castbar.max)
                local i = 1
                while (delta * i) < width do
                    if i > #Castbar.ticks then CreateATick() end
                    local tick = Castbar.ticks[i]
                    tick:SetHeight(Castbar:GetHeight() * 1.5)
                    tick:SetPoint("CENTER", Castbar, "LEFT", delta * i, 0)
                    tick:Show()
                    i = i + 1
                end
            end
        end
    end
end

function DUF.PostCastStart(Castbar, unit, name, castid)
    if (unit == 'pet') then
        Castbar:SetAlpha(1)
        for _, spellID in pairs(ignorePetSpells) do
            if (UnitCastingInfo('pet') == GetSpellInfo(spellID)) then
                Castbar:SetAlpha(0)
            end
        end
    end
    DUF.UpdateCastbarColor(Castbar, unit)
    if (Castbar.SafeZone) then
        Castbar.SafeZone:SetDrawLayer("BORDER", -1)
    end
end

function DUF.PostCastFailed(Castbar, unit, spellname, castid)
    if (Castbar.Text) then
        Castbar.Text:SetText(FAILED) 
    end
        Castbar:SetStatusBarColor(1, 0, 0) -- Red
    if (Castbar.max) then 
        Castbar:SetValue(Castbar.max)
    end
end

function DUF.PostCastInterrupted(Castbar, unit, spellname, castid)
    --Castbar:SetStatusBarColor(1, 0, 0)
    if (Castbar.max) then -- Some spells got trough without castbar
        Castbar:SetValue(Castbar.max)
    end
end

function DUF.PostStop(Castbar, unit, spellname, castid)
    --Castbar:SetValue(Castbar.max)
    if (Castbar.Ticks) then
        CastingBarFrameTicksSet(Castbar, unit, name, true)
    end
end

function DUF.PostChannelStart(Castbar, unit, name)
    if (unit == 'pet' and Castbar:GetAlpha() == 0) then
        Castbar:SetAlpha(1)
    end

    DUF.UpdateCastbarColor(Castbar, unit)
    if Castbar.SafeZone then
        Castbar.SafeZone:SetDrawLayer("BORDER", 1)
    end
    if (Castbar.Ticks) then
        CastingBarFrameTicksSet(Castbar, unit, name)
    end
end

function DUF.UpdateCastbarColor(Castbar, unit)
    if Castbar.Shield:IsShown() then
        --show shield
        Castbar:SetStatusBarColor(0.5, 0.5, 0.5, 1)
        Castbar.Spark:SetVertexColor(0.8, 0.8, 0.8, 1)
    else
        --no shield
        Castbar:SetStatusBarColor(27/255, 147/255, 226/255)
        Castbar.Spark:SetVertexColor(0.8, 0.6, 0, 1)
    end
end

function DUF.CreateFont(parent, fontname, fontHeight, fontStyle)
    local fontStr = parent:CreateFontString(nil, 'OVERLAY')
    fontStr:SetFont(fontname or STANDARD_TEXT_FONT, fontHeight or 12, fontStyle)
    fontStr:SetJustifyH('LEFT')
    fontStr:SetShadowColor(0,0,0)
    fontStr:SetShadowOffset(0.85, -0.85)

    return fontStr
end

function DUF.CreateIcon(f, layer, size, sublevel, anchorframe, anchorpoint1, anchorpoint2, posx, posy)
    local icon = f:CreateTexture(nil, layer, nil, sublevel)
    icon:SetSize(size, size)
    icon:SetPoint(anchorpoint1, anchorframe, anchorpoint2, posx, posy)

    return icon
end

function DUF.FlipTexture(texture)
    if(texture and texture.SetTexCoord) then
        return texture:SetTexCoord(1, 0, 0, 1)
    end
end

function DUF.PostCreateIcon(icons, button)
    button.icon:SetTexCoord(.08, .92, .08, .92)
    button.icon:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2)
    button.icon:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
    button.icon:SetDrawLayer("BACKGROUND", -8)

    button.overlay:SetTexture(C.Media.Texture.border)
    button.overlay:SetTexCoord(0, 1, 0, 1)
    button.overlay:SetDrawLayer("BACKGROUND", -7)
    button.overlay:ClearAllPoints()
    button.overlay:SetAllPoints(button)
    button.overlay:SetVertexColor(0.25, 0.25, 0.25)

    button:CreateShadow()

    --button.overlay.SetVertexColor = T.Dummy
    button.overlay.Hide = T.Dummy
end

function DUF.PostUpdateIcon(icons, unit, icon, index, offset, filter, isDebuff, duration, timeLeft)
	local _, _, _, _, dtype, duration, expirationTime, _, isStealable = UnitAura(unit, index, icon.filter)

	local playerUnits = {
		player = true,
		pet = true,
		vehicle = true,
	}

	if icon.debuff then
		if not UnitIsFriend("player", unit) and not playerUnits[icon.owner] then
			if icons.onlyShowPlayer then
				icon:Hide()
			else
				icon:SetBackdropBorderColor(unpack(C.Media.border_color))
				icon.icon:SetDesaturated(true)
			end
		else
			local color = DebuffTypeColor[dtype] or DebuffTypeColor.none
			icon:SetBackdropBorderColor(color.r, color.g, color.b)
			icon.icon:SetDesaturated(false)
		end
	else
		if (isStealable or ((T.class == "MAGE" or T.class == "PRIEST" or T.class == "SHAMAN" or T.class == "HUNTER") and dtype == "Magic")) and not UnitIsFriend("player", unit) then
			icon:SetBackdropBorderColor(1, 0.85, 0)
		else
			icon:SetBackdropBorderColor(unpack(C.Media.border_color))
		end
		icon.icon:SetDesaturated(false)
	end

	icon.first = true
end

function DUF.PostUpdatePower(Power, unit, cur, max)
    local self = Power:GetParent()

    if (UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit)) or (max == 0) then
        Power:SetValue(0)
        if Power.Value then
            Power.Value:SetText('')
        end

        return
    end

    if not Power.Value then return end
end

function DUF.SetFader(self, config)
    if config ~= nil then
   
        local index = 1
        for k, v in pairs(config) do
            if k == "NormalAlpha" then
                self.NormalAlpha = v
            elseif k == "Range" then
                self.Range = v
                self.outsideRangeAlphaPerc = .3
            else
                if not self.Fader then self.Fader = {} end

                self.Fader[index] = {}
                self.Fader[index][k] = v

                index = index + 1
            end
        end
    end
end

T.Unitframe = DUF