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

local strlower, setmetatable = strlower, setmetatable
local pairs, type, next = pairs, type, next

-- TODO Remove all but class specializations using resources.
local mtMicroSphereData = {
  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"),
      ["brewmaster"] = { buffGroup = { ss.BuffData.get("monk", "stagger"), }, },
    },
    ["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"),
    },
  },
};

mtMicroSphereData.usingClassResource = function()
  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

mtMicroSphereData.getGroupList = function(region)
  if strlower(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 = mtMicroSphereData.usingClassResource()
    return {
      group1 = not usingClassResource1 and "Group 1" or nil,
      group2 = not usingClassResource2 and "Group 2" or nil,
    };
  end
end


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

  return res
end

mtMicroSphereData.set = function(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] = data or {}
  else
    ss.profile.microResources[strlower(ss.curSpecName)] = checkStructure(ss.profile.microResources[strlower(ss.curSpecName)])
    ss.profile.microResources[strlower(ss.curSpecName)][index] = data or {}
  end

  ss.Layout:AddMicroSpheres()
end

mtMicroSphereData.setSecondary = function(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] = data or {}
  else
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)] = checkStructure(ss.profile.microResourcesSecondary[strlower(ss.curSpecName)])
    ss.profile.microResourcesSecondary[strlower(ss.curSpecName)][index] = data or {}
  end

  ss.Layout:AddMicroSpheres("mainResource")
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

local fixDefaults = function()
  ss.profile.microResources.fillTextures = nil;

  if next(ss.profile.microResources) == nil then
    ss.profile.microResources = nil
  elseif mtMicroSphereData.data[strlower(ss.curClass)] and not ss.profile.microResourcesFixed then
    ss.profile.microResources = mtMicroSphereData.data[strlower(ss.curClass)]
    ss.profile.microResourcesFixed = true
  end
end

mtMicroSphereData.load = function()
  ss.profile.microResources = ss.profile.microResources or (mtMicroSphereData.data[strlower(ss.curClass)] or {})
  init(ss.profile.microResources)
  ss.profile.microResourcesSecondary = ss.profile.microResourcesSecondary or {}
  init(ss.profile.microResourcesSecondary)

  fixDefaults()
end

ss["MicroSphereData"] = setmetatable({}, { __index = mtMicroSphereData });
