local Srendarr = _G['Srendarr']
local L = Srendarr:GetLocale()

local ATTRIBUTE_VISUAL_POWER_SHIELDING  = ATTRIBUTE_VISUAL_POWER_SHIELDING
local EVENT_PLAYER_DEAD                 = EVENT_PLAYER_DEAD
local IsSlotUsed                        = IsSlotUsed
local GetSlotName                       = GetSlotName
local GetSlotTexture                    = GetSlotTexture
local GetSlotBoundId                    = GetSlotBoundId
local GetSlotItemSound                  = GetSlotItemSound
local GetAbilityDuration                = GetAbilityDuration
local GetAbilityCastInfo                = GetAbilityCastInfo
local GetGameTimeMilliseconds           = GetGameTimeMilliseconds

local db, auraFrameLong, auraFrameShort, auraFrameDebuffs

-- HOTBAR WATCHLIST --
local watchlist = {
    [3] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [4] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [5] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [6] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [7] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [8] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
    [9] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0},
}
local triggeredSlots = {}

function Srendarr:GetTriggeredSlotNum(name)
    return triggeredSlots[name]
end

do -- BUTTON HOOKS FOR CAST DETECTION
    local CostFail              = HasCostFailure
    local ReqFail               = HasRequirementFailure
    local WeaponFail            = HasWeaponSlotFailure
    local TargetFail            = HasTargetFailure
    local RangeFail             = HasRangeFailure
    local StatusFail            = HasStatusEffectFailure
    local FallingFail           = HasFallingFailure
    local SwimmingFail          = HasSwimmingFailure
    local MountedFail           = HasMountedFailure
    local RezFail               = HasReincarnatingFailure
    local GetSlotCooldownInfo   = GetSlotCooldownInfo
    local zomax                 = zo_max
    local B_PRESSED             = BSTATE_PRESSED
    local B_NORMAL              = BSTATE_NORMAL
    local SPAM_THRESHOLD        = Srendarr.SPAM_THRESHOLD

    local buffFrame, debuffFrame

    local ActionButton_SetState_Orig
    local QuickSlotButton_SetState_Orig

    local flags = {
        [3] = false,
        [4] = false,
        [5] = false,
        [6] = false,
        [7] = false,
        [8] = false,
        [9] = false,
    }
    local lastCast = {
        [3] = 0,
        [4] = 0,
        [5] = 0,
        [6] = 0,
        [7] = 0,
        [8] = 0,
        [9] = 0,
    }
    local watched = {}

    local function ActionFailed(slot)
        if (CostFail(slot) or ReqFail(slot) or WeaponFail(slot) or TargetFail(slot)
            or RangeFail(slot) or StatusFail(slot) or FallingFail(slot)
            or SwimmingFail(slot) or MountedFail(slot) or RezFail(slot)
        ) then
            return true
        end
        return false
    end

    local function ActionButton_SetState_Hook(self, state, locked)
        ActionButton_SetState_Orig(self, state, locked)

        -- Trigger event for target debuff list
        Srendarr:OnTargetChanged()
        local slot = self.slotNum
        if (watched[slot]) then -- only proceed if this button is being watched
            if (state == B_PRESSED) then
                flags[slot] = true
            elseif (state == B_NORMAL) then
                if (flags[slot]) then -- button was just pressed, this is a cast attempt
                    local start = GetGameTimeMilliseconds() / 1000

                    if (not ActionFailed(slot) and (start > lastCast[slot] + SPAM_THRESHOLD)) then -- avoid failure and button mashing
                        local casting = watchlist[slot]

                        local proc = Srendarr:HasProc(casting.name) --for now just Crystal Fragments
                        if proc then
                            if buffFrame.k_auraActive[proc] then
                                casting.cast = 0
                            end
                        end

                        -- @todo Here Buff / Debuff section
                        if (casting.buff) then -- buff in this slot
                            buffFrame:AddAura(1, 1, casting.name, casting.texture, (start + casting.cast), (start + casting.cast + casting.buff), casting.isShield, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_BUFF)
                        end

                        if (casting.debuff) then -- debuff in this slot
                            debuffFrame:AddAura(1, 2, casting.name, casting.texture, (start + casting.cast), (start + casting.cast + casting.debuff), casting.isShield, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_DEBUFF)
                        end

                        lastCast[slot] = start

                        --check for class passive effects
                        local name, buff, debuff, texture, abilityId = Srendarr:GetClassPassiveSkillEffect(casting.name)
                        if (name) then
                            if (buff) then
                                buffFrame:AddAura(1, 1, name, texture, (start + casting.cast), (start + casting.cast) + buff, false, nil, nil, abilityId, BUFF_EFFECT_TYPE_BUFF)
                            end

                            if (debuff) then
                                debuffFrame:AddAura(1, 2, name, casting.texture, (start + casting.cast), (start + casting.cast) + debuff, false, nil, nil, abilityId, BUFF_EFFECT_TYPE_DEBUFF)
                            end
                        end
                    end
                end
                flags[slot] = false
            end
        end
    end

    local function QuickSlotButton_SetState_Hook(self, state, locked)
        QuickSlotButton_SetState_Orig(self, state, locked)

        if (watched[9]) then
            local start = GetGameTimeMilliseconds() / 1000

            if (start > lastCast[9]) then
                local button = ZO_ActionBar_GetButton(9)
                local slotNum = button:GetSlot()
                if button.useable then
                    local timeLeft = GetSlotCooldownInfo(slotNum)

                    lastCast[9] = start + zomax((timeLeft / 1000), SPAM_THRESHOLD)

                    local casting = watchlist[9]

                    if (casting.buff) then
                        buffFrame:AddAura(1, 1, casting.name, casting.texture, start, start + casting.buff, false, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_BUFF)
                    end

                    if (casting.debuff) then
                        debuffFrame:AddAura(1, 2, casting.name, casting.texture, start, start + casting.debuff, false, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_DEBUFF)
                    end
                end
            end
        end
    end

    function Srendarr:SetupActionButtonHooks()
        buffFrame   = Srendarr.auraFrames[1] -- short term always go to the first frame
        debuffFrame = Srendarr.auraFrames[3] -- debuffs always go to the third frame

        ActionButton_SetState_Orig = ActionButton3Button.SetState
        ActionButton3Button.SetState = ActionButton_SetState_Hook
        ActionButton4Button.SetState = ActionButton_SetState_Hook
        ActionButton5Button.SetState = ActionButton_SetState_Hook
        ActionButton6Button.SetState = ActionButton_SetState_Hook
        ActionButton7Button.SetState = ActionButton_SetState_Hook
        --ultimate
        ActionButton8Button.SetState = ActionButton_SetState_Hook
        --quickslot
        QuickSlotButton_SetState_Orig = ActionButton9Button.SetState
        ActionButton9Button.SetState = QuickSlotButton_SetState_Hook
    end

    function Srendarr:ConfigureActionButtonWatcher(slotNum)
        watched[slotNum] = (watchlist[slotNum].name) and true or false
    end
end

function Srendarr.OnActionSlotChanged(evt, slotNum)
    if (slotNum < 3 or slotNum > 8) then return end

    local actionButton
    if slotNum ~= 8 then
        for ability, slot in pairs(triggeredSlots) do
            if (slot == slotNum) then
                triggeredSlots[ability] = nil
            end
        end

        actionButton = ZO_ActionBar_GetButton(slotNum)
        if Srendarr:IsPlayingProcAnimation(actionButton) then
            Srendarr:StopProcAnimations(actionButton)
        end
    end

    if (IsSlotUsed(slotNum)) then
        local ability = GetSlotName(slotNum)
        local abilityId = GetSlotBoundId(slotNum)
        local texture = GetSlotTexture(slotNum)
        local buff, debuff, cast, corrections = Srendarr:GetAuraData(ability)

        --corrections
        local duration = GetAbilityDuration(abilityId)
        if (duration > 0 and corrections ~= 3) then
            if (buff and buff > 0 and (not corrections or corrections == 1)) then
                buff = duration / 1000
            end
            if (debuff and debuff > 0 and (not corrections or corrections == 2)) then
                debuff = duration / 1000
            end
        end
        local channeled, castTime, channelTime = GetAbilityCastInfo(abilityId)
        if (castTime > 0) then
            cast = castTime / 1000
        end

        if (not Srendarr.db.showDebuff) then
            debuff = false -- if not showing debuffs, then don't track
        end

        if (buff or debuff) then
            local data      = watchlist[slotNum]
            data.name       = ability
            data.buff       = buff
            data.debuff     = debuff
            data.cast       = cast
            data.texture    = texture
            data.isShield   = Srendarr:IsDamageShield(ability)
            data.abilityId  = abilityId
        else
            watchlist[slotNum].name = false
        end

        --proc animaitons
        if slotNum ~= 8 then
            local proc = Srendarr:HasProc(ability)
            if Srendarr:IsProc(ability) then
                Srendarr:PlayProcAnimations(actionButton)
            elseif proc then
                triggeredSlots[proc] = slotNum
                local aura = auraFrameShort.k_auraActive[proc]
                if aura then
                    local remaining = (aura.k_finish * 1000) - GetGameTimeMilliseconds()
                    if remaining > 0 then
                        Srendarr:PlayProcAnimations(actionButton, true)
                    end
                end
            end
        end
    else
        watchlist[slotNum].name = false
    end

    Srendarr:ConfigureActionButtonWatcher(slotNum)
end

function Srendarr.OnActionSlotsFullUpdate(evt, isHotbarSwap)
    for slotNum = 3, 8 do
        Srendarr.OnActionSlotChanged(evt, slotNum)
    end
end

function Srendarr.OnQuickSlotChanged(evt, slotNum)
    if (IsSlotUsed(slotNum) and GetSlotItemSound(slotNum) == ITEM_SOUND_CATEGORY_POTION) then --only care about potions
        local ability = GetSlotName(slotNum)
        local abilityId = GetSlotBoundId(slotNum)
        local texture = GetSlotTexture(slotNum)
        local buff, debuff = Srendarr:GetPotionData(ability, abilityId)

        --corrections
        if (buff and buff > 0) then
            buff = buff * Srendarr:GetMedicinalUseCoefficient()
        end
        if (debuff and debuff > 0) then
            debuff = debuff * Srendarr:GetMedicinalUseCoefficient()
        end

        if (not Srendarr.db.showDebuff) then
            debuff = false -- if not showing debuffs, then don't track
        end

        if (buff or debuff) then
            local data      = watchlist[9]
            data.name       = ability
            data.buff       = buff
            data.debuff     = debuff
            data.cast       = 0
            data.texture    = texture
            data.isShield   = false
            data.abilityId  = abilityId
        else
            watchlist[9].name = false
        end

    else
        watchlist[9].name = false
    end

    Srendarr:ConfigureActionButtonWatcher(9)
end

do  --triggered effects animations
    local AM = ANIMATION_MANAGER
    local WM = WINDOW_MANAGER
    local PlaySound = PlaySound

    local function CreateProcAnimations(actionButton)
        if not actionButton.procBurstTimeline then
            actionButton.procBurstTexture = WM:CreateControl("$(parent)Burst", actionButton.slot, CT_TEXTURE)
            actionButton.procBurstTexture:SetAnchor(TOPLEFT, actionButton.slot:GetNamedChild("FlipCard"))
            actionButton.procBurstTexture:SetAnchor(BOTTOMRIGHT, actionButton.slot:GetNamedChild("FlipCard"))
            actionButton.procBurstTexture:SetTexture("EsoUI/Art/ActionBar/coolDown_completeEFX.dds")
            actionButton.procBurstTexture:SetBlendMode(TEX_BLEND_MODE_ADD)
            actionButton.procBurstTexture:SetDrawLevel(2)
            actionButton.procBurstTexture:SetHidden(true)
            actionButton.procLoopTexture = WM:CreateControl("$(parent)Loop", actionButton.slot, CT_TEXTURE)
            actionButton.procLoopTexture:SetAnchor(TOPLEFT, actionButton.slot:GetNamedChild("FlipCard"))
            actionButton.procLoopTexture:SetAnchor(BOTTOMRIGHT, actionButton.slot:GetNamedChild("FlipCard"))
            actionButton.procLoopTexture:SetTexture("EsoUI/Art/ActionBar/abilityHighlight_mage_med.dds")
            actionButton.procLoopTexture:SetBlendMode(TEX_BLEND_MODE_ADD)
            actionButton.procLoopTexture:SetDrawLevel(2)
            actionButton.procLoopTexture:SetHidden(true)

            actionButton.procBurstTimeline = AM:CreateTimelineFromVirtual("UltimateReadyBurst", actionButton.procBurstTexture)
            actionButton.procLoopTimeline = AM:CreateTimelineFromVirtual("UltimateReadyLoop", actionButton.procLoopTexture)

            actionButton.procBurstTimeline:SetHandler("OnPlay", function() PlaySound(SOUNDS.DEATH_RECAP_KILLING_BLOW_SHOWN) end)

            local function OnStop(self)
                if(self:GetProgress() == 1) then
                    actionButton.procBurstTexture:SetHidden(true)
                    actionButton.procLoopTimeline:PlayFromStart()
                    actionButton.procLoopTexture:SetHidden(false)
                end
            end
            actionButton.procBurstTimeline:SetHandler("OnStop", OnStop)

            actionButton.procLoopTimeline:SetHandler("OnStop", function() actionButton.procLoopTexture:SetHidden(true) end)
        end
    end

    function Srendarr:PlayProcAnimations(actionButton, isActive)
        CreateProcAnimations(actionButton)
        if actionButton.procBurstTimeline then
            if not actionButton.procBurstTimeline:IsPlaying() and not actionButton.procLoopTimeline:IsPlaying() then
                if isActive then
                    actionButton.procLoopTimeline:PlayFromStart()
                    actionButton.procLoopTexture:SetHidden(false)
                else
                    actionButton.procBurstTimeline:PlayFromStart()
                    actionButton.procBurstTexture:SetHidden(false)
                end
            end
        end
    end

    function Srendarr:StopProcAnimations(actionButton)
        if actionButton.procBurstTimeline then
            actionButton.procBurstTexture:SetHidden(true)
            actionButton.procLoopTexture:SetHidden(true)
            actionButton.procBurstTimeline:Stop()
            actionButton.procLoopTimeline:Stop()
        end
    end

    function Srendarr:IsPlayingProcAnimation(actionButton)
        if actionButton.procBurstTimeline then
            return actionButton.procBurstTimeline:IsPlaying() or actionButton.procLoopTimeline:IsPlaying()
        end
    end
end

function Srendarr.OnEffectChanged(_, change, buff, name, unit, start, finish, stack, icon, _, effectType, abilityType, statusEffectType, unitName, unitId, abilityId)
    if (unit ~= 'player') then return end
    -- Trigger event for target debuff list
    Srendarr:OnTargetChanged()

    -- Skip Minor Buffs
    if (Srendarr.db.hideMinorBuffs and Srendarr.MinorBuffs[abilityId] ~= nil) then
        return
    end

    -- Skip Major Buffs
    if (Srendarr.db.hideMajorBuffs and Srendarr.MajorBuffs[abilityId] ~= nil) then
        return
    end

    if (change == EFFECT_RESULT_FADED) then -- losing an aura
        if (auraFrameLong.k_auraActive[name]) then
            if (auraFrameLong.k_auraActive[name].k_type < 3) then -- timed, ghost it
                auraFrameLong.k_auraActive[name]:Ghost()
            else -- non timed, kill it
                auraFrameLong:RemoveAura(name)
            end
        end
        if(effectType == BUFF_EFFECT_TYPE_DEBUFF) then
            if (auraFrameDebuffs.k_auraActive[name]) then
                if (auraFrameDebuffs.k_auraActive[name].k_type < 1) then -- timed, ghost it
                auraFrameDebuffs.k_auraActive[name]:Ghost()
                else -- non timed, kill it
                auraFrameDebuffs:RemoveAura(name)
                end
            end
        else
            if (auraFrameShort.k_auraActive[name]) then
                if (auraFrameShort.k_auraActive[name].k_type < 1) then -- timed, ghost it
                    auraFrameShort.k_auraActive[name]:Ghost()
                else -- non timed, kill it
                    auraFrameShort:RemoveAura(name)
                end
            end
        end
        if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then
            local slotNum = triggeredSlots[name]
            if slotNum then
                local actionButton = ZO_ActionBar_GetButton(slotNum)
                Srendarr:StopProcAnimations(actionButton)
            end
        end
    else -- adding or updating an aura
        local isShield = abilityType == ABILITY_TYPE_DAMAGESHIELD
        if (finish > start) then -- timed ability

            if(effectType == BUFF_EFFECT_TYPE_DEBUFF) then

                d('abilityId', abilityId)
                d('abilityName', name)
                d('buff', buff)
                d('effectType', effectType)
                d('statufEffectType', statusEffectType)
                if (Srendarr:IsWatchedTimed(name)) then
                    auraFrameDebuffs:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType)
                end
            else
                if (finish - start < db.shortBuffThreshold) then
                    if (Srendarr:IsWatchedTimed(name)) then
                        auraFrameShort:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType)
                    end
                else
                    if (Srendarr:IsWatchedTimed(name)) then
                        auraFrameLong:AddAura(2, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType)
                    end
                end
            end
        elseif (Srendarr:IsToggled(name)) then -- toggled ability
            if (db.showToggle) then -- showing toggled
                auraFrameLong:AddAura(3, 1, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType)
            end
        else -- passive (assumption: passives have start = finish)
            if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then
                local duration = Srendarr:GetAuraData(name) or 0
                auraFrameShort:AddAura(1, 1, name, icon, start, start + duration, isShield, abilityType, buff, abilityId, effectType)
            elseif (Srendarr:IsWatchedPassive(name, abilityType)) then
                auraFrameLong:AddAura(4, 1, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType)
            end
        end
        if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then
            local slotNum = triggeredSlots[name]
            if slotNum then
                local actionButton = ZO_ActionBar_GetButton(slotNum)
                Srendarr:PlayProcAnimations(actionButton)
            end
        end
        if (name == L.Passive_MedicinalUse) then
            Srendarr:SetMedicinalUseCoefficient(abilityId)
        end
    end
end

do --shields
    local GetUnitAttributeVisualizerEffectInfo  = GetUnitAttributeVisualizerEffectInfo
    local callLater = zo_callLater

    local function RemoveShields()
        local value = GetUnitAttributeVisualizerEffectInfo('player', ATTRIBUTE_VISUAL_POWER_SHIELDING, STAT_MITIGATION, ATTRIBUTE_HEALTH, POWERTYPE_HEALTH) or 0

        if (value <= 0) then
            -- shields are always 'short', remove from [1] if present
            for _, aura in pairs(auraFrameShort.k_auraActive) do
                if (aura.k_isShield) then
                    aura:Ghost()
                end
            end
        end
    end

    function Srendarr.OnVisualRemoved(_, unit, visual, ...)
        if (unit == 'player' and visual == ATTRIBUTE_VISUAL_POWER_SHIELDING) then
            callLater(RemoveShields, 5)
        end
    end
end

function Srendarr.OnPlayerDeath(event)
    if (event == EVENT_PLAYER_DEAD) then -- player died
        Srendarr:StripAuras()
    else -- player lives again
        Srendarr:UpdateAuras()
    end
end

do
    local equippedArmor = {
        [EQUIP_SLOT_CHEST]      = ARMORTYPE_NONE,
        [EQUIP_SLOT_FEET]       = ARMORTYPE_NONE,
        [EQUIP_SLOT_HAND]       = ARMORTYPE_NONE,
        [EQUIP_SLOT_HEAD]       = ARMORTYPE_NONE,
        [EQUIP_SLOT_LEGS]       = ARMORTYPE_NONE,
        [EQUIP_SLOT_SHOULDERS]  = ARMORTYPE_NONE,
        [EQUIP_SLOT_WAIST]      = ARMORTYPE_NONE,
    }

    function Srendarr:GetNumArmorPieces(desiredArmorType)
        local numPieces = 0
        for equipSlot, armorType in pairs(equippedArmor) do
            if armorType == desiredArmorType then
                numPieces = numPieces + 1
            end
        end
        return numPieces
    end

    function Srendarr.InventorySlotUpdated(event, bagId, slotId, isNewItem, itemSoundCategory, updateReason)
        if bagId == BAG_WORN and updateReason == INVENTORY_UPDATE_REASON_DEFAULT and equippedArmor[slotId] then
            local newArmorType = GetItemArmorType(bagId, slotId)
            if newArmorType ~= equippedArmor[slotId] then
                equippedArmor[slotId] = newArmorType
                Srendarr:SetupPassiveSkillEffects()
            end
        end
    end

    function Srendarr:InitializeArmorWatcher()
        for equipSlot in pairs(equippedArmor) do
            equippedArmor[equipSlot] = GetItemArmorType(BAG_WORN, equipSlot)
        end
        Srendarr:SetupPassiveSkillEffects()
    end
end

function Srendarr.OnCombatState(event, inCombat)
    if (inCombat) then
        if (db.onlyInCombat) then
            for i = 1, 3 do       --hide all auras except of long term buffs (4)
                Srendarr.auraSceneFragments[i]:SetHiddenForReason("combatstate", false)
            end
        end
    else
        Srendarr:ClearTimerType(2)              -- end all potential debuffs
        Srendarr.auraFrames[3]:RemoveAllAuras() -- end all potential debuffs

        if (db.onlyInCombat) then
            for i = 1, 3 do
                Srendarr.auraSceneFragments[i]:SetHiddenForReason("combatstate", true)
            end
        end
    end
end

function Srendarr.OnPlayerActivated()
    Srendarr:UpdateAuras()
end

do
    local GetNumBuffs       = GetNumBuffs
    local GetUnitBuffInfo   = GetUnitBuffInfo
    local DoesUnitExist     = DoesUnitExist

    local frame, db, frameDebuff

    function Srendarr.OnTargetChanged()
        if (Srendarr.db.showTargetAurasDebuff == false) then
           return
        end
        -- cleanse out previous auras
        frame:RemoveAllAuras()
        frameDebuff:RemoveAllAuras()
        Srendarr:ClearTimerType(3)
        Srendarr:ClearTimerType(4)

        if (DoesUnitExist('reticleover')) then -- have a target
            if (db.onlyInCombat and not Srendarr.ui_InCombat) then return end -- showing only in combat, but not

            local numAuras = GetNumBuffs('reticleover')

            if (numAuras > 0) then
                for x = 1, numAuras do
                    local name, start, finish, buff, stack, icon, _, effectType, abilityType, statusEffectType, abilityId, _ = GetUnitBuffInfo('reticleover', x)
                    local isShield = abilityType == ABILITY_TYPE_DAMAGESHIELD


                    -- Skip Minor Buffs
                    if (Srendarr.db.hideMinorBuffs and Srendarr.MinorBuffs[abilityId] ~= nil) then
                        return
                    end

                    -- Skip Major Buffs
                    if (Srendarr.db.hideMajorBuffs and Srendarr.MajorBuffs[abilityId] ~= nil) then
                        return
                    end

                    if (finish > start) then
                        if (Srendarr:IsWatchedTimedTarget(name) and effectType == BUFF_EFFECT_TYPE_DEBUFF) then
                            frameDebuff:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType)
                        elseif (Srendarr:IsWatchedTimedTarget(name) and effectType == BUFF_EFFECT_TYPE_BUFF) then
                            frame:AddAura(2, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType)
                        end
                    elseif (Srendarr:IsToggled(name)) then -- toggled
                        if (db.showToggleTarget) then
                            frame:AddAura(3, 3, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType)
                        end
                    else -- passive
                        if (Srendarr:IsWatchedPassiveTarget(name, abilityType)) then
                            frame:AddAura(4, 3, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType)
                        end
                    end
                end

                frame:UpdateDisplay()
                frameDebuff:UpdateDisplay()
            end
        end
    end

    function Srendarr:InitializeOnTargetChanged()
        db, frame = self.db, self.auraFrames[4]
        db, frameDebuff = self.db, self.auraFrames[5]
    end
end

function Srendarr:ConfigureEvents()
    if (db.combineBuff) then
        auraFrameLong = self.auraFrames[1]
    else
        auraFrameLong = self.auraFrames[2]
    end

    if (db.showTargetAuras or db.showTargetAurasDebuff) then
        EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RETICLE_TARGET_CHANGED, self.OnTargetChanged)
    else
        EVENT_MANAGER:UnregisterForEvent(self.name, EVENT_RETICLE_TARGET_CHANGED)
    end
end

function Srendarr:InitializeEvents()
    db               = self.db
    auraFrameShort   = self.auraFrames[1]
    auraFrameDebuffs = self.auraFrames[3]

    -- register events
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTION_SLOTS_FULL_UPDATE,       self.OnActionSlotsFullUpdate)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTION_SLOT_UPDATED,            self.OnActionSlotChanged)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTIVE_QUICKSLOT_CHANGED,       self.OnQuickSlotChanged)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_EFFECT_CHANGED,                 self.OnEffectChanged)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_DEAD,                    self.OnPlayerDeath)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ALIVE,                   self.OnPlayerDeath)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_UNIT_ATTRIBUTE_VISUAL_REMOVED,  self.OnVisualRemoved)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE,            self.OnCombatState)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED,               self.OnPlayerActivated)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_INVENTORY_SINGLE_SLOT_UPDATE,   self.InventorySlotUpdated)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_SKILLS_FULL_UPDATE,             function() Srendarr:SetupPassiveSkillEffects() end)

    EVENT_MANAGER:AddFilterForEvent(self.name, EVENT_EFFECT_CHANGED,                REGISTER_FILTER_UNIT_TAG, 'player')
    EVENT_MANAGER:AddFilterForEvent(self.name, EVENT_UNIT_ATTRIBUTE_VISUAL_REMOVED, REGISTER_FILTER_UNIT_TAG, 'player')

    self:ConfigureEvents()
    self:InitializeArmorWatcher()
    self.OnActionSlotsFullUpdate() -- call on load to record initial hotbar data
    self.OnQuickSlotChanged(nil, GetCurrentQuickslot())
    self:SetupActionButtonHooks()  -- configure hooks, never call this again!
    self:InitializeOnTargetChanged()
    self.OnCombatState(nil, IsUnitInCombat("player"))
end