-------------------------------------------------------------------------------
---------------------------------- NAMESPACE ----------------------------------
-------------------------------------------------------------------------------

local ADDON_NAME, ns = ...
local Class = ns.Class
local Group = ns.Group
local L = ns.locale

local Map = ns.Map

local Mount = ns.reward.Mount
local Pet = ns.reward.Pet
local Reward = ns.reward.Reward
local Toy = ns.reward.Toy
local Transmog = ns.reward.Transmog

-------------------------------------------------------------------------------

ns.expansion = 9

-------------------------------------------------------------------------------
------------------------------------ ICONS ------------------------------------
-------------------------------------------------------------------------------

local ICONS = "Interface\\Addons\\"..ADDON_NAME.."\\artwork\\icons"
local GLOWS = "Interface\\Addons\\"..ADDON_NAME.."\\artwork\\glows"
local function Icon(name) return ICONS..'\\'..name..'.blp' end
local function Glow(name) return GLOWS..'\\'..name..'.blp' end

ns.icons.cov_sigil_ky = {Icon('covenant_kyrian'), nil}
ns.icons.cov_sigil_nl = {Icon('covenant_necrolord'), nil}
ns.icons.cov_sigil_nf = {Icon('covenant_nightfae'), nil}
ns.icons.cov_sigil_vn = {Icon('covenant_venthyr'), nil}
ns.icons.tormentor = {Icon('tormentor'), Glow('tormentor')}

-------------------------------------------------------------------------------
---------------------------------- CALLBACKS ----------------------------------
-------------------------------------------------------------------------------

ns.addon:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED', function ()
    -- Listen for aura applied/removed events so we can refresh when the player
    -- enters and exits the rift in Korthia and the Maw
    local _,e,_,_,_,_,_,_,t,_,_,s  = CombatLogGetCurrentEventInfo()
    if (e == 'SPELL_AURA_APPLIED' or e == 'SPELL_AURA_REMOVED') and
        t == UnitName('player') and (s == 352795 or s == 354870) then
        C_Timer.After(1, function() ns.addon:Refresh() end)
    end
end)

ns.addon:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED', function (...)
    -- Watch for a spellcast event that signals the kitten was pet.
    -- https://www.wowhead.com/spell=321337/petting
    -- Watch for a spellcast event for collecting a shard
    -- https://shadowlands.wowhead.com/spell=335400/collecting
    local _, source, _, spellID = ...
    if source == 'player' and (spellID == 321337 or spellID == 335400) then
        C_Timer.After(1, function() ns.addon:Refresh() end)
    end
end)

-------------------------------------------------------------------------------
------------------------------ CALLING TREASURES ------------------------------
-------------------------------------------------------------------------------

-- Add reward information to Blizzard's vignette treasures for callings

local GILDED_WADER = Pet({item=180866, id=2938}) -- Gilded Wader

local BLEAKWOOD_CHEST = { Pet({item=180592, id=2901}) } -- Trapped Stonefiend
local BROKEN_SKYWARD_BELL = { GILDED_WADER, Toy({item=184415}) } -- Soothing Vesper
local DECAYED_HUSK = {
    Transmog({item=179593, slot=L["cloth"]}), -- Darkreach Mask
    Transmog({item=179594, slot=L["leather"]}), -- Witherscorn Guise
}
local GILDED_CHEST = { Toy({item=184418}) } -- Acrobatic Steward
local HIDDEN_HOARD = { GILDED_WADER }
local HUNT_SHADEHOUNDS = { Mount({item=184167, id=1304}) } -- Mawsworn Soulhunter
local SECRET_TREASURE = { Pet({item=180589, id=2894}) } -- Burdened Soul
local SILVER_STRONGBOX = { GILDED_WADER }
local SLIME_COATED_CRATE = {
    Pet({item=181262, id=2952}), -- Bubbling Pustule
    Toy({item=184447}) -- Kevin's Party Supplies
}
local SPOUTING_GROWTH = { Pet({item=181173, id=2949}) } -- Skittering Venomspitter

local VIGNETTES = {
    [4173] = SECRET_TREASURE,
    [4174] = SECRET_TREASURE,
    [4175] = SECRET_TREASURE,
    [4176] = SECRET_TREASURE,
    [4177] = SECRET_TREASURE,
    [4178] = SECRET_TREASURE,
    [4179] = SECRET_TREASURE,
    [4180] = SECRET_TREASURE,
    [4181] = SECRET_TREASURE,
    [4182] = SECRET_TREASURE,
    [4202] = SPOUTING_GROWTH,
    [4212] = BLEAKWOOD_CHEST,
    [4214] = GILDED_CHEST,
    [4217] = DECAYED_HUSK,
    [4218] = DECAYED_HUSK,
    [4219] = DECAYED_HUSK,
    [4220] = DECAYED_HUSK,
    [4221] = DECAYED_HUSK,
    [4239] = BROKEN_SKYWARD_BELL,
    [4240] = BROKEN_SKYWARD_BELL,
    [4241] = BROKEN_SKYWARD_BELL,
    [4242] = BROKEN_SKYWARD_BELL,
    [4243] = BROKEN_SKYWARD_BELL,
    [4263] = SILVER_STRONGBOX,
    [4264] = SILVER_STRONGBOX,
    [4265] = SILVER_STRONGBOX,
    [4266] = SILVER_STRONGBOX,
    [4267] = SILVER_STRONGBOX,
    [4268] = SILVER_STRONGBOX,
    [4269] = SILVER_STRONGBOX,
    [4270] = SILVER_STRONGBOX,
    [4271] = SILVER_STRONGBOX,
    [4272] = SILVER_STRONGBOX,
    [4273] = SILVER_STRONGBOX,
    [4275] = BROKEN_SKYWARD_BELL,
    [4276] = HIDDEN_HOARD,
    [4277] = HIDDEN_HOARD,
    [4278] = HIDDEN_HOARD,
    [4279] = HIDDEN_HOARD,
    [4280] = HIDDEN_HOARD,
    [4281] = HIDDEN_HOARD,
    [4362] = SPOUTING_GROWTH,
    [4363] = SPOUTING_GROWTH,
    [4366] = SLIME_COATED_CRATE,
    [4460] = HUNT_SHADEHOUNDS,
    [4577] = SILVER_STRONGBOX
}

local vignetteHandled = false

hooksecurefunc(GameTooltip, 'Show', function(self)
    if vignetteHandled then return end
    local owner = self:GetOwner()
    if owner and owner.vignetteID then
        local rewards = VIGNETTES[owner.vignetteID]
        if rewards and #rewards > 0 then
            self:AddLine(' ') -- add blank line before rewards
            for i, reward in ipairs(rewards) do
                if reward:IsEnabled() then
                    reward:Render(self)
                end
            end
            vignetteHandled = true
            self:Show()
       end
    end
end)

hooksecurefunc(GameTooltip, 'ClearLines', function(self)
    vignetteHandled = false
end)

-------------------------------------------------------------------------------
---------------------------------- COVENANTS ----------------------------------
-------------------------------------------------------------------------------

ns.covenants = {
    KYR = { id = 1, icon = 'cov_sigil_ky', assault=63824 },
    VEN = { id = 2, icon = 'cov_sigil_vn', assault=63822 },
    FAE = { id = 3, icon = 'cov_sigil_nf', assault=63823 },
    NEC = { id = 4, icon = 'cov_sigil_nl', assault=63543 }
}

local function ProcessCovenant (node)
    local covenant = node.covenant or node.assault
    if not covenant then return end
    if node._covenantProcessed then return end

    local name = C_Covenants.GetCovenantData(covenant.id).name
    local str = node.covenant and L["covenant_required"] or L["cov_assault_only"]
    local subl = ns.color.Orange(string.format(str, name))
    local ricon = ns.GetIconLink(covenant.icon, 13)

    -- not compatible with rlabel getters
    if not node.getters.rlabel then
        node.rlabel = node.rlabel and node.rlabel..' '..ricon or ricon
    end
    node.sublabel = node.sublabel and subl..'\n'..node.sublabel or subl
    node._covenantProcessed = true
end

function Reward:GetCategoryIcon()
    return self.covenant and ns.GetIconPath(self.covenant.icon)
end

function Reward:IsObtainable()
    if self.covenant then
        if self.covenant.id ~= C_Covenants.GetActiveCovenantID() then
            return false
        end
    end
    return true
end

-------------------------------------------------------------------------------
----------------------------------- GROUPS ------------------------------------
-------------------------------------------------------------------------------

ns.groups.ANIMA_SHARD = Group('anima_shard', 'crystal_b', {defaults=ns.GROUP_HIDDEN})
ns.groups.BLESSINGS = Group('blessings', 1022951, {defaults=ns.GROUP_HIDDEN})
ns.groups.BONUS_BOSS = Group('bonus_boss', 'peg_rd', {defaults=ns.GROUP_HIDDEN})
ns.groups.CARRIAGE = Group('carriages', 'horseshoe_g', {defaults=ns.GROUP_HIDDEN})
ns.groups.DREDBATS = Group('dredbats', 'flight_point_g', {defaults=ns.GROUP_HIDDEN})
ns.groups.FAERIE_TALES = Group('faerie_tales', 355498, {defaults=ns.GROUP_HIDDEN})
ns.groups.FUGITIVES = Group('fugitives', 236247, {defaults=ns.GROUP_HIDDEN})
ns.groups.GRAPPLES = Group('grapples', 'peg_bk', {defaults=ns.GROUP_HIDDEN})
ns.groups.HELGARDE_CACHE = Group('helgarde_cache', 'chest_gy', {defaults=ns.GROUP_HIDDEN75})
ns.groups.HYMNS = Group('hymns', 'scroll', {defaults=ns.GROUP_HIDDEN})
ns.groups.INQUISITORS = Group('inquisitors', 3528307, {defaults=ns.GROUP_HIDDEN})
ns.groups.INVASIVE_MAWSHROOM = Group('invasive_mawshroom', 134534, {defaults=ns.GROUP_HIDDEN75})
ns.groups.KORTHIA_SHARED = Group('korthia_dailies', 1506458, {defaults=ns.GROUP_HIDDEN75})
ns.groups.MAWSWORN_CACHE = Group('mawsworn_cache', 3729814, {defaults=ns.GROUP_HIDDEN75})
ns.groups.NEST_MATERIALS = Group('nest_materials', 136064, {defaults=ns.GROUP_HIDDEN75})
ns.groups.NILGANIHMAHT_MOUNT = Group('nilganihmaht', 1391724, {defaults=ns.GROUP_HIDDEN75})
ns.groups.RIFT_HIDDEN_CACHE = Group('rift_hidden_cache', 'chest_bk', {defaults=ns.GROUP_ALPHA75})
ns.groups.RIFT_PORTAL = Group('rift_portal', 'portal_gy')
ns.groups.RIFTBOUND_CACHE = Group('riftbound_cache', 'chest_bk', {defaults=ns.GROUP_ALPHA75})
ns.groups.RIFTSTONE = Group('riftstone', 'portal_bl')
ns.groups.SINRUNNER = Group('sinrunners', 'horseshoe_o', {defaults=ns.GROUP_HIDDEN})
ns.groups.SLIME_CAT = Group('slime_cat', 3732497, {defaults=ns.GROUP_HIDDEN})
ns.groups.STYGIA_NEXUS = Group('stygia_nexus', 'peg_gn', {defaults=ns.GROUP_HIDDEN75})
ns.groups.STYGIAN_CACHES = Group('stygian_caches', 'chest_nv', {defaults=ns.GROUP_HIDDEN75})
ns.groups.VESPERS = Group('vespers', 3536181, {defaults=ns.GROUP_HIDDEN})
ns.groups.ZOVAAL_VAULT = Group('zovault', 'star_chest_g', {defaults=ns.GROUP_ALPHA75})

ns.groups.ANIMA_VESSEL = Group('anima_vessel', 'chest_tl', {
    defaults=ns.GROUP_ALPHA75,
    IsEnabled=function (self)
        -- Anima vessels and caches cannot be seen until the "Vault Anima Tracker"
        -- upgrade is purchased from the Death's Advance quartermaster
        if not C_QuestLog.IsQuestFlaggedCompleted(64061) then return false end
        return Group.IsEnabled(self)
    end
})

ns.groups.BROKEN_MIRROR = Group('broken_mirror', 3854020, {
    defaults=ns.GROUP_ALPHA75,
    IsEnabled=function (self)
        -- Broken mirrors are Venthyr-only (might have completed the quest and then swapped covenants)
        if C_Covenants.GetActiveCovenantID() ~= 2 then return false end
        -- Broken mirrors cannot be accessed until the quest "Repair and Restore" is completed
        if not C_QuestLog.IsQuestFlaggedCompleted(59740) then return false end
        return Group.IsEnabled(self)
    end
})

ns.groups.RELIC = Group('relic', 'star_chest_b', {
    defaults=ns.GROUP_ALPHA75,
    IsEnabled=function (self)
        -- Relics cannot be collected until the quest "What Must Be Found" is completed
        if not C_QuestLog.IsQuestFlaggedCompleted(64506) then return false end
        return Group.IsEnabled(self)
    end
})

-------------------------------------------------------------------------------
------------------------------------ MAPS -------------------------------------
-------------------------------------------------------------------------------

local SLMap = Class('ShadowlandsMap', Map)

function SLMap:Prepare ()
    Map.Prepare(self)
    for coord, node in pairs(self.nodes) do
        -- Update rlabel and sublabel for covenant-restricted nodes
        ProcessCovenant(node)
    end
end

ns.Map = SLMap

-------------------------------------------------------------------------------

local RiftMap = Class('RiftMap', SLMap)

function RiftMap:Prepare()
    SLMap.Prepare(self)

    self.rifted = false
    for i, spellID in ipairs{352795, 354870} do
        if AuraUtil.FindAuraByName(GetSpellInfo(spellID), 'player') then
            self.rifted = true
        end
    end
end

function RiftMap:CanDisplay(node, coord, minimap)
    -- check node's rift availability (nil=no, 1=yes, 2=both)
    if self.rifted and not node.rift then return false end
    if not self.rifted and node.rift == 1 then return false end
    return SLMap.CanDisplay(self, node, coord, minimap)
end

ns.RiftMap = RiftMap

-------------------------------------------------------------------------------
--------------------------------- REQUIREMENTS --------------------------------
-------------------------------------------------------------------------------

local Venari = Class('Venari', ns.requirement.Requirement)

function Venari:Initialize(quest)
    self.text = L["venari_upgrade"]
    self.quest = quest
end

function Venari:IsMet()
    return C_QuestLog.IsQuestFlaggedCompleted(self.quest)
end

ns.requirement.Venari = Venari
