----------------------------------------
-- Buff Information for Micro Spheres --
----------------------------------------
local AddOnName, nsVars = ...
local ss = nsVars.SS

local UnitDebuff, GetTime = UnitDebuff, GetTime
local string, tonumber, strlower, select = string, tonumber, strlower, select

--- Provides debuff information.
-- @param buff The debuff identifier.
-- @return The debuff information.
-- @see UnitDebuff().
--
local getMinMax = function(buff)
  local duration, expires = select(6, UnitDebuff("target", buff))
  return buff, (duration and 1 or 0), 1, (duration or 1), (expires or 1)
end

--- Provides corruption information.
-- @param buff The debuff identifier.
-- @return The debuff information.
-- @see UnitDebuff().
--
local getCorruption = function(buff)
  local duration, expires = select(6, UnitDebuff("target", buff))
  -- Values are 0 if corruption is permanent, return time + 1 if so.
  return buff, (duration and 1 or 0), 1, (duration or 1), (expires and (expires == 0 and (GetTime() + 1) or expires) or 1)
end

--- Provides stacking debuff information.
-- @param spell The debuff identifier.
-- @return The debuff information.
-- @see UnitDebuff().
--
local getStackingMinMax = function(spell)
  local buffName = string.gsub(spell, "%d", "")
  local index = strlower(string.gsub(spell, "[ :'%(%)%d]", ""))
  
  local stacks, _, duration, expires = select(4, UnitDebuff("target", buffName))
  
  if stacks then
    local buffStack = string.gsub(spell, "[^%d]", "")
    buffStack = (buffStack and buffStack ~= "") and tonumber(buffStack) or 1
    
    duration = (stacks >= buffStack) and duration or nil
    expires = (stacks >= buffStack) and expires or nil
  end
  
  return index, (duration and 1 or 0), 1, (duration or 1), (expires or 1)
end

-- TODO: Add vulnerable for marks hunter
local mtDebuffData = {
  demonhunter = {
    ["fierybrand"] = { "Fiery Brand", { r=181, g=233, b=18, a=1 }, getMinMax = getMinMax, name = "Fiery Brand", },
  },
  warlock = {
    ["corruption"] = { "Corruption", { r=152, g=24, b=32, a=1 }, getMinMax = getCorruption, name = "Corruption", },
    ["agony"]      = { "Agony",      { r=187, g=69, b=32, a=1 }, getMinMax = getMinMax, name = "Agony", },
  },
  warrior = {
    ["colossussmash"]          = { "Colossus Smash",           { r=220, g=150, b=25, a=1 },        getMinMax = getMinMax,         name = "Colossus Smash", },
    ["executionersprecision"]  = { "Executioner's Precision",  { r=0.843, g=0.196, b=0.078, a=1 }, getMinMax = getStackingMinMax, name = "Executioner's Precision", },
    ["executionersprecision2"] = { "Executioner's Precision2", { r=0.843, g=0.196, b=0.078, a=1 }, getMinMax = getStackingMinMax, name = "Executioner's Precision", },
  },
  deathknight = {
    ["virulentplague"]  = { "Virulent Plague",  { r=185, g=200, b=150, a=1 }, getMinMax = getMinMax,         name = "Virulent Plague", },
    ["festeringwound"]  = { "Festering Wound",  { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound2"] = { "Festering Wound2", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound3"] = { "Festering Wound3", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound4"] = { "Festering Wound4", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound5"] = { "Festering Wound5", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound6"] = { "Festering Wound6", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound7"] = { "Festering Wound7", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
    ["festeringwound8"] = { "Festering Wound8", { r=220, g=44, b=245, a=1 },  getMinMax = getStackingMinMax, name = "Festering Wound", },
  },
  druid = {},
  mage = {},
  monk = {},
  shaman = {},
  hunter = {},
  paladin = {},
  priest = {},
  rogue = {},
}

--- Provides resource details.
-- @param class The class identifier.
-- @param buff The buff identifier.
-- @return The resource data.
--
mtDebuffData.get = function(class, buff)
  local res = mtDebuffData[strlower(class)][strlower(buff)]
  res.ssClass = "DebuffData"
  return res
end

--- Returns a reference to the target function.
-- @param name The name of the function.
-- @return The function reference.
--
mtDebuffData.getFunction = function(name)
  if name == "getStackingMinMax" then
    return getStackingMinMax
  else
    return getMinMax
  end
end

--- Initializes a stored resource with actual values.
-- @param resource The resource to initialize.
--
mtDebuffData.init = function(resource)
  local index = strlower(string.gsub(resource[1], "[ :'%(%)]", ""))
  
  if mtDebuffData[ss.curClass][index] then
    -- update identifier, color and getMinMax functions.
    resource[1]        = mtDebuffData[ss.curClass][index][1]
    resource[2]        = mtDebuffData[ss.curClass][index][2]
    resource.getMinMax = mtDebuffData[ss.curClass][index].getMinMax
  else
    resource.getMinMax = function() return "",0,0,0,0 end
  end
end

ss.Utils.addModule("DebuffData", mtDebuffData)
