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


RaidNotifier = RaidNotifier or {}

RaidNotifier.name		= 'RaidNotifier'
RaidNotifier.slash		= '/rn'
RaidNotifier.version	= '1.2.1'
RaidNotifier.versionDB	= 1
RaidNotifier.loaded	    = false
RaidNotifier.author     = 'silentgecko'
RaidNotifier.savedVarsName  = 'RNVars'
RaidNotifier.variables = {
    sanctum_ophidia = {
        magicka_deto      = true,
        poison            = true,
    },
    general = {
        buffFood_reminder = true,
    }
}
RaidNotifier.tempVars = {
    last_notify = {
        sanctum_ophidia = {
            magicka_deto = 0,
            poison       = 0,
        },
        general = {
            buffFood_reminder = 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,
    }

    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 = "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,
        },
    }

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


---------Passing saved variables to the labels at initialize-------
function RaidNotifier.Initialize(event, 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, EVENT_EFFECT_CHANGED, self.generalBuffFoodReminder)
    end

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

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

    EVENT_MANAGER:UnregisterForEvent(self.name, EVENT_EFFECT_CHANGED)
end

function RaidNotifier.sanctumDebuffs(_, change, buff, name, unit, start, finish, stack, icon, _, effectType, abilityType, statusEffectType, unitName, unitId, abilityId)
    -- only take care of player
    if (unit ~= 'player') then return end

    local self = RaidNotifier
    local buffsDebuffs = self.BuffsDebuffs.sanctum_ophidia

    -- only notice on effect added
    if (change == EFFECT_RESULT_GAINED) then
        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

        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
    end
end

function RaidNotifier.generalBuffFoodReminder(_, change, buff, name, unit, start, finish, stack, icon, _, effectType, abilityType, statusEffectType, unitName, unitId, abilityId)
    -- only take care of player
    if (unit ~= 'player') then return end

    local self = RaidNotifier

    -- 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 numAuras = GetNumBuffs('player')
    if (numAuras > 0) then
        local currentTime = GetTimeStamp()

        for x = 1, numAuras do
            local name, start, 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)

                if bufffood_remaining <= 60 and (lastNotifyDiff > 49) then
                   -- alert 1 min
                   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))
                elseif bufffood_remaining <= 120 and (lastNotifyDiff > 170) then
                   -- alert 2 min
                   self.tempVars.last_notify.general.buffFood_reminder = currentTime
                   CENTER_SCREEN_ANNOUNCE:AddMessage(7, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, zo_strformat(GetString(RAIDNOTIFIER_ALERTS_GENERAL_BUFFFOOD_MINUTES), name, formatedTime))
                elseif bufffood_remaining <= 300 and (lastNotifyDiff > 3600) then
                   -- alert 5 min
                   self.tempVars.last_notify.general.buffFood_reminder = currentTime
                   CENTER_SCREEN_ANNOUNCE:AddMessage(10, CSA_EVENT_SMALL_TEXT, SOUNDS.CHAMPION_POINTS_COMMITTED, zo_strformat(GetString(RAIDNOTIFIER_ALERTS_GENERAL_BUFFFOOD_MINUTES), name, formatedTime))
                end
            end
        end

        -- no bufffood found, alert every minute
        if buffFoodFound == false then
            local lastNotify     = self.tempVars.last_notify.general.buffFood_reminder
            local lastNotifyDiff = GetDiffBetweenTimeStamps(currentTime, lastNotify)
            if lastNotifyDiff > 60 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

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