--- Provides uitility functions relating to the Blizzard API.
--
local APIUtils = {}
local AddOnName, nsVars = ...
local ss = nsVars.SS

local try = ss.Utils.try
local AuraUtil = AuraUtil
local UnitBuff, UnitDebuff = UnitBuff, UnitDebuff
local type = type

local function UnitBuffIndex(unit, name)
  if type(name) == "number" then
    return name
  elseif unit == "player" then
    -- Return the cached index.
    return ss.playerBuffs[name]
  end
  
  -- 40 is the maximum amount of possible auras.
  for i = 1, 40 do
    if UnitBuff(unit, i) == name then
      -- Return the aura's index.
      return i
    end
  end
end

local function UnitDebuffIndex(unit, name, filter)
  if type(name) == "number" then
    return name
  end
  
  -- 40 is the maximum amount of possible auras.
  for i = 1, 40 do
    if UnitDebuff(unit, i, filter) == name then
      -- Return the aura's index.
      return i
    end
  end
end

--- Provides a string representation for a shapeshift id.
-- @param id The shapeshift id.
-- @return The shapeshift name.
--
function APIUtils.shapeshiftToString(id)
  local forms = {
    [0]  = "default",
    [1]  = "cat",
    [2]  = "tree of life",
    [3]  = "travel",
    [4]  = "aquatic",
    [5]  = "bear",
    [27] = "flight",
    [31] = "moonkin",
  };
  
  return forms[id] or "default"
end

--- Retrieves the text value of a UIDropDownMenu.
-- @param menu The UIDropDownMenu object.
-- @return The text value.
-- @see UIDropDownMenu_SetText().
--
function APIUtils.UIDropDownMenu_GetText(menu)
  if type(menu) == 'table' and type(menu.Text) == 'table' and type(menu.Text.GetText) == 'function' then
    return menu.Text:GetText()
  else
    ss.Utils.throw(ss.Utils.Errors.ErrorInvalidArgs, "lua", "UIDropDownMenu_GetText",
      {"menu", "UIDropDownMenu", menu,}
    )
  end
end

--- Calls the API's UnitBuff function with try,
-- since patch 8.0 (Battle for Azeroth),
-- this function no longer accepts a string identifier.
-- @param ... The params that would normally be given.
-- @return The result of UnitBuff(), or an empty table if an error is raised.
-- @see https://us.battle.net/forums/en/wow/topic/20762318007
--
function APIUtils.UnitBuff(...)
  local args = {...}
  
  if AuraUtil and AuraUtil.FindAuraByName then
    return AuraUtil.FindAuraByName(args[2], args[1])
  end
  
  args[2] = UnitBuffIndex(args[1], args[2])
  args._func = UnitBuff

  args._catch = function()
    return nil
  end

  return try(args)
end

--- Calls the API's UnitDebuff function with try,
-- since patch 8.0 (Battle for Azeroth),
-- this function no longer accepts a string identifier.
-- @param ... The params that would normally be given.
-- @return The result of UnitDebuff(), or an empty table if an error is raised.
-- @see https://us.battle.net/forums/en/wow/topic/20762318007
--
function APIUtils.UnitDebuff(...)
  local args = {...}
  
  if AuraUtil and AuraUtil.FindAuraByName then
    return AuraUtil.FindAuraByName(args[2], args[1], args[3])
  end
  
  args[2] = UnitDebuffIndex(args[1], args[2], args[3])
  args._func = UnitDebuff
  
  args._catch = function()
    return nil
  end

  return try(args)
end

local auras, auraName = {}, nil

function APIUtils.GetPlayerBuffs()
  auras, auraName = {}, nil
  
  -- 40 is the maximum amount of possible auras.
  for i = 1, 40 do
    -- Possible memory leak?
    auraName = UnitBuff("player", i)
    
    if auraName then
      -- Store the aura index.
      auras[auraName] = i
    end
  end
  
  return auras
end

ss.Utils.addModule("APIUtils", APIUtils)
