local LAM = LibStub:GetLibrary("LibAddonMenu-2.0")


RaidNotifier = RaidNotifier or {}

RaidNotifier.name            = 'RaidNotifier'
RaidNotifier.slash           = '/rn'
RaidNotifier.version         = '1.3.8'
RaidNotifier.versionDB       = 2
RaidNotifier.loaded           = false
RaidNotifier.author        = 'silentgecko'
RaidNotifier.savedVarsName = 'RNVars'

RaidNotifier.variables = {
    sanctum_ophidia = {
        magicka_deto      = true,
        poison            = true,
        mantikora_spear   = true,
    },
    maelstrom = {
        stage7_poison  = true,
        stage9_synergy = true,
    },
    mawLorkhaj = {
        twinBoss_aspects = 4,
    },
    general = {
        buffFood_reminder = true,
        buffFood_reminder_interval = 60,
    },
    debug = false
}

RaidNotifier.pingEventCodes = {
    mantikora_spear = 51816
}

RaidNotifier.tempVars = {
    last_notify = {
        sanctum_ophidia = {
            magicka_deto    = 0,
            poison          = 0,
            mantikora_spear = 0,
        },
        general = {
            buffFood_reminder = 0,
        },
        maelstrom = {
            stage7_poison  = 0,
            stage9_synergy = 0,
        },
        maw_lorkhaj = {
            twinBoss_aspect = 0,
        },
    },
    last_ping = 0,
}

local function CreateSettingsMenu()
    local self = RaidNotifier
    ------Creating the menu with LibAddonMenu-2.0 (thank you Seerah)-------
    self.panelData = {
        type = "panel",
        name = self.name,
        author = self.author,
        version = self.version,
        registerForRefresh = false,
    }

    local choices = {
        maw_lorkhaj = {
            twinBoss_aspect = {
                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_OFF),
                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_MINIMAL),
                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_NORMAL),
                GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_FULL),
            },
        },
    }

    self.optionsData = {
        {
            type = "description",
            text = GetString(RAIDNOTIFIER_DESCRIPTION),
        },
        {
            type = "header",
            name = GetString(RAIDNOTIFIER_SETTINGS_GENERAL_HEADER),
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_GENERAL_BUFFFOOD_REMINDER),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_GENERAL_BUFFFOOD_REMINDER_TT),
            getFunc = function() return RaidNotifier.savedVariables.general.buffFood_reminder end,
            setFunc = function(value)
                RaidNotifier.savedVariables.general.buffFood_reminder = value
            end,
        },
        {
            type = "slider",
            name = GetString(RAIDNOTIFIER_SETTINGS_GENERAL_BUFFFOOD_REMINDER_INTERVAL),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_GENERAL_BUFFFOOD_REMINDER_INTERVAL_TT),
            min = 30,
            max = 120,
            step = 5,
            getFunc = function() return RaidNotifier.savedVariables.general.buffFood_reminder_interval end,
            setFunc = function(value)
                RaidNotifier.savedVariables.general.buffFood_reminder_interval = value
            end,
            default = 60,
            width = "full",
        },
        -- Maelstrom Arena
        {
            type = "header",
            name = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_HEADER),
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_MAGICKA_DETONATION),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_MAGICKA_DETONATION_TT),
            getFunc = function() return RaidNotifier.savedVariables.sanctum_ophidia.magicka_deto end,
            setFunc = function(value)
                RaidNotifier.savedVariables.sanctum_ophidia.magicka_deto = value
            end,
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_POISON),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_POISON_TT),
            getFunc = function() return RaidNotifier.savedVariables.sanctum_ophidia.poison end,
            setFunc = function(value)
                RaidNotifier.savedVariables.sanctum_ophidia.poison = value
            end,
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_MANTIKORA_SPEAR),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_SANCTUM_MANTIKORA_SPEAR_TT),
            getFunc = function() return RaidNotifier.savedVariables.sanctum_ophidia.mantikora_spear end,
            setFunc = function(value)
                RaidNotifier.savedVariables.sanctum_ophidia.mantikora_spear = value
            end,
        },
        {
            type = "header",
            name = GetString(RAIDNOTIFIER_SETTINGS_MAELSTROM_HEADER),
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_MAELSTROM_STAGE7_POISON),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_MAELSTROM_STAGE7_POISON_TT),
            getFunc = function() return RaidNotifier.savedVariables.maelstrom.stage7_poison end,
            setFunc = function(value)
                RaidNotifier.savedVariables.maelstrom.stage7_poison = value
            end,
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_MAELSTROM_STAGE9_SYNERGY),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_MAELSTROM_STAGE9_SYNERGY_TT),
            getFunc = function() return RaidNotifier.savedVariables.maelstrom.stage9_synergy end,
            setFunc = function(value)
                RaidNotifier.savedVariables.maelstrom.stage9_synergy = value
            end,
        },

        -- Maw of Lorkhaj
        {
            type = "header",
            name = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_HEADER),
        },
        {
            type = "dropdown",
            name = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_MAWLORKHAJ_TWIN_ASPECTS_TT),
            choices = choices.maw_lorkhaj.twinBoss_aspect,
            getFunc = function()
                return choices.maw_lorkhaj.twinBoss_aspect[RaidNotifier.savedVariables.mawLorkhaj.twinBoss_aspect]
            end,
            setFunc = function(value)
                for i, str in ipairs(choices.maw_lorkhaj.twinBoss_aspect) do
                    if value == str then
                        RaidNotifier.savedVariables.mawLorkhaj.twinBoss_aspect = i
                    end
                end
            end,
            default = 4
        },

        {
            type = "header",
            name = GetString(RAIDNOTIFIER_SETTINGS_DEBUG_HEADER),
        },
        {
            type = "checkbox",
            name = GetString(RAIDNOTIFIER_SETTINGS_DEBUG),
            tooltip = GetString(RAIDNOTIFIER_SETTINGS_DEBUG_TT),
            getFunc = function() return RaidNotifier.savedVariables.debug end,
            setFunc = function(value)
                RaidNotifier.savedVariables.debug = value
            end,
        },
    }

    LAM:RegisterAddonPanel("RaidNotifierPanel", self.panelData)
    LAM:RegisterOptionControls("RaidNotifierPanel", self.optionsData)
end

---------Passing saved variables to the labels at initialize-------
function RaidNotifier.Initialize(_, addonName)
    local self = RaidNotifier

    if addonName ~= self.name then return end

    EVENT_MANAGER:UnregisterForEvent(self.name, EVENT_ADD_ON_LOADED)

    self.savedVariables = ZO_SavedVars:NewAccountWide(self.savedVarsName, self.versionDB, nil, self.variables)

    CreateSettingsMenu()

    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_STARTED,  RaidNotifier.addEventListeners)
    EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_COMPLETE, RaidNotifier.removeEventListeners)
    --EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RAID_TRIAL_FAILED,   RaidNotifier.removeEventListeners)

    if IsRaidInProgress() then
        self.addEventListeners()
    else
        self.removeEventListeners()
    end

end

-- Add Events
function RaidNotifier.addEventListeners()
    local self   = RaidNotifier
    local raidId = GetCurrentParticipatingRaidId()

    -- add general
    if raidId > 0 then
        EVENT_MANAGER:RegisterForEvent(self.name .. "_BUFFFOOD", EVENT_EFFECT_CHANGED, self.generalBuffFoodReminder)
        EVENT_MANAGER:RegisterForEvent(self.name .. "_PINGS",    EVENT_MAP_PING,       self.receivePing)
    end

    -- add sanctum
    if raidId == 3 then
        EVENT_MANAGER:RegisterForEvent(self.name .. "_SANCTUM", EVENT_EFFECT_CHANGED, self.sanctumDebuffs)
    end

    if raidId == 5 then
         --for some weird reason only the initial coloring shows up in EVENT_EFFECT_CHANGED, the changing of colors does NOT show up AT ALL :/
        EVENT_MANAGER:RegisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_COMBAT_EVENT, self.mawLorkhajCombat)  --EVENT_MANAGER:RegisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_EFFECT_CHANGED, self.mawLorkhajDebuffs)
    end

    -- add maelstrom
    if raidId == 6 then
        EVENT_MANAGER:RegisterForEvent(self.name .. "_MAELSTROM", EVENT_EFFECT_CHANGED, self.maelstromDebuffs)
    end
end


-- Remove all Events
function RaidNotifier.removeEventListeners()
    local self   = RaidNotifier

    EVENT_MANAGER:UnregisterForEvent(self.name .. "_BUFFFOOD",   EVENT_EFFECT_CHANGED)
    EVENT_MANAGER:UnregisterForEvent(self.name .. "_SANCTUM",    EVENT_EFFECT_CHANGED)
    EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAELSTROM",  EVENT_EFFECT_CHANGED)
    EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_COMBAT_EVENT) --EVENT_MANAGER:UnregisterForEvent(self.name .. "_MAWLORKHAJ", EVENT_EFFECT_CHANGED)
    EVENT_MANAGER:UnregisterForEvent(self.name .. "_PINGS",      EVENT_MAP_PING)
end

--[[
local hud


function RaidNotifier.StartGlyphTimer(index, cooldown)
    if not hud.glyphWindow then return end

    local glyph = hud.glyphWindow.glyphs[index]
    if not glyph then return end

    glyph.timer:SetText(ZO_FormatTimeMilliseconds(cooldown, TIME_FORMAT_STYLE_DESCRIPTIVE_MINIMAL_SHOW_TENTHS_SECS))
    glyph.start = GetFrameTimeMilliseconds()
    glyph.cooldown = cooldown
    glyph.timer:SetHidden(false)
    glyph.glow:SetHidden(true)

    if hud.glyphWindow:IsHidden() then hud.glyphWindow:SetHidden(false) end
end

function RaidNotifier.StopGlyphTimer(index)
    if not hud.glyphWindow then return end

    local glyph = hud.glyphWindow.glyphs[index]
    if not glyph then return end

    glyph.timer:SetHidden(true)
    glyph.start = 0
    glyph.glow:SetHidden(false)

    if hud.glyphWindow:IsHidden() then hud.glyphWindow:SetHidden(false) end
end

function RaidNotifier.UpdateGlyphWindowHandler()
    if not hud.glyphWindow then return end

    for i, glyph in ipairs(hud.glyphWindow.glyphs) do
        if glyph.start > 0 then
            local duration = glyph.start + glyph.cooldown - GetFrameTimeMilliseconds()
            if duration <= 0 then
                glyph.start = 0
                glyph.timer:SetHidden(true)
                glyph.glow:SetHidden(false)
            else
                glyph.timer:SetText(ZO_FormatTimeMilliseconds(duration, TIME_FORMAT_STYLE_DESCRIPTIVE_MINIMAL_SHOW_TENTHS_SECS))
            end
        end
    end

end

function RaidNotifier.SetupGlyphWindow(size, pos, numGlyphs, glyphLayout)
    local self = RaidNotifier

    if not hud then
        hud = WINDOW_MANAGER:CreateTopLevelWindow(self.name .. "_HUD")
        hud:SetAnchor(TOPLEFT, guiRoot, TOPLEFT, 0, 0)
    end

    if not hud.glyphWindow then
        hud.glyphWindow = WINDOW_MANAGER:CreateControlFromVirtual(nil, hud, "ZO_DefaultBackdrop")
        hud.glyphWindow:SetHidden(false)
    end
    hud.glyphWindow:SetDimensions(unpack(size))
    hud.glyphWindow:ClearAnchors()
    hud.glyphWindow:SetAnchor(TOPLEFT, hud, TOPLEFT, unpack(pos))
    local window = hud.glyphWindow

    local function CreateGlyph(parent, size)
        local glyph = WINDOW_MANAGER:CreateControl(nil, parent, CT_CONTROL)
        glyph:SetAnchor(TOPLEFT, parent, TOPLEFT, 0, 0)
        glyph:SetDimensions(size, size)

        glyph.bg = WINDOW_MANAGER:CreateControl(nil, glyph, CT_TEXTURE)
        glyph.bg:SetDimensions(size, size)
        glyph.bg:SetAnchor(CENTER, glyph, CENTER)
        glyph.bg:SetTexture("RaidNotifier/assets/glyph_background.dds")

        glyph.glow = WINDOW_MANAGER:CreateControl(nil, glyph.bg, CT_TEXTURE)
        glyph.glow:SetDimensions(size, size)
        glyph.glow:SetAnchor(CENTER, glyph.bg, CENTER)
        glyph.glow:SetTexture("RaidNotifier/assets/glyph_glow.dds")

        glyph.timer = WINDOW_MANAGER:CreateControl(nil, glyph.bg, CT_LABEL)
        glyph.timer:SetAnchor(CENTER, glyph.bg, CENTER)
        glyph.timer:SetFont("ZoFontWinH4")
        glyph.timer:SetText("15s")
        glyph.timer:SetHidden(true)
        glyph.start = 0

        glyph:SetHidden(true)
        return glyph
    end

    window.glyphs = {}
    for i=1, numGlyphs do
        if not window.glyphs[i] then
            window.glyphs[i] = CreateGlyph(window, 58)
        end
        local glyph = window.glyphs[i]
        local x, y, bg, glow = unpack(glyphLayout[i])
        glyph:ClearAnchors()
        glyph:SetAnchor(CENTER, window, CENTER, x*size[1]*0.5/100, y*size[2]*0.5/100)
        if bg ~= nil then
            glyph.bg:SetTexture("RaidNotifier/assets/"..bg)
        end
        if glow ~= nil then
            glyph.glow:SetTexture("RaidNotifier/assets/"..glow)
        end
        glyph:SetHidden(false)
    end
end

--/script EVENT_MANAGER:RegisterForEvent("TMP42", EVENT_COMBAT_EVENT,  RaidNotifier.mawLorkhajCombat) RaidNotifier.createHud()


zo_callLater(function() EVENT_MANAGER:RegisterForEvent("TMP42", EVENT_COMBAT_EVENT,  RaidNotifier.mawLorkhajCombat) RaidNotifier.createHud() end, 2000)

function RaidNotifier.createHud()
    local self = RaidNotifier

    local ui = self.UIs.maw_lorkhaj
    self.SetupGlyphWindow(ui.window_size, ui.window_pos, ui.zhajBoss_numGlyphs, ui.zhajBoss_glyphLayout)
    EVENT_MANAGER:RegisterForUpdate(self.name, ui.update_interval, self.UpdateGlyphWindowHandler)

    --EVENT_MANAGER:RegisterForUpdate(self.name, 100, GlyphUpdateHandler)
end

function RaidNotifier.mawLorkhajFindGlyph(glyphId, glyphs, knownGlyphs, allowNew)

    local self = RaidNotifier
    if not knownGlyphs[glyphId] then
        if not allowNew then return 0 end

        local lowest = {distance=9999, index=0, data=nil}
        for index, data in ipairs(glyphs) do
            for p=1, GetGroupSize() do
                if IsUnitOnline("group"..p) then
                    local pX, pY = GetMapPlayerPosition("group"..p)
                    if (data.index == nil) then --only check unknown glyphs
                        local x, y = data.x, data.y
                        local distance = math.sqrt((pX-x)*(pX-x)+(pY-y)*(pY-y)) * 1000
                        if (distance < lowest.distance) then
                            --d("Unit="..("group"..p)..", Disance="..distance..", Index="..index)
                            lowest.distance=distance
                            lowest.index=index
                            lowest.data=data
                        end
                    end
                end
            end
        end
        if lowest.distance < 8 and lowest.index > 0 then
            --d("Within target distance!")
            lowest.data.index = lowest.index
            knownGlyphs[glyphId] = lowest.index
            return lowest.index
        else
            return 0
        end
    else
        return knownGlyphs[glyphId]
    end
end
--]]



function RaidNotifier.mawLorkhajCombat(_, result, isError, abilityName, _, _, sourceName, sourceType, targetName, targetType, _, _, _, _, sourceUnitId, targetUnitId, abilityId)

    local self = RaidNotifier
    -- remove event listener, the api won't get it on zoning
    if IsRaidInProgress() == false then
        self.removeEventListeners()
        return
    end
    local buffsDebuffs = self.BuffsDebuffs.maw_lorkhaj


    --Zhaj'hassa the Forgotten
    --[[
    if (abilityId == buffsDebuffs.zhajBoss_glyphability) then
        local findNew = (result == 2250) --only scan for new glyph when effect/glyph is used by the player, NOT when it respawns
        local glyphIndex = self.mawLorkhajFindGlyph(targetUnitId, buffsDebuffs.zhajBoss_glyphs, buffsDebuffs.zhajBoss_knownGlyphs, findNew)
        if (result == 2245) then --(change == EFFECT_RESULT_GAINED)
            self.StopGlyphTimer(glyphIndex)
        elseif (result == 2250) then --(change == EFFECT_RESULT_FADED)
            self.StartGlyphTimer(glyphIndex, buffsDebuffs.zhajBoss_glyphcooldown)
        end
    elseif (abilityId == buffsDebuffs.zhajBoss_curseability) then
        local glyphIndex = 7
        if (result == 2245) then --(change == EFFECT_RESULT_GAINED)
            self.StartGlyphTimer(glyphIndex, buffsDebuffs.zhajBoss_curseduration)
        elseif (result == 2250) then --(change == EFFECT_RESULT_FADED)
            self.StopGlyphTimer(glyphIndex)
        end
    end
    --]]


    -- False Moon Twins, S’Kinrai and Vashai
    if (targetType == COMBAT_UNIT_TYPE_PLAYER) then
        -- debugging for now, I might have missed an abilityId
        if (abilityName == buffsDebuffs.twinBoss_holyaspectname) then
            if (buffsDebuffs.twinBoss_holyaspect[abilityId] == nil) then
                self.debug("Unknown Holy Aspect: ", abilityId)
                abilityId = 59472
                self.debug("Holy Aspect: ", abilityId)
            end
        elseif (abilityName == buffsDebuffs.twinBoss_shadowaspectname) then
            if (buffsDebuffs.twinBoss_shadowaspect[abilityId] == nil) then
                self.debug("Unknown Shadow Aspect: ", abilityId)
                abilityId = 59523
                self.debug("Shadow Aspect: ", abilityId)
            end
        end
        --]]

        local alert = nil
        if (buffsDebuffs.twinBoss_holyaspect[abilityId]) then
            if self.savedVariables.mawLorkhaj.twinBoss_aspect > 1 then
                alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT
            end
        elseif (buffsDebuffs.twinBoss_shadowaspect[abilityId]) then
            if self.savedVariables.mawLorkhaj.twinBoss_aspect > 1 then
                alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT
            end
        elseif (buffsDebuffs.twinBoss_holyconversion[abilityId]) then
            if (sourceName ~= "") then      --will be name of one of the bosses
                --conversion just started
                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 0 then
                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_CONVERSION
                end
            else
                --conversion ended
                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 2 then
                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT
                end
            end
        elseif (buffsDebuffs.twinBoss_shadowconversion[abilityId]) then
            if (sourceName ~= "") then      --will be name of one of the bosses
                --conversion just started
                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 0 then
                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_CONVERSION
                end
            else
                --conversion ended
                if self.savedVariables.mawLorkhaj.twinBoss_aspect > 2 then
                    alert = RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT
                end
            end
        end

        if (alert ~= nil) then
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if timeDiff > 5 then
                self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(alert), nil, nil, nil, nil, nil, 2000)
            end
        end
    end

end

-- Maw of Lorkhaj Events
--[[
function RaidNotifier.mawLorkhajDebuffs(_, change, _, name, unitTag, _, _, _, _, _, _, _, _, _, unitId, abilityId)

    -- only take care of player
    --if (unitTag ~= 'player') then return end

    local self = RaidNotifier
    -- remove event listener, the api won't get it on zoning
    if IsRaidInProgress() == false then
        self.removeEventListeners()
        return
    end

    local buffsDebuffs = self.BuffsDebuffs.maw_lorkhaj
    if (buffsDebuffs.zhajBoss_glyphs[unitId] > 0 and abilityId == buffsDebuffs.zhajBoss_glyphability) then
        if (change == EFFECT_RESULT_GAINED) then
            d("Glyph"..buffsDebuffs.zhajBoss_glyphs[unitId].." respawned")
        elseif (change == EFFECT_RESULT_FADED) then
            d("Glyph"..buffsDebuffs.zhajBoss_glyphs[unitId].." used")
        end
    end

    -- only notice on effect added
    if (change == EFFECT_RESULT_GAINED) then

        -- Maw of Lorkhaj - Twin Boss Holy/Shadow Aspect (aka, "the color stuff")
--        if self.savedVariables.maw_lorkhaj.twinBoss_aspect then
            -- only notify when the last one is at least 10 seconds, use one stamp
            -- for both the initial aspect as well as the aspect conversion
            --local currentTime = GetTimeStamp()
            --local lastNotify  = self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect
            --local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            --if (buffsDebuffs.twinBoss_holyaspect[abilityId]) and timeDiff > 5 then
            --    self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
            --    CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAWLORKHAJ_HOLY_ASPECT), nil, nil, nil, nil, nil, 2000)
            --end
            --if (buffsDebuffs.twinBoss_shadowaspect[abilityId]) and timeDiff > 5 then
            --    self.tempVars.last_notify.maw_lorkhaj.twinBoss_aspect = currentTime
            --    CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAWLORKHAJ_SHADOW_ASPECT), nil, nil, nil, nil, nil, 2000)
            --end

--        end

    end
end
--]]


-- Sanctum Ophidia Events
function RaidNotifier.sanctumDebuffs(_, change, _, name, unit, _, _, _, _, _, _, _, _, _, _, abilityId)
    -- only take care of player
    if (unit ~= 'player') then return end

    local self = RaidNotifier
    -- remove event listener, the api won't get it on zoning
    if IsRaidInProgress() == false then
        self.removeEventListeners()
        return
    end

    local buffsDebuffs = self.BuffsDebuffs.sanctum_ophidia

    -- only notice on effect added
    if (change == EFFECT_RESULT_GAINED) then

        -- Sanctum Serpent Poison Alert
        if self.savedVariables.sanctum_ophidia.poison then
            -- only notify when the last one is at least 15 seconds ago and it is poison
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.sanctum_ophidia.poison
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if (buffsDebuffs.poison == abilityId) and timeDiff > 15 then
                self.tempVars.last_notify.sanctum_ophidia.poison = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_SANCTUM_POISON), nil, nil, nil, nil, nil, 2000)
            end
        end

        -- Sanctum Serpent Magicka Detonation Alert
        if self.savedVariables.sanctum_ophidia.magicka_deto then
            -- only notify when the last one is at least 10 seconds ago and it is poison
            -- debug abilityId: 30255 / Boundless Storm
            -- Real abilityId: 59036 / "Serp Target"
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.sanctum_ophidia.magicka_deto
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if (abilityId == buffsDebuffs.magicka_deto) and timeDiff > 10 then
                self.tempVars.last_notify.sanctum_ophidia.magicka_deto = currentTime

                -- get current magicka percentage
                local current, maximum, _ = GetUnitPower("player", POWERTYPE_MAGICKA)
                local magickaPercentage   = zo_roundToNearest(current/maximum,0.01) * 100

                -- only notify if the current magicka is over 15%
                if magickaPercentage > 15 then
                    CENTER_SCREEN_ANNOUNCE:AddMessage(1, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_SANCTUM_MAGICKA_DETONATION), nil, nil, nil, nil, nil, 5000)
                end
            end
        end

        -- Sanctum Mantikora Spear Throw Alert
        -- @todo send map ping and listen to it
        if self.savedVariables.sanctum_ophidia.mantikora_spear then
            -- only notify when the last one is at least 5 seconds ago and it is the spear
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.sanctum_ophidia.mantikora_spear
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if (buffsDebuffs.spear == abilityId) and timeDiff > 5 then
                self.tempVars.last_notify.sanctum_ophidia.mantikora_spear = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_SANCTUM_MANTIKORA_SPEAR))
                self.sendPing('manti_spear')
            end
        end
    end
end


-- Maelstrom Arena Events
function RaidNotifier.maelstromDebuffs(_, change, _, name, unit, _, _, _, _, _, _, _, _, _, _, abilityId)
    -- only take care of player
    if (unit ~= 'player') then return end

    local self = RaidNotifier
    -- remove event listener, the api won't get it on zoning
    if IsRaidInProgress() == false then
        self.removeEventListeners()
        return
    end
    local buffsDebuffs = self.BuffsDebuffs.maelstrom

    -- only notice on effect added
    if (change == EFFECT_RESULT_GAINED) then

        -- Maelstrom Poison Alert
        if self.savedVariables.maelstrom.stage7_poison then
            -- only notify when the last one is at least 15 seconds ago and it is poison
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.maelstrom.stage7_poison
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if (buffsDebuffs.stage7_poison[abilityId]) and timeDiff > 15 then
                self.tempVars.last_notify.maelstrom.stage7_poison = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_COMBINED_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAELSTROM_STAGE7_POISON), nil, nil, nil, nil, nil, 2000)
            end
        end

        -- Maelstrom Stage 9 Synergy Alert
        if self.savedVariables.sanctum_ophidia.mantikora_spear then
            -- only notify when the last one is at least 15 seconds ago and it is the synergy
            local currentTime = GetTimeStamp()
            local lastNotify  = self.tempVars.last_notify.maelstrom.stage9_synergy
            local timeDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if (buffsDebuffs.stage9_synergy == abilityId) and timeDiff > 15 then
                self.tempVars.last_notify.maelstrom.stage9_synergy = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(2, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_MAELSTROM_STAGE9_SYNERGY), nil, nil, nil, nil, nil, 2000)
            end
        end
    end
end

-- General Events
function RaidNotifier.generalBuffFoodReminder(_, _, _, _, unit)
    -- only take care of player
    if (unit ~= 'player') then return end

    local self = RaidNotifier
    -- remove event listener, the api won't get it on zoning
    if IsRaidInProgress() == false then
        self.removeEventListeners()
        return
    end

    -- return if the player don't want the reminder
    if self.savedVariables.general.buffFood_reminder == false then
        return
    end

    local buffsDebuffs = self.BuffsDebuffs.buffFood
    local buffFoodFound = false
    local reminderInterval = self.savedVariables.general.buffFood_reminder_interval

    local numAuras = GetNumBuffs('player')
    if (numAuras > 0) then
        local currentTime = GetTimeStamp()

        for x = 1, numAuras do
            local name, _, finish, _, _, _, _, _, _, _, abilityId, _ = GetUnitBuffInfo('player', x)
            if buffsDebuffs[abilityId] then
                -- set bufffoodfound to true
                buffFoodFound = true

                local bufffood_remaining = finish - (GetFrameTimeMilliseconds() / 1000.0)
                local lastNotify         = self.tempVars.last_notify.general.buffFood_reminder
                local lastNotifyDiff     = GetDiffBetweenTimeStamps(currentTime, lastNotify)
                local formatedTime       = ZO_FormatTime(bufffood_remaining, TIME_FORMAT_STYLE_COLONS, TIME_FORMAT_PRECISION_SECONDS)

                -- new set interval
                if bufffood_remaining <= 600 and (lastNotifyDiff > reminderInterval) then
                    -- every set interval
                    self.tempVars.last_notify.general.buffFood_reminder = currentTime
                    CENTER_SCREEN_ANNOUNCE:AddMessage(3, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, zo_strformat(GetString(RAIDNOTIFIER_ALERTS_GENERAL_BUFFFOOD_MINUTES), name, formatedTime))
                end
                if self.savedVariables.debug and buffFoodFound == false then
                    RaidNotifier.debug('bufffood id forgot?', abilityId)
                    RaidNotifier.debug('ability name', name)
                end
            end
        end

        -- no bufffood found, alert every interval
        if buffFoodFound == false then
            local lastNotify     = self.tempVars.last_notify.general.buffFood_reminder
            local lastNotifyDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if lastNotifyDiff > reminderInterval then
                self.tempVars.last_notify.general.buffFood_reminder = currentTime
                CENTER_SCREEN_ANNOUNCE:AddMessage(3, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_GENERAL_NO_BUFFFOOD))
            end
        end
    else
        -- no buffs found, we can directly alert
        CENTER_SCREEN_ANNOUNCE:AddMessage(3, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, GetString(RAIDNOTIFIER_ALERTS_GENERAL_NO_BUFFFOOD))
    end
end

-- send pings
function RaidNotifier.sendPing(event)
    local self           = RaidNotifier
    local realEventCodes = self.pingEventCodes

    if event == 'manti_spear' then
        local lastPing     = self.tempVars.last_ping
        local currentTime  = GetTimeStamp()
        local lastPingDiff = GetDiffBetweenTimeStamps(currentTime, lastPing)
        local eventCode    = realEventCodes.mantikora_spear

        -- only ping every 5 seks
        if lastPingDiff > 5 then
            local eventCoordX = eventCode/100000
            local eventCoordY = eventCode/1000000

            --send the ping
            PingMap(MAP_PIN_TYPE_PING, MAP_TYPE_LOCATION_CENTERED, eventCoordX , eventCoordY)
            self.tempVars.last_ping = currentTime
        end
    end
end

-- receive pings
function RaidNotifier.receivePing(_, pingEventType, _, pingTag, offsetX, offsetY, isOwner)
    -- ignore
    if (offsetX == 0 and offsetY == 0) then return end
    if (pingEventType == PING_EVENT_REMOVED) then return end
    if (isOwner == true) then return end

    local self           = RaidNotifier
    local realEventCodes = self.pingEventCodes

    --ping data
    local unitName        = GetUnitName(pingTag)
    local eventCodeA      = math.abs(offsetX * 100000)
    local eventCodeB      = math.abs(offsetY * 1000000)
    local currentTime     = GetTimeStamp()
    local realEventCode   = realEventCodes.mantikora_spear -- atm we only have this one, @todo iterate over them and then switch for the different alerts
    local zosEventCodeMin = realEventCode - 100
    local zosEventCodeMax = realEventCode + 100
    local lastPing        = self.tempVars.last_ping
    local lastPingDiff    = GetDiffBetweenTimeStamps(currentTime, lastPing)

    -- make sure we have a correct eventCode
    -- the pingmap make some rounding errors, so we have to define a range and check if the ping is inside this range
    if (eventCodeA >= zosEventCodeMin and eventCodeA <= zosEventCodeMax) and (eventCodeB >= zosEventCodeMin and eventCodeB <= zosEventCodeMax) then
        local eventCode = realEventCode
        self.debug('eventCode matched', eventCode)
        self.debug('eventCode for manti spear')
        -- set last ping to now to prevent spamming
        self.tempVars.last_ping = currentTime

        if lastPingDiff > 5 then
            CENTER_SCREEN_ANNOUNCE:AddMessage(10, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, zo_strformat(GetString(RAIDNOTIFIER_ALERTS_SANCTUM_MANTIKORA_SPEAR_PLAYER), unitName))
        end
    end
end

-- debug func
function RaidNotifier.debug(message, data)
    local self = RaidNotifier
    if self.savedVariables.debug then
        d('RaidNotifier Debug:')
        if data ~= nil then
            d(message, data)
        else
            d(message)
        end
    end
end

---------Events-------
EVENT_MANAGER:RegisterForEvent(RaidNotifier.name, EVENT_ADD_ON_LOADED, RaidNotifier.Initialize)