local ADDON_NAME, Addon = ...

---------------------------------------------------------------------------------------------------
-- Imported functions and constants
---------------------------------------------------------------------------------------------------

-- Lua APIs

-- WoW APIs
local EvaluateColorValueFromBoolean = C_CurveUtil and C_CurveUtil.EvaluateColorValueFromBoolean
local CreateColor = CreateColor

-- ThreatPlates APIs

local _G =_G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: 

---------------------------------------------------------------------------------------------------
-- Register events available in an expansion centrally
---------------------------------------------------------------------------------------------------

local WOW_EVENTS = {
  ACTIVE_TALENT_GROUP_CHANGED = Addon.ExpansionIsAtLeastCata,
  ARENA_OPPONENT_UPDATE = true, -- Added in 3.1.0 / 1.14.0
  BN_CONNECTED = true,
  BN_FRIEND_ACCOUNT_OFFLINE = true,
  BN_FRIEND_ACCOUNT_ONLINE = true,
  COMBAT_LOG_EVENT_UNFILTERED = not Addon.ExpansionIsAtLeastMidnight, -- Removed in Midnight
  FRIENDLIST_UPDATE = true,
  GUILD_ROSTER_UPDATE = true,
  GROUP_LEFT = true,
  GROUP_ROSTER_UPDATE = true,   -- Added in 5.0.4 / 1.13.2, also can be registered in Cata Classic
  NAME_PLATE_CREATED = true,
  NAME_PLATE_UNIT_ADDED = true,
  NAME_PLATE_UNIT_REMOVED = true,
  PLAYER_CONTROL_GAINED = true,
  PLAYER_CONTROL_LOST = true,
  PLAYER_ENTERING_WORLD = true,
  PLAYER_FLAGS_CHANGED = true,
  PLAYER_FOCUS_CHANGED = Addon.ExpansionIsAtLeastTBC,
  PLAYER_LOGIN = true,
  PLAYER_MAP_CHANGED = Addon.ExpansionIsAtLeastTWW, -- Added in 11.0.0 (TWW)
  PLAYER_REGEN_DISABLED = true,
  PLAYER_REGEN_ENABLED = true,
  PLAYER_SOFT_ENEMY_CHANGED = true,
  PLAYER_SOFT_FRIEND_CHANGED = true,
  PLAYER_SOFT_INTERACT_CHANGED = true,
  PLAYER_TARGET_CHANGED = true,
  PVP_MATCH_ACTIVE = Addon.IS_MAINLINE, -- BfA Patch 8.2.0 (2019-06-25): Added.
  QUEST_ACCEPTED = true,
  QUEST_DATA_LOAD_RESULT = Addon.IS_MAINLINE, -- Added in 8.2.5
  QUEST_LOG_UPDATE = true,
  QUEST_REMOVED = true,
  QUEST_WATCH_UPDATE = true,
  RAID_TARGET_UPDATE = true,
  RUNE_POWER_UPDATE = Addon.ExpansionIsAtLeastWrath,
  RUNE_TYPE_UPDATE = Addon.ExpansionIsBetween(LE_EXPANSION_WRATH_OF_THE_LICH_KING, LE_EXPANSION_LEGION),
  RUNE_UPDATED = Addon.IS_CLASSIC_SOD, -- Only needed for Rogue rune detection in SoD Classic
  TRAIT_CONFIG_UPDATED = Addon.ExpansionIsAtLeastCata, 
  UI_SCALE_CHANGED = true,
  UNIT_ABSORB_AMOUNT_CHANGED = Addon.WOW_FEATURE_ABSORBS, -- Absorbs (or at least absorbs functions) were added in Mists
  UNIT_AURA = true,
  UNIT_DISPLAYPOWER = true,
  UNIT_FACTION = true,
  UNIT_FLAGS = true,
  UNIT_HEAL_ABSORB_AMOUNT_CHANGED = Addon.WOW_FEATURE_ABSORBS, -- Absorbs (or at least absorbs functions) were added in Mists
  UNIT_HEALTH = Addon.ExpansionIsAtLeastMists, -- Shadowlands Patch 9.0.1 (2020-10-13): Fully replaces UNIT_HEALTH_FREQUENT
  UNIT_HEALTH_FREQUENT = not Addon.ExpansionIsAtLeastMists,
  UNIT_LEVEL = true,
  UNIT_MAXHEALTH = true,
  UNIT_MAXPOWER = true,
  UNIT_NAME_UPDATE = true,
  UNIT_PORTRAIT_UPDATE = true,
  UNIT_POWER_FREQUENT = true, -- Added in 4.3.0 / 1.13.2
  UNIT_POWER_POINT_CHARGE = Addon.IS_MAINLINE, -- Shadowlands Patch 9.0.1 (2020-10-13): Added.
  UNIT_POWER_UPDATE = true,
  UNIT_QUEST_LOG_CHANGED = true,
  UNIT_SPELLCAST_CHANNEL_START = true,
  UNIT_SPELLCAST_CHANNEL_STOP = true,
  UNIT_SPELLCAST_CHANNEL_UPDATE = true,
  UNIT_SPELLCAST_DELAYED = true,
  UNIT_SPELLCAST_INTERRUPTED = Addon.ExpansionIsAtLeastMidnight, 
  --UNIT_SPELLCAST_FAILED = Addon.ExpansionIsAtLeastMidnight, 
  --UNIT_SPELLCAST_FAILED_QUIET = Addon.ExpansionIsAtLeastMidnight, 
  UNIT_SPELLCAST_EMPOWER_START = Addon.ExpansionIsAtLeastDF,
  UNIT_SPELLCAST_EMPOWER_STOP = Addon.ExpansionIsAtLeastDF,
  UNIT_SPELLCAST_EMPOWER_UPDATE = Addon.ExpansionIsAtLeastDF,
  UNIT_SPELLCAST_INTERRUPTIBLE = true,
  UNIT_SPELLCAST_NOT_INTERRUPTIBLE = true,
  UNIT_SPELLCAST_START = true,
  UNIT_SPELLCAST_STOP = true,
  UNIT_SPELLCAST_SENT = Addon.ExpansionIsAtLeastMidnight,
  UNIT_TARGET = true,
  UNIT_THREAT_LIST_UPDATE = true,
  UNIT_THREAT_SITUATION_UPDATE = true,
  UPDATE_BATTLEFIELD_SCORE = Addon.ExpansionIsAtLeastCata,
  UPDATE_MOUSEOVER_UNIT = true,
  UPDATE_SHAPESHIFT_FORM = true,  
  UPDATE_UI_WIDGET = true, -- Added in 8.0.1 / 1.13.2
}

--local DebugUnknowEvents = {}

function Addon:ExpansionSupportsEvent(event, register_for_current_expansion)
  -- if WOW_EVENTS[event] == nil then DebugUnknowEvents[event] = true end
  return register_for_current_expansion ~= false and WOW_EVENTS[event]
end

function Addon:RegisterEvent(event_handler_frame, event, register_for_current_expansion)
  if Addon:ExpansionSupportsEvent(event, register_for_current_expansion) then 
    event_handler_frame:RegisterEvent(event)
  end
end

function Addon:RegisterUnitEvent(event_handler_frame, event, unitid, register_for_current_expansion)
  if Addon:ExpansionSupportsEvent(event, register_for_current_expansion) then 
    event_handler_frame:RegisterUnitEvent(event, unitid)
  end
end

function Addon:UnregisterEvent(event_handler_frame, event)
  -- Only need to check if event is known in the current expansion
  if WOW_EVENTS[event] then
    event_handler_frame:UnregisterEvent(event)
  end
end

function Addon:DebugCompatibility()
  local frame = CreateFrame("Frame")
  
  for event, is_supported in pairs(WOW_EVENTS) do
    local success, result = pcall(frame.RegisterEvent, frame, event)
    if not success then
      Addon.Logging.Debug("    ", event .. ": FAILED =>", (not WOW_EVENTS[event] and "CORRECT") or "ERROR")
    elseif not WOW_EVENTS[event] then
      Addon.Logging.Debug("    ", event .. ": OK => DISABLED")      
    end
  end

  if DebugUnknowEvents then
    Addon.Logging.Debug("    Failed Events")      
    for event, _ in pairs(DebugUnknowEvents) do
      Addon.Logging.Debug("      =>", event)      
    end
  end
end

---------------------------------------------------------------------------------------------------
-- Tooltip handling
---------------------------------------------------------------------------------------------------

-- C_TooltipInfo.GetUnit was added in 10.0.2
if Addon.ExpansionIsAtLeastDF then
  Addon.C_TooltipInfo_GetUnit_NPCRole = C_TooltipInfo.GetUnit
  Addon.C_TooltipInfo_GetUnit_Quest = C_TooltipInfo.GetUnit
else
  local ScannerName = "ThreatPlates_Tooltip_Subtext"
  local TooltipScanner = CreateFrame( "GameTooltip", ScannerName , nil, "GameTooltipTemplate" ) -- Tooltip name cannot be nil
  TooltipScanner:SetOwner( WorldFrame, "ANCHOR_NONE" )

  local TooltipScannerData = {
    lines = {
      [1] = {},
      [2] = {},
      [3] = {},
      [4] = {},
      [5] = {},
    }
  }

  local function CreateLineData(line, with_color)
    local line_id = ScannerName .. "TextLeft" .. tostring(line)

    TooltipScannerData.lines[line].leftText = _G[line_id]:GetText()
    if with_color then
      TooltipScannerData.lines[line].leftColor = RGB_P(_G[line_id]:GetTextColor())
    end
  end

  -- Compatibility functions for tooltips in WoW Classic
  Addon.C_TooltipInfo_GetUnit_NPCRole = function(unitid)
    TooltipScanner:ClearLines()
		TooltipScanner:SetUnit(unitid)

    CreateLineData(1) 
    CreateLineData(2)
    CreateLineData(3)
    
    return TooltipScannerData
  end

  Addon.C_TooltipInfo_GetUnit_Quest = function(unitid)
    TooltipScanner:ClearLines()
		TooltipScanner:SetUnit(unitid)

    CreateLineData(3, true)
    CreateLineData(4, true)
    CreateLineData(5, true)
    
    return TooltipScannerData
  end
end

-- Quest widget is not available in Classic (Vanilla, TBC, Wrath)
if not Addon.ExpansionIsAtLeastMists then
  Addon.ShowQuestUnit = function(...) return false end
end

---------------------------------------------------------------------------------------------------
-- Midnight
---------------------------------------------------------------------------------------------------

Addon.IsSecretValue = _G.issecretvalue or function() return false end

-- Safe wrapper for UnitIsUnit: returns false instead of a secret value when the result is restricted.
-- Use this instead of the raw UnitIsUnit() call wherever the result is used in a boolean context.
if Addon.ExpansionIsAtLeastMidnight then
  function Addon.UnitIsUnit(unit1, unit2)
    local result = UnitIsUnit(unit1, unit2)
    return not Addon.IsSecretValue(result) and result
  end
else
  Addon.UnitIsUnit = UnitIsUnit
end

function Addon.EvaluateColorValueFromBoolean(boolean, color_if_true, color_if_false)
  local r = EvaluateColorValueFromBoolean(boolean, color_if_true.r, color_if_false.r)
  local g = EvaluateColorValueFromBoolean(boolean, color_if_true.g, color_if_false.g)
  local b = EvaluateColorValueFromBoolean(boolean, color_if_true.b, color_if_false.b)
  local a = EvaluateColorValueFromBoolean(boolean, color_if_true.a, color_if_false.a)
  return CreateColor(r, g, b, a)
end

---------------------------------------------------------------------------------------------------
-- Deprecated Blizzard API compatibility wrappers
---------------------------------------------------------------------------------------------------
-- These old globals are being replaced by namespaced C_* APIs, but the C_* replacements are not yet
-- available on all currently supported clients (e.g. C_CombatLog/C_PvP are missing on Classic Era/
-- Anniversary as of this writing). Fall back to the old global if the new API is not present.

-- IsSpellKnown/IsPlayerSpell -> C_SpellBook: confirmed available on all currently supported clients,
-- including Classic Era.
if C_SpellBook then
  local IsSpellInSpellBook = C_SpellBook.IsSpellInSpellBook
  local IsSpellKnown = C_SpellBook.IsSpellKnown
  -- Enum.SpellBookSpellBank ships together with C_SpellBook, so it is guaranteed to exist whenever C_SpellBook does.
  local SPELLBOOK_BANK_PET = Enum.SpellBookSpellBank.Pet
  local SPELLBOOK_BANK_PLAYER = Enum.SpellBookSpellBank.Player

  function Addon.IsSpellKnown(spellID, isPet)
    return IsSpellInSpellBook(spellID, isPet and SPELLBOOK_BANK_PET or SPELLBOOK_BANK_PLAYER, false)
  end

  function Addon.IsPlayerSpell(spellID)
    return IsSpellKnown(spellID, SPELLBOOK_BANK_PLAYER)
  end
else
  Addon.IsSpellKnown = IsSpellKnown
  Addon.IsPlayerSpell = IsPlayerSpell
end

-- CombatLogGetCurrentEventInfo -> C_CombatLog.GetCurrentEventInfo: confirmed missing on Classic Era/Anniversary.
Addon.CombatLogGetCurrentEventInfo = (C_CombatLog and C_CombatLog.GetCurrentEventInfo) or CombatLogGetCurrentEventInfo

-- GetBattlefieldScore -> C_PvP.GetScoreInfo: confirmed missing on all Classic clients so far. Only name and
-- talentSpec are used anywhere in this addon, so the wrapper returns just those two values instead of the
-- full legacy 17-value tuple.
if C_PvP and C_PvP.GetScoreInfo then
  local GetScoreInfo = C_PvP.GetScoreInfo

  function Addon.GetBattlefieldScore(playerIndex)
    local scoreInfo = GetScoreInfo(playerIndex)
    return scoreInfo and scoreInfo.name, scoreInfo and scoreInfo.talentSpec
  end
else
  local GetBattlefieldScore = GetBattlefieldScore

  function Addon.GetBattlefieldScore(playerIndex)
    local name, _, _, _, _, _, _, _, _, _, _, _, _, _, _, talentSpec = GetBattlefieldScore(playerIndex)
    return name, talentSpec
  end
end