--- Sphere Micro Sphere Data Framework
--
local MicroSphereData = {}
local AddOnName, nsVars = ...
local ss = nsVars.SS

local strlower = strlower
local table, pairs, type = table, pairs, type

MicroSphereData.data = {
  ["deathknight"] = {
    ["blood"]  = ss.ClassResourceData.resourceInfo("runes"),
    ["frost"]  = ss.ClassResourceData.resourceInfo("runes"),
    ["unholy"] = ss.ClassResourceData.resourceInfo("runes"),
  },
  ["paladin"] = {
    ["retribution"] = ss.ClassResourceData.resourceInfo("holy power"),
  },
  ["mage"] = {
    ["arcane"] = ss.ClassResourceData.resourceInfo("arcane charges"),
  },
  ["druid"] = {
    ["balance"]     = { cat = ss.ClassResourceData.resourceInfo("combo points"), },
    ["feral"]       = { cat = ss.ClassResourceData.resourceInfo("combo points"), },
    ["guardian"]    = { cat = ss.ClassResourceData.resourceInfo("combo points"), },
    ["restoration"] = { cat = ss.ClassResourceData.resourceInfo("combo points"), },
  },
  ["monk"] = {
    ["windwalker"] = ss.ClassResourceData.resourceInfo("chi"),
  },
  ["rogue"] = {
    ["outlaw"]        = ss.ClassResourceData.resourceInfo("combo points"),
    ["assassination"] = ss.ClassResourceData.resourceInfo("combo points"),
    ["subtlety"]      = ss.ClassResourceData.resourceInfo("combo points"),
  },
  ["warlock"] = {
    ["affliction"]  = ss.ClassResourceData.resourceInfo("soul shards"),
    ["demonology"]  = ss.ClassResourceData.resourceInfo("soul shards"),
    ["destruction"] = ss.ClassResourceData.resourceInfo("soul shards"),
  },
}

local function checkStructure(res)
  if res.ssClass then
    res = {res, {} }
  end

  return res
end

local function init(resource)
  if type(resource) == "table" then
    for k,v in pairs(resource) do
      if v.name then
        ss[v.ssClass].init(v)
      else
        init(v)
      end
    end
  end
end

--- Provides a list of micro sphere groups for the config panel.
-- @param region The region to list.
-- @return the list of available groups.
--
function MicroSphereData.getGroupList(region)
  if ss.curClass == "druid" then
    return {
      Default = {
        group1 = "Group 1",
        group2 = "Group 2",
      },
      Bear = {
        group1 = "Group 1",
        group2 = "Group 2",
      },
      Cat = {
        group1 = region and "Group 1" or nil,
        group2 = "Group 2",
      },
      Moonkin = {
        group1 = "Group 1",
        group2 = "Group 2",
      },
    };
  elseif region then
    return {
      group1 = "Group 1",
      group2 = "Group 2",
    };
  else
    local usingClassResource1, usingClassResource2 = MicroSphereData.usingClassResource()
    return {
      group1 = not usingClassResource1 and "Group 1" or nil,
      group2 = not usingClassResource2 and "Group 2" or nil,
    };
  end
end

--- Loads micro resource settings from storage.
--
function MicroSphereData.load()
  -- Load custom resources.
  MicroSphereData.loadCustomResources("BuffData")
  MicroSphereData.loadCustomResources("DebuffData")
  MicroSphereData.loadCustomResources("SpellChargeData")
  
  -- Assign functions.
  ss.profile.microResources = ss.profile.microResources or (MicroSphereData.data[ss.curClass] or {})
  init(ss.profile.microResources)

  ss.profile.microResourcesSecondary = ss.profile.microResourcesSecondary or {}
  init(ss.profile.microResourcesSecondary)
end

--- Loads custom micro resources from storage.
-- @param type The type of resource to load.
--
function MicroSphereData.loadCustomResources(type)
  for k, v in pairs(ss.global.customResources[type][ss.curClass]) do
    if not ss[v.ssClass][ss.curClass][k] then
      ss[v.ssClass][ss.curClass][k] = ss.Utils.tcopy(v, true)
      ss[v.ssClass][ss.curClass][k].getMinMax = ss[v.ssClass].getFunction(v.getMinMax)
    end
  end
end

--- Updates stored micro sphere settings.
-- @param data The micro sphere data.
-- @param index The storage index.
-- @param index2 The storage index for group 2 values.
--
function MicroSphereData.set(data, index, index2)
  ss.profile.microResources                           = ss.profile.microResources or {}
  ss.profile.microResources[strlower(ss.curSpecName)] = ss.profile.microResources[strlower(ss.curSpecName)] or { {}, {} }

  if index2 then
    ss.profile.microResources[strlower(ss.curSpecName)][index2]        = ss.profile.microResources[strlower(ss.curSpecName)][index2] or { {}, {} }
    ss.profile.microResources[strlower(ss.curSpecName)][index2]        = checkStructure(ss.profile.microResources[strlower(ss.curSpecName)][index2])
    ss.profile.microResources[strlower(ss.curSpecName)][index2][index] = ss.Utils.tcopy(data or {}, true)
  else
    ss.profile.microResources[strlower(ss.curSpecName)]        = checkStructure(ss.profile.microResources[strlower(ss.curSpecName)])
    ss.profile.microResources[strlower(ss.curSpecName)][index] = ss.Utils.tcopy(data or {}, true)
  end

  ss.Layout:AddMicroSpheres()
end

--- Updates stored micro sphere settings (secondary).
-- @param data The micro sphere data.
-- @param index The storage index.
-- @param index2 The storage index for group 2 values.
--
function MicroSphereData.setSecondary(data, index, index2)
  ss.profile.microResourcesSecondary                           = ss.profile.microResourcesSecondary or {}
  ss.profile.microResourcesSecondary[strlower(ss.curSpecName)] = ss.profile.microResourcesSecondary[strlower(ss.curSpecName)] or { {}, {} }

  if index2 then
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index2]        = ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index2] or { {}, {} }
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index2]        = checkStructure(ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index2])
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index2][index] = ss.Utils.tcopy(data or {}, true)
  else
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)]        = checkStructure(ss.profile.microResourcesSecondary[strlower(ss.curSpecName)])
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index] = ss.Utils.tcopy(data or {}, true)
  end

  ss.Layout:AddMicroSpheres("mainResource")
end

--- Checks for a class resource the requires a micro sphere region.
-- @return Flag for class resource usage.
--
function MicroSphereData.usingClassResource()
  local resource = ss.profile.microResources

  if resource and resource[strlower(ss.curSpecName)] then
    resource = resource[strlower(ss.curSpecName)]
    if resource[1] and type(resource[1]) == "table" then
      return (resource[1].ssClass and resource[1].ssClass == "ClassResourceData"), (resource[2] and resource[2].ssClass and resource[2].ssClass == "ClassResourceData")
    elseif resource.ssClass and resource.ssClass == "ClassResourceData" then
      return true
    end
  end

  return false
end

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