---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)
local wt = Private.Ace
---@class WTAPI
local WTAPI = WTAPI

Private.OurVersion = "v3.0.1"

Private.saved = {}
Private.config = {}
Private.timers = {}
Private.activeInstances = {}
Private.defaultEncounterNotes = {}
Private.bigWigsCastCounts = {}
Private.rosterData = {}
Private.rosterDataAllPlayers = ""
Private.weakauraPlayerTable = {}
Private.weakauraPlayerCount = 0
Private.weakauraReceiveTimer = nil
Private.weakauraReceivedUpdateCount = 0
Private.versionCheckDone = false
Private.versionReceiveDone = false
Private.partyPoliceAvailable = true

Private.WeakAuras = {
    -- Mandatory
    {version=1, displayName="Liquid Anchors", optional=false, data=Private.weakauraData["Liquid Anchors (don't rename these)"]},
    {version=2, displayName="Liquid Raid", optional=false, data=Private.weakauraData["Liquid - Manaforge Omega"]},
    {version=1, displayName="Wild Things", optional=false, data=Private.weakauraData["Wild Things"]},
    {version=1, displayName="WT - Functions", optional=false, data=Private.weakauraData["Wild Things - Functions"]},
    {version=1, displayName="Interrupt Anchor", optional=false, data=Private.weakauraData["Interrupt Anchor"]},
    -- Optional
    {version=2, displayName="Co-Tank Frames", optional=true, data=Private.weakauraData["Co-Tank Frames"]},
    {version=2, displayName="Helpers/Reminders", optional=true, data=Private.weakauraData["Wild Things - Helpers & Reminders"]},
    {version=1, displayName="Break Timer", optional=true, data=Private.weakauraData["Wild Things - Break Timer"]},
    {version=1, displayName="Missing enchants", optional=true, data=Private.weakauraData["Wild Things - Missing enchants"]},
}

-- Private.WeakAuraMandatory = {
--     "Liquid Anchors (don't rename these)",
--     "Liquid - Manaforge Omega",
--     "Wild Things",
--     "Wild Things - Functions",
--     "Interrupt Anchor",
-- }

-- Private.WeakAuraOptional = {
--     "Co-Tank Frames",
--     "Wild Things - Helpers & Reminders",
--     "Wild Things - Break Timer",
--     "Wild Things - Missing enchants",
-- }

Private.waTypes = {
    WT = "WT Dynamic Text",
    WTB = "WT Dynamic Bar",
    WTSB = "WT Dynamic Special Bar",
    WTA = "WT Dynamic Assignment",
    WTI = "WT Dynamic Icon",
    WTBI = "WT Dynamic Big Icon",
    WTC = "WT Dynamic Circle"
}

Private.eventTypes = {
    SCS = "SPELL_CAST_START",
    SCC = "SPELL_CAST_SUCCESS",
    SAA = "SPELL_AURA_APPLIED",
    SAR = "SPELL_AURA_REMOVED"
}

Private.localERTIcons = {
    -- Raid Target Icon (ID)
    ["[rt1]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1:0|t",
    ["[rt2]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2:0|t",
    ["[rt3]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_3:0|t",
    ["[rt4]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_4:0|t",
    ["[rt5]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_5:0|t",
    ["[rt6]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_6:0|t",
    ["[rt7]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_7:0|t",
    ["[rt8]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_8:0|t",

    -- Raid Target Icon (ENG)
    ["[star]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1:0|t",
    ["[circle]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2:0|t",
    ["[diamond]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_3:0|t",
    ["[triangle]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_4:0|t",
    ["[moon]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_5:0|t",
    ["[square]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_6:0|t",
    ["[cross]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_7:0|t",
    ["[skull]"] = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_8:0|t",

    -- Role Icons
    ["[tank]"] = "|A:Adventures-Tank:0:0|a",
    ["[healer]"] = "|A:Adventures-Healer:0:0|a",
    ["[dps]"] = "|A:Adventures-DPS:0:0|a",

    -- Class Icons
    ["[" .. GetClassInfo(1) .. "]"] = "|A:classicon-warrior:0:0|a",
    ["[Warrior]"] = "|A:classicon-warrior:0:0|a",
    ["[" .. GetClassInfo(2) .. "]"] = "|A:classicon-paladin:0:0|a",
    ["[Paladin]"] = "|A:classicon-paladin:0:0|a",
    ["[" .. GetClassInfo(3) .. "]"] = "|A:classicon-hunter:0:0|a",
    ["[Hunter]"] = "|A:classicon-hunter:0:0|a",
    ["[" .. GetClassInfo(4) .. "]"] = "|A:classicon-rogue:0:0|a",
    ["[Rogue]"] = "|A:classicon-rogue:0:0|a",
    ["[" .. GetClassInfo(5) .. "]"] = "|A:classicon-priest:0:0|a",
    ["[Priest]"] = "|A:classicon-priest:0:0|a",
    ["[" .. GetClassInfo(6) .. "]"] = "|A:classicon-deathknight:0:0|a",
    ["[Death Knight]"] = "|A:classicon-deathknight:0:0|a",
    ["[" .. GetClassInfo(7) .. "]"] = "|A:classicon-shaman:0:0|a",
    ["[Shaman]"] = "|A:classicon-shaman:0:0|a",
    ["[" .. GetClassInfo(8) .. "]"] = "|A:classicon-mage:0:0|a",
    ["[Mage]"] = "|A:classicon-mage:0:0|a",
    ["[" .. GetClassInfo(9) .. "]"] = "|A:classicon-warlock:0:0|a",
    ["[Warlock]"] = "|A:classicon-warlock:0:0|a",
    ["[" .. GetClassInfo(10) .. "]"] = "|A:classicon-monk:0:0|a",
    ["[Monk]"] = "|A:classicon-monk:0:0|a",
    ["[" .. GetClassInfo(11) .. "]"] = "|A:classicon-druid:0:0|a",
    ["[Druid]"] = "|A:classicon-druid:0:0|a",
    ["[" .. GetClassInfo(12) .. "]"] = "|A:classicon-demonhunter:0:0|a",
    ["[Demon Hunter]"] = "|A:classicon-demonhunter:0:0|a",
    ["[" .. GetClassInfo(13) .. "]"] = "|A:classicon-demonhunter:0:0|a",
    ["[Evoker]"] = "|A:classicon-demonhunter:0:0|a",
}

-- Takes a spell ID and returns an in-line icon string
Private.gsubIcon = function(spellID, width, height)
    spellID = tonumber(spellID)
    local spellTexture = C_Spell.GetSpellInfo(spellID).originalIconID
    spellTexture = spellTexture or "Interface\\Icons\\INV_MISC_QUESTIONMARK"

    return string.format("%s %s", CreateTextureMarkup(spellTexture, 64, 64, width, height, 5/64, 59/64, 5/60, 59/64, 0, 0), "")
end

Private.specToType = {
    -- Death Knight
    [250] = "Melee", -- Blood
    [251] = "Melee", -- Frost
    [252] = "Melee", -- Unholy
    -- Demon Hunter
    [577] = "Melee", -- Havoc
    [581] = "Melee", -- Vengeance
    -- Druid
    [102] = "Ranged", -- Balance
    [103] = "Melee", -- Feral
    [104] = "Melee", -- Guardian
    [105] = "Ranged", -- Restoration
    -- Hunter
    [253] = "Ranged", -- Beast Mastery
    [254] = "Ranged", -- Marksmanship
    [255] = "Melee", -- Survival
    -- Mage
    [62] = "Ranged", -- Arcane
    [63] = "Ranged", -- Fire
    [64] = "Ranged", -- Frost
    -- Monk
    [268] = "Melee", -- Brewmaster
    [270] = "Melee", -- Mistweaver
    [269] = "Melee", -- Windwalker
    -- Paladin
    [65] = "Melee", -- Holy
    [66] = "Melee", -- Protection
    [70] = "Melee", -- Retribution
    -- Priest
    [256] = "Ranged", -- Discipline
    [257] = "Ranged", -- Holy
    [258] = "Ranged", -- Shadow
    -- Rogue
    [259] = "Melee", -- Assassination
    [260] = "Melee", -- Outlaw
    [261] = "Melee", -- Subtlety
    -- Shaman
    [262] = "Ranged", -- Elemental
    [263] = "Melee", -- Enhancement
    [264] = "Ranged", -- Restoration
    -- Warlock
    [265] = "Ranged", -- Affliction
    [266] = "Ranged", -- Demonology
    [267] = "Ranged", -- Destruction
    -- Warrior
    [71] = "Melee", -- Arms
    [72] = "Melee", -- Fury
    [73] = "Melee", -- Protection
    -- Evoker
    [1467] = "Ranged", -- Devastation
    [1468] = "Ranged", -- Preservation
    [1473] = "Ranged", -- Augmentation
}

Private.classIDtoClass = {
    -- Death Knight
    [6] = "Death Knight",
    -- Demon Hunter
    [12] = "Demon Hunter",
    -- Druid
    [11] = "Druid",
    -- Hunter
    [3] = "Hunter",
    -- Mage
    [8] = "Mage",
    -- Monk
    [10] = "Monk",
    -- Paladin
    [2] = "Paladin",
    -- Priest
    [5] = "Priest",
    -- Rogue
    [4] = "Rogue",
    -- Shaman
    [7] = "Shaman",
    -- Warlock
    [9] = "Warlock",
    -- Warrior
    [1] = "Warrior",
    -- Evoker
    [13] = "Evoker",
}

Private.encounterOrder = {2144, 3129, 3131, 3130, 3132, 3122, 3133, 3134, 3135}

Private.encounterIdToName = {
    [2144] = "Taloc",
    [3129] = "Sentinel",
    [3131] = "Loomithar",
    [3130] = "Soulbinder",
    [3132] = "Forgeweaver",
    [3122] = "Soul Hunters",
    [3133] = "Fractillus",
    [3134] = "Nexus-King",
    [3135] = "Dimensius",
}

Private.encounterIdToJournalId = {
    [2144] = 2168,
    [3129] = 2684,
    [3131] = 2686,
    [3130] = 2685,
    [3132] = 2687,
    [3122] = 2688,
    [3133] = 2747,
    [3134] = 2690,
    [3135] = 2691,
}

local phaseColor = "|cffffff55"

Private.assignmentIds = {
    ["nsdispel1"] = "Your Dispel Position: {pos}",
    -- Nerub'ar Palace
    -- 1. Ulgrax
    ["UlgraxGrp1"] = "Group 1",
    ["UlgraxGrp2"] = "Group 2",
    -- 2. Bloodbound Horror
    ["HorrorGrp1"] = "Group 1",
    ["HorrorGrp2"] = "Group 2",
    -- 3. Sikran
    -- 4. Rasha'nan
    -- 5. Ovi'nax
    ["OvinaxYellow"] = "Egg World Mark: " .. Private.localERTIcons["[star]"],
    ["OvinaxOrange"] = "Egg World Mark: " .. Private.localERTIcons["[circle]"],
    ["OvinaxPurple"] = "Egg World Mark: " .. Private.localERTIcons["[diamond]"],
    ["OvinaxGreen"] = "Egg World Mark: " .. Private.localERTIcons["[triangle]"],
    ["int:219046:446700:skull"] = "|cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[skull]"] .. " |cffaf7878Voracious Worm|r ",
    ["int:219046:446700:cross"] = "|cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[cross]"] .. " |cffaf7878Voracious Worm|r ",
    ["int:219046:446700:square"] = "|cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[square]"] .. " |cffaf7878Voracious Worm|r ",
    -- 6. Ky'veza
    ["Pos1"] = "Position 1 (" .. Private.localERTIcons["[diamond]"] .. ")",
    ["Pos2"] = "Position 2 (" .. Private.localERTIcons["[triangle]"] .. ")",
    ["Pos3"] = "Position 3 (" .. Private.localERTIcons["[square]"] .. ")",
    ["Pos4"] = "Position 4 (" .. Private.localERTIcons["[circle]"] .. ")",
    ["Pos5"] = "Position 5 (" .. Private.localERTIcons["[star]"] .. ")",
    ["Pos6"] = "Position 6 (" .. Private.localERTIcons["[cross]"] .. ")",
    ["Pos7"] = "Position 7 (" .. Private.localERTIcons["[diamond]"] .. ")",
    ["Pos8"] = "Position 8 (" .. Private.localERTIcons["[square]"] .. ")",
    ["Pos9"] = "Position 9 (" .. Private.localERTIcons["[diamond]"] .. ")",
    ["Pos10"] = "Position 10 (" .. Private.localERTIcons["[triangle]"] .. ")",
    ["Pos11"] = "Position 11 (" .. Private.localERTIcons["[square]"] .. ")",
    ["Pos12"] = "Position 12 (" .. Private.localERTIcons["[circle]"] .. ")",
    ["Pos13"] = "Position 13 (" .. Private.localERTIcons["[star]"] .. ")",
    ["Pos14"] = "Position 14 (" .. Private.localERTIcons["[cross]"] .. ")",
    ["Pos15"] = "Position 15 (" .. Private.localERTIcons["[diamond]"] .. ")",
    ["Pos16"] = "Position 16 (" .. Private.localERTIcons["[triangle]"] .. ")",
    ["Pos17"] = "Position 17 (" .. Private.localERTIcons["[square]"] .. ")",
    ["Pos18"] = "Position 18 (" .. Private.localERTIcons["[circle]"] .. ")",
    ["Pos19"] = "Position 19 (" .. Private.localERTIcons["[star]"] .. ")",
    ["Pos20"] = "Position 20 (" .. Private.localERTIcons["[cross]"] .. ")",
    -- 7. Silken Court
    ["AllRedGrp1"] = "Right side: |cffff3333Red|r (|cffaf7878Anub'arash|r) | |cffffff55Position:|r {pos}",
    ["AllBlueGrp2"] = "Left side: |cff3333ffBlue|r (|cffaf7878Skeinspinner Takazj|r) | |cffffff55Position:|r {pos+10}",
    ["TriangleInt"] = phaseColor .. "1. Intermission" .. "|r Outer static Position: " .. Private.localERTIcons["[triangle]"],
    ["DiamondInt"] = phaseColor .. "1. Intermission" .. "|r Outer static Position: " .. Private.localERTIcons["[diamond]"],
    -- 8. Ansurek
    ["b1star"] = phaseColor .. "P1" .. "|r Bombe 1: Outer " .. Private.localERTIcons["[star]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b1circle"] = phaseColor .. "P1" .. "|r Bombe 1: Middle " .. Private.localERTIcons["[circle]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b2star"] = phaseColor .. "P1" .. "|r Bombe 2: Outer " .. Private.localERTIcons["[star]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b2circle"] = phaseColor .. "P1" .. "|r Bombe 2: Middle " .. Private.localERTIcons["[circle]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b2diamond"] = phaseColor .. "P1" .. "|r Bombe 2: Inner " .. Private.localERTIcons["[diamond]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b3star"] = phaseColor .. "P1" .. "|r Bombe 3: Outer " .. Private.localERTIcons["[star]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b3circle"] = phaseColor .. "P1" .. "|r Bombe 3: Middle " .. Private.localERTIcons["[circle]"] .. "{pos1: |cffff3333(YOU POP)|r}",
    ["b3diamond"] = phaseColor .. "P1" .. "|r Bombe 3: Inner " .. Private.localERTIcons["[diamond]"] .. "{pos1: |cffff3333(YOU POP)|r}",

    ["AnsurekIntBlueGrp1"] = phaseColor .. "Intermission" .. "|r Melee Side " .. Private.localERTIcons["[square]"],
    ["AnsurekIntGreenGrp2"] = phaseColor .. "Intermission" .. "|r Range Side " .. Private.localERTIcons["[triangle]"],

    ["int:223150:447950:moon"] = phaseColor .. "P2" .. "|r Main Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[moon]"] .. " |cffaf7878Ascended Voidspeaker|r ",
    ["int:223150:447950:circle"] = phaseColor .. "P2" .. "|r Main Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[circle]"] .. " |cffaf7878Ascended Voidspeaker|r ",
    ["int:223150:447950:square"] = phaseColor .. "P2" .. "|r 3. Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[square]"] .. " |cffaf7878Ascended Voidspeaker|r ",
    ["int:223150:447950:cross"] = phaseColor .. "P2" .. "|r 3. Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[cross]"] .. " |cffaf7878Ascended Voidspeaker|r ",

    ["int:226200:455374:star"] = phaseColor .. "P2" .. "|r 2. Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[star]"] .. " |cffaf7878Chamber Acolyte|r ",
    ["int:226200:455374:triangle"] = phaseColor .. "P2" .. "|r 2. Platform - |cffff3333{pos}.|r Interrupt{pos1: and |cffff3333Mark|r} " .. Private.localERTIcons["[triangle]"] .. " |cffaf7878Chamber Acolyte|r ",

    ["nsgate1"] = phaseColor .. "P2" .. "|r Gate Melee Side " .. Private.localERTIcons["[square]"],
    ["nsgate2"] = phaseColor .. "P2" .. "|r Gate Range Side " .. Private.localERTIcons["[triangle]"],

    ["nsessence1"] = phaseColor .. "P3" .. "|r 1. Essence",
    ["nsessence2"] = phaseColor .. "P3" .. "|r 2. Essence",

    -- Liberation of Undermine
    -- 2. Cauldron of Carnage
    ["FireGrp1"] = phaseColor .. "Starting Position|r: Left side - |cffff3333Fire|r",
    ["LightningGrp2"] = phaseColor .. "Starting Position|r: Right side - |cff3333ffLightning|r",

    -- 3. Rik Reverb
    ["nsrik1"] = "Pylon " .. Private.localERTIcons["[star]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik2"] = "Pylon " .. Private.localERTIcons["[circle]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik3"] = "Pylon " .. Private.localERTIcons["[diamond]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik4"] = "Pylon " .. Private.localERTIcons["[triangle]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik5"] = "Pylon " .. Private.localERTIcons["[moon]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik6"] = "Pylon " .. Private.localERTIcons["[square]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik7"] = "Pylon " .. Private.localERTIcons["[cross]"] .. " - Position: |cffff3333{pos+-1}|r",
    ["nsrik8"] = "Pylon " .. Private.localERTIcons["[skull]"] .. " - Position: |cffff3333{pos+-1}|r",

    -- 7. Mug'Zee, Heads of Security
    ["EarthSoakDiamondGrp1"] = phaseColor .. "(Red Side)|r " .. Private.gsubIcon(472631, 12, 12) .. "Earth Soak: " .. Private.localERTIcons["[diamond]"],
    ["EarthSoakStarGrp2"] = phaseColor .. "(Red Side)|r " .. Private.gsubIcon(472631, 12, 12) .. "Earth Soak: " .. Private.localERTIcons["[star]"],

    ["RocketSoak1"] = phaseColor .. "(Blue Side)|r " .. Private.gsubIcon(467381, 12, 12) .. "Rocket Soak: Group 1",
    ["RocketSoak2"] = phaseColor .. "(Blue Side)|r " .. Private.gsubIcon(467381, 12, 12) .. "Rocket Soak: Group 2",


}

Private.assignmentImages = {
    -- Nerub'ar Palace
    -- 6. Ky'veza
    [2920] = {
        [1] = {
            ["path"] = "Interface\\AddOns\\%s\\Media\\Images\\Assignments\\TWW1\\6_kyveza_intermission_positions.png",
            ["width"] = 348,
            ["height"] = 300,
        },
    },
    -- 7. Silken Court
    [2921] = {
        [1] = {
            ["path"] = "Interface\\AddOns\\%s\\Media\\Images\\Assignments\\TWW1\\7_silkencourt_venomous_rain.png",
            ["width"] = 300,
            ["height"] = 300,
        },
        [2] = {
            ["path"] = "Interface\\AddOns\\%s\\Media\\Images\\Assignments\\TWW1\\7_silkencourt_web_pull.png",
            ["width"] = 300,
            ["height"] = 300,
        },
    },

    -- Liberation of Undermine
}

Private.ttsVoiceID = -1

-- Check if the selected voice is valid
for _, voiceData in ipairs(C_VoiceChat.GetTtsVoices()) do
    local voiceID = -1--Private.config.TTS - 2

    if voiceID == voiceData.voiceID then
        Private.ttsVoiceID = voiceID
    end
end

-- Play a preview sound when the text-to-speech voice is changed in custom options
if Private.ttsVoiceID > -1 and Private.saved.ttsVoiceID and Private.ttsVoiceID ~= Private.saved.ttsVoiceID then
    C_VoiceChat.SpeakText(
        Private.ttsVoiceID,
        "TEST VOICE",
        Enum.VoiceTtsDestination.RemoteTransmission,
        C_TTSSettings and C_TTSSettings.GetSpeechRate() or 0,
        C_TTSSettings and C_TTSSettings.GetSpeechVolume() or 50
    )
end

Private.saved.ttsVoiceID = Private.ttsVoiceID

Private.tcopy = function(obj, seen)
    if type(obj) ~= 'table' then return obj end
    if seen and seen[obj] then return seen[obj] end
    local s = seen or {}
    local res = setmetatable({}, getmetatable(obj))
    s[obj] = res
    for k, v in pairs(obj) do res[Private.tcopy(k, s)] = Private.tcopy(v, s) end
    return res
end

Private.tlength = function(T)
    local count = 0
    for _ in pairs(T) do count = count + 1 end
    return count
end

Private.printTable = function(tbl, indent)
    if type(tbl) ~= "table" then
        print("printTable: not a table, got:", tostring(tbl))
        return
    end
    indent = indent or ""
    for k, v in pairs(tbl) do
        if type(v) == "table" then
            print(indent .. k .. ":")
            Private.printTable(v, indent .. "  ")
        else
            print(indent .. k .. ": " .. tostring(v))
        end
    end
end

Private.CheckInstanceID = function(instanceID)
    if Private.activeInstances[instanceID] == nil then
      return false
    else
        if instanceID == 1861 or instanceID == 2164 then
            local _, battleTag, _, _, _, _, _ = BNGetInfo()
            if battleTag == "Sniqi#2790" then
                return true
            else
                return false
            end
        else
            return true
        end
    end
end

Private.CheckEncounterID = function(encounterID)
    if Private.defaultEncounterNotes[encounterID] == nil then
      return false
    else
      return true
    end
end

Private.GetUnitAura = function(unit, spell, filter)
    if not filter then filter = "HELPFUL|HARMFUL" end

    local r_name, r_icon, r_count, r_dispelType, r_duration, r_expirationTime, r_source, r_isStealable, r_nameplateShowPersonal, r_spellId, r_canApplyAura, r_isBossDebuff, r_castByPlayer, r_nameplateShowAll, r_timeMod

    AuraUtil.ForEachAura(unit, filter, nil, function(name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod)
        if spellId == spell then
            r_name, r_icon, r_count, r_dispelType, r_duration, r_expirationTime, r_source, r_isStealable, r_nameplateShowPersonal, r_spellId, r_canApplyAura, r_isBossDebuff, r_castByPlayer, r_nameplateShowAll, r_timeMod = name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod
            return true
        end
    end)

    return r_name, r_icon, r_count, r_dispelType, r_duration, r_expirationTime, r_source, r_isStealable, r_nameplateShowPersonal, r_spellId, r_canApplyAura, r_isBossDebuff, r_castByPlayer, r_nameplateShowAll, r_timeMod
end

Private.compare_versions = function(v1, v2)
    local function split(version)
        local parts = {}
        version = version:match("^v?(.*)")
        for num in version:gmatch("%d+") do
            table.insert(parts, tonumber(num))
        end
        return parts
    end

    local v1_parts = split(v1)
    local v2_parts = split(v2)

    for i = 1, math.max(#v1_parts, #v2_parts) do
        local num1 = v1_parts[i] or 0
        local num2 = v2_parts[i] or 0
        if num1 < num2 then
            return -1  -- v1 ist kleiner als v2 (Update verfügbar)
        elseif num1 > num2 then
            return 1   -- v1 ist größer als v2
        end
    end
    return 0  -- Beide Versionen sind gleich
end

function WTAPI:ParseTooltipText(tooltipText)
    if tooltipText and tooltipText.lines and tooltipText.lines[2] and tooltipText.lines[2].leftText then
        tooltipText = tooltipText.lines[2].leftText
        local debuffType = "none";
        local tooltipSize = {};
        if(tooltipText) then
        for t in tooltipText:gmatch("(-?%d[%d%.,]*)") do
            if (LARGE_NUMBER_SEPERATOR == ",") then
            t = t:gsub(",", "");
            else
            t = t:gsub("%.", "");
            t = t:gsub(",", ".");
            end
            tinsert(tooltipSize, tonumber(t));
        end
        end

        if (#tooltipSize) then
        return tooltipText, debuffType, unpack(tooltipSize);
        else
        return tooltipText, debuffType, 0;
        end
    end
end

Private.WAIterateGroupMembers = function(reversed, forceParty)
    local unit = (not forceParty and IsInRaid()) and 'raid' or 'party'
    local numGroupMembers = unit == 'party' and GetNumSubgroupMembers() or GetNumGroupMembers()
    local i = reversed and numGroupMembers or (unit == 'party' and 0 or 1)
    return function()
        local ret
        if i == 0 and unit == 'party' then
            ret = 'player'
        elseif i <= numGroupMembers and i > 0 then
            ret = unit .. i
        end
        i = i + (reversed and -1 or 1)
        return ret
    end
end
