local AddOnName, nsVars = ...
local ss = nsVars.SS

local setmetatable = setmetatable
local strlower, select, UnitBuff, UnitStagger, UnitHealthMax = strlower, select, UnitBuff, UnitStagger, UnitHealthMax
local string, GetTime = string, GetTime

local timeBuffer = 0.05

local getMinMax = function(buff)
  local duration, expires = select(6, UnitBuff("player", buff))
  return buff, (duration and 1 or 0), 1, (duration or 1), (expires or 1)
end

local getIncantersFlowMinMax = function(buff)
  local cur, max, prog = select(3, UnitIncantersFlow())
  return buff, (cur and 1 or 0), 1, (max or 1), (prog and (GetTime() + (max * prog) + timeBuffer) or 1)
end

-- Bloodtalons
local getBloodtalonsMinMax = function(spell)
  local stacks, _, duration, expires = select(4, UnitBuff("player", "Bloodtalons"))

  if spell == "Bloodtalons2" and stacks then
    duration = (stacks == 2) and duration or nil
    expires = (stacks == 2) and expires or nil
  elseif stacks then
    duration = (stacks >= 1) and duration or nil
    expires = (stacks >= 1) and expires or nil
  end

  return "bloodtalons", (duration and 1 or 0), 1, (duration or 1), (expires or 1)
end

-- Focused Rage
local getFocusedRageMinMax = function(spell)
  local stacks, _, duration, expires = select(4, UnitBuff("player", "Focused Rage"))

  if spell == "Focused Rage3" and stacks then
    duration = (stacks == 3) and duration or nil
    expires = (stacks == 3) and expires or nil
  elseif spell == "Focused Rage2" and stacks then
    duration = (stacks >= 2) and duration or nil
    expires = (stacks >= 2) and expires or nil
  elseif stacks then
    duration = (stacks >= 1) and duration or nil
    expires = (stacks >= 1) and expires or nil
  end

  return "focusedrage", (duration and 1 or 0), 1, (duration or 1), (expires or 1)
end

-- Stagger
local getStaggerMinMax = function()
  local min, max = UnitStagger("player"), UnitHealthMax("player")
  return "Stagger", min, max
end

-- Global Cooldown
local getGCD = function(spell)
  local duration = ss.gcdWatch.max and ss.gcdWatch.max or 1
  local expires = (ss.gcdWatch.start and ss.gcdWatch.max) and (ss.gcdWatch.start + ss.gcdWatch.max) or 1

  if ss.gcdWatch.start and GetTime() >= expires - timeBuffer then
    ss.gcdWatch.start = nil
  end

  return spell, (duration ~= expires) and 1 or 0, 1, duration, expires
end

local mtBuffData = {
  ["demonhunter"] = {
    ["momentum"]       = { "Momentum", { r=0.824, g=0.526, b=0.157, a=1 }, getMinMax = getMinMax, name = "Momentum", },
    ["empowerwards"]   = { "Empower Wards", { r=0.471, g=0.784, b=0.294, a=1 }, getMinMax = getMinMax, name = "Empower Wards", },
    ["demonspikes"]    = { "Demon Spikes", { r=0.784, g=0.725, b=0.000, a=1 }, getMinMax = getMinMax, name = "Demon Spikes", },
    ["soulbarrier"]    = { "Soul Barrier", { r=0.392, g=0.529, b=0.137, a=1 }, getMinMax = getMinMax, name = "Soul Barrier", },
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["druid"] = {
    ["guardianofelune"]      = { "Guardian of Elune", { r=0.451, g=0.039, b=0.725, a=1 }, getMinMax = getMinMax, name = "Guardian of Elune",},
    ["ironfur"]              = { "Ironfur", { r=0.529, g=0.686, b=1.000, a=1 }, getMinMax = getMinMax, name = "Ironfur", },
    ["markofursol"]          = { "Mark of Ursol", { r=0.490, g=0.196, b=1.000, a=1 }, getMinMax = getMinMax, name = "Mark of Ursol", },
    ["frenziedregeneration"] = { "Frenzied Regeneration", { r=0.588, g=0.353, b=0.157, a=1 }, getMinMax = getMinMax, name = "Frenzied Regeneration", },
    ["bloodtalons"]          = { "Bloodtalons", { r=0.706, g=0.098, b=0.000, a=1 }, getMinMax = getBloodtalonsMinMax, name = "Bloodtalons", },
    ["bloodtalons2"]         = { "Bloodtalons2", { r=0.706, g=0.098, b=0.000, a=1 }, getMinMax = getBloodtalonsMinMax, name = "Bloodtalons", },
    ["globalcooldown"]       = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["mage"] = {
    ["kaelthassultimateability"] = { "Kael'thas's Ultimate Ability", { r=0.647, g=0.294, b=0.765, a=1 }, getMinMax = getMinMax, name = "Kael'thas's Ultimate Ability",},
    ["incantersflow"]            = { "Incanter's Flow", { r=0.824, g=0.157, b=0.196, a=1 }, getMinMax = getIncantersFlowMinMax, name = "Incanter's Flow",},
    ["globalcooldown"]           = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["monk"] = {
    ["stagger"] = { "stagger", ss.ClassResourceData.resourceColor("chi"), getMinMax = getStaggerMinMax, name = "Stagger", },
    ["hitcombo"] = { "Hit Combo", { r=1.000, g=0.686, b=0.157, a=1 }, getMinMax = getMinMax, name = "Hit Combo", },
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["shaman"] = {
    ["boulderfist"]                  = { "Boulderfist", { r=0.588, g=0.333, b=0.118, a=1 }, getMinMax = getMinMax, name = "Boulderfist",},
    ["flametongue"]                  = { "Flametongue", { r=1.000, g=0.725, b=0.451, a=1 }, getMinMax = getMinMax, name = "Flametongue",},
    ["crashlightning"]               = { "Crash Lightning", { r=0.098, g=0.588, b=1.000, a=1 }, getMinMax = getMinMax, name = "Crash Lightning",},
    ["doomwinds"]                    = { "Doom Winds", { r=0.471, g=0.882, b=0.353, a=1 }, getMinMax = getMinMax, name = "Doom Winds",},
    ["windsong"]                     = { "Windsong", { r=0.510, g=0.784, b=0.824, a=1 }, getMinMax = getMinMax, name = "Windsong",},
    ["landslide"]                    = { "Landslide", { r=0.627, g=0.176, b=0.176, a=1 }, getMinMax = getMinMax, name = "Landslide",},
    ["elementalblastcriticalstrike"] = { "Elemental Blast: Critical Strike", { r=0.804, g=0.745, b=1.000, a=1 }, getMinMax = getMinMax, name = "Elemental Blast: Critical Strike",},
    ["elementalblasthaste"]          = { "Elemental Blast: Haste", { r=0.647, g=0.333, b=0.686, a=1 }, getMinMax = getMinMax, name = "Elemental Blast: Haste",},
    ["elementalblastmastery"]        = { "Elemental Blast: Mastery", { r=1.000, g=0.706, b=0.000, a=1 }, getMinMax = getMinMax, name = "Elemental Blast: Mastery",},
    ["shockofthetwistingnether"]     = { "Shock of the Twisting Nether", { r=0.608, g=1.000, b=0.529, a=1 }, getMinMax = getMinMax, name = "Shock of the Twisting Nether",},
    ["chillofthetwistingnether"]     = { "Chill of the Twisting Nether", { r=0.608, g=0.882, b=1.000, a=1 }, getMinMax = getMinMax, name = "Chill of the Twisting Nether",},
    ["fireofthetwistingnether"]      = { "Fire of the Twisting Nether", { r=0.843, g=0.176, b=0.000, a=1 }, getMinMax = getMinMax, name = "Fire of the Twisting Nether",},
    ["globalcooldown"]               = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["warrior"] = {
    ["enrage"]              = { "Enrage", { r=1.000, g=0.215, b=0.000, a=1 }, getMinMax = getMinMax, name = "Enrage",},
    ["enragedregeneration"] = { "Enraged Regeneration", { r=0.804, g=0.255, b=0.137, a=1 }, getMinMax = getMinMax, name = "Enraged Regeneration",},
    ["meatcleaver"]         = { "Meat Cleaver", { r=0.314, g=0.608, b=0.765, a=1 }, getMinMax = getMinMax, name = "Meat Cleaver",},
    ["shieldblock"]         = { "Shield Block", { r=0.294, g=0.549, b=0.784, a=1 }, getMinMax = getMinMax, name = "Shield Block",},
    ["ignorepain"]          = { "Ignore Pain", { r=1.000, g=0.647, b=0.020, a=1 }, getMinMax = getMinMax, name = "Ignore Pain",},
    ["frothingberserker"]   = { "Frothing Berserker", { r=1.000, g=0.549, b=0.000, a=1 }, getMinMax = getMinMax, name = "Frothing Berserker",},
    ["focusedrage"]         = { "Focused Rage", { r=0.843, g=0.196, b=0.078, a=1 }, getMinMax = getFocusedRageMinMax, name = "Focused Rage",},
    ["focusedrage2"]        = { "Focused Rage2", { r=0.843, g=0.196, b=0.078, a=1 }, getMinMax = getFocusedRageMinMax, name = "Focused Rage",},
    ["focusedrage3"]        = { "Focused Rage3", { r=0.843, g=0.196, b=0.078, a=1 }, getMinMax = getFocusedRageMinMax, name = "Focused Rage",},
    ["globalcooldown"]      = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["deathknight"] = {
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["hunter"] = {
    ["mongoosefury"] = { "Mongoose Fury", { r=0.804, g=0.157, b=0.098, a=1 }, getMinMax = getMinMax, name = "Mongoose Fury",},
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["paladin"] = {
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["priest"] = {
    ["norgannonsforesight"] = { "Norgannon's Foresight", { r=0.000, g=0.922, b=1.000, a=1 }, getMinMax = getMinMax, name = "Norgannon's Foresight", },
    ["globalcooldown"]      = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["rogue"] = {
    ["truebearing"]         = { "True Bearing", { r=1.000, g=0.824, b=0.373, a=1 }, getMinMax = getMinMax, name = "True Bearing",},
    ["sharkinfestedwaters"] = { "Shark Infested Waters", { r=0.333, g=0.550, b=0.725, a=1 }, getMinMax = getMinMax, name = "Shark Infested Waters",},
    ["broadsides"]          = { "Broadsides", { r=1.000, g=0.627, b=0.059, a=1 }, getMinMax = getMinMax, name = "Broadsides",},
    ["grandmelee"]          = { "Grand Melee", { r=0.725, g=0.333, b=0.176, a=1 }, getMinMax = getMinMax, name = "Grand Melee",},
    ["jollyroger"]          = { "Jolly Roger", { r=0.725, g=0.686, b=0.686, a=1 }, getMinMax = getMinMax, name = "Jolly Roger",},
    ["buriedtreasure"]      = { "Buried Treasure", { r=1.000, g=0.843, b=0.000, a=1 }, getMinMax = getMinMax, name = "Buried Treasure",},
    ["envenom"]             = { "Envenom", { r=0.431, g=1.000, b=0.255, a=1 }, getMinMax = getMinMax, name = "Envenom",},
    ["globalcooldown"]      = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
  ["warlock"] = {
    ["globalcooldown"] = { "Global Cooldown", { r=0.482, g=1.000, b=0.827, a=1 }, getMinMax = getGCD, name = "Global Cooldown",},
  },
};

mtBuffData.hasBuffs = function()
  return mtBuffData[strlower(ss.curClass)] and true or nil
end

mtBuffData.get = function(class, buff)
  local res = mtBuffData[strlower(class)][strlower(buff)]
  res.ssClass = "BuffData"
  return res
end

mtBuffData.init = function(resource)
  local index = strlower(string.gsub(resource[1], " ", ""))
  index = strlower(string.gsub(index, "'", ""))
  index = strlower(string.gsub(index, ":", ""))
  resource.getMinMax = mtBuffData[strlower(ss.curClass)][index].getMinMax
end

ss["BuffData"] = setmetatable({}, { __index = mtBuffData });
