-----------------------------------------------------
-- Layout Container for SeamoreSpheres unit frames --
-----------------------------------------------------
local addon, nsVars = ...
local ss = nsVars.SS

local setmetatable = setmetatable
local CreateFrame, UIParent, pairs = CreateFrame, UIParent, pairs
local strlower, select, table = strlower, select, table
local GetShapeshiftFormID = GetShapeshiftFormID

local mtLayout = {
  spheres = {},
  artwork = {},
};

function mtLayout:AddArtwork(texture,sphere,name,offsetX,offsetY,height,width)
  local art = CreateFrame("Frame",ss._f..name,sphere)
  art:SetPoint      ("CENTER",offsetX,offsetY)
  art:SetHeight     (height)
  art:SetWidth      (width)
  art:SetFrameStrata("MEDIUM")
  art:SetFrameLevel (9)
  art.texture = art:CreateTexture(nil,"OVERLAY")
  art.texture:SetTexture  (texture)
  art.texture:SetAllPoints(art)
  return art
end

function mtLayout:AddMicroSpheres(sphere)
  sphere = sphere or "health"
  self.spheres[sphere]:toggleResourceGroup         (false)
  self.spheres[sphere]:toggleSecondaryResourceGroup(false)
  local microResource = (sphere == "mainResource") and ss.profile.microResourcesSecondary or ss.profile.microResources

  if ss.curClass == "druid" then
    if microResource and microResource[strlower(ss.curSpecName)] then
      for k,v in pairs(microResource[strlower(ss.curSpecName)]) do
        if ss.curShapeshift and (k == ss.curShapeshift) then
          self.spheres[sphere]:AddResourceGroup(v, (sphere == "mainResource") and "secondary" or nil)

          if not v.getMinMax and not v.buffGroup then
            if v[1].buffGroup then
              self.spheres[sphere]:toggleResourceGroup(v[1])
            elseif v[1].getMinMax then
              self.spheres[sphere]:toggleResourceGroup(select(2, v[1].getMinMax(v[1][1])))
            else
              self.spheres[sphere]:toggleResourceGroup(false)
            end

            if v[2].buffGroup then
              self.spheres[sphere]:toggleSecondaryResourceGroup(v[2])
            elseif v[2].getMinMax then
              self.spheres[sphere]:toggleSecondaryResourceGroup(select(2, v[2].getMinMax(v[2][1])))
            else
              self.spheres[sphere]:toggleSecondaryResourceGroup(false)
            end
          elseif v.buffGroup then
            -- depricated
            self.spheres[sphere]:toggleResourceGroup         (v)
            self.spheres[sphere]:toggleSecondaryResourceGroup(false)
          elseif v.getMinMax then
            -- depricated
            self.spheres[sphere]:toggleResourceGroup         (select(2, v.getMinMax(v[1])))
            self.spheres[sphere]:toggleSecondaryResourceGroup(false)
          end

          break
        end
      end
    end
  else
    if microResource then
      for k,v in pairs(microResource) do
        if k == strlower(ss.curSpecName) then
          self.spheres[sphere]:AddResourceGroup(v, (sphere == "mainResource") and "secondary" or nil)
          break
        end
      end
    end

    self:ToggleMicroSpheres(sphere)
  end
end

function mtLayout:CheckConfig()
  if ss.Config:IsVisible() then
    ss:ToggleConfig()
  end
end

function mtLayout:EndCombat()
  if self.inCombat then
    if ss.global.track.combat then
      for k,v in pairs(self.spheres) do
        local configName = v:Get("configName")

        if ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec] and v:Get("prevMode") then
          if (configName ~= "pet") and (configName == "health" or ss.curClass ~= "druid") then
            v:setMode(ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec][ss.profile.modeInfo[configName].mode]);
          end
        end
      end
    end

    self.inCombat = nil
  end
end

function mtLayout:InCombat()
  return self.inCombat
end

function mtLayout:Initialize()
  ss:InitializeConfigPanel()

  self.spheres.health = ss.Sphere:New()
  self.spheres.health:initialize(ss.db.health, UIParent, "active")
  self:AddMicroSpheres()

  ss.Config.previewSphereList.health  = {"Health", "Health"}
  ss.Config.previewSphereList.vehicle = {"Vehicle", "Vehicle"}

  -- Create main resource sphere
  self.spheres.mainResource = ss.Sphere:New()
  self.spheres.mainResource:initialize(ss.db.mainResource,UIParent,"active")
  self:AddMicroSpheres("mainResource")
  ss.Config.previewSphereList.mainResource    = {"Main Resource", "MainResource"}
  ss.Config.previewSphereList.vehicleResource = {"Vehicle Resource", "VehicleResource"}

  self:TrackAdditionalResource(ss.db.track["additionalResource"] and ss.ClassResources.hasSecondaryResource())
  self:ShowArtwork            (ss.global.show.artwork)

  if ss.curClass == "druid" then
    self:Shapeshift(ss.shapeshiftToString(GetShapeshiftFormID() or 0))
  elseif (ss.curClass == "hunter") or (ss.curClass == "warlock") or (ss.curClass == "mage") then
    self:TrackPet(true)
    self:TrackPet(false)
  end
end

function mtLayout:OnPlayerEnteredVehicle()
  if not self.inVehicle then
    self.spheres["health"]      :setResource(ss.db["vehicle"])
    self.spheres["mainResource"]:setResource(ss.db["vehicleResource"])

    if self.inCombat then
      self.spheres["health"]:setMode(ss.db["vehicle"].modes[ss.profile.modeInfo["vehicle"].modeSpec]["combat"]);

      if ss.curClass ~= "druid" then
        self.spheres["mainResource"]:setMode(ss.db["vehicleResource"].modes[ss.profile.modeInfo["vehicleResource"].modeSpec]["combat"]);
      end
    end

    self.inVehicle = true
  end
end

function mtLayout:OnPlayerExitedVehicle()
  if self.inVehicle then
    self.spheres["health"]      :setResource(ss.db["health"])
    self.spheres["mainResource"]:setResource(ss.db["mainResource"])

    if self.inCombat then
      self.spheres["health"]:setMode(ss.db["health"].modes[ss.profile.modeInfo["health"].modeSpec]["combat"]);

      if ss.curClass ~= "druid" then
        self.spheres["mainResource"]:setMode(ss.db["mainResource"].modes[ss.profile.modeInfo["mainResource"].modeSpec]["combat"]);
      end
    end

    self.inVehicle = nil
  end
end

function mtLayout:OnSpecializationChanged()
  self:Refresh()
  self:AddMicroSpheres()
  self:AddMicroSpheres("mainResource")
end

function mtLayout:OnUnitMaxPowerChanged()
  self:ToggleMicroSpheres()
  self:ToggleMicroSpheres("mainResource")
  self:AddMicroSpheres()
  self:AddMicroSpheres("mainResource")
end

function mtLayout:ShowArtwork(show)
  if show then
    self.healthArtwork       = self.healthArtwork       or self:AddArtwork(ss.private.textures.healthArtwork,       self.spheres.health      :Get("sphere"), "HealthArtwork",      -90, 5, 160, 160)
    self.mainResourceArtwork = self.mainResourceArtwork or self:AddArtwork(ss.private.textures.mainResourceArtwork, self.spheres.mainResource:Get("sphere"), "MainResourceArtwork",70,  5, 160, 160)

    self.healthArtwork      :Show()
    self.mainResourceArtwork:Show()
  else
    if self.healthArtwork       then self.healthArtwork      :Hide() end
    if self.mainResourceArtwork then self.mainResourceArtwork:Hide() end
  end
end

function mtLayout:TrackAdditionalResource(track)
  if track and not self.spheres.additionalResource then
    self.spheres.additionalResource = ss.Sphere:New()
    self.spheres.additionalResource:initialize(ss.db.additionalResource,UIParent,"active")
    ss.Config.previewSphereList.additionalResource = {"Additional Resource", "AdditionalResource"}
  elseif track and self.spheres.additionalResource then
    self.spheres.additionalResource:setResource(ss.db.additionalResource)
    self.spheres.additionalResource:show       (true)
    ss.Config.previewSphereList.additionalResource = {"Additional Resource", "AdditionalResource"}
  elseif not track and self.spheres.additionalResource then
    self.spheres.additionalResource:show(false)
    ss.Config.previewSphereList.additionalResource = nil
  end
end

function mtLayout:ToggleMicroSpheres(sphere)
  if ss.curClass ~= "druid" then
    sphere              = sphere or "health"
    local microResource = (sphere == "mainResource") and ss.profile.microResourcesSecondary or ss.profile.microResources

    if microResource and microResource[strlower(ss.curSpecName)] then
      if (not microResource[strlower(ss.curSpecName)].getMinMax) and (not microResource[strlower(ss.curSpecName)].buffGroup) then
        if microResource[strlower(ss.curSpecName)][1].buffGroup then
          self.spheres[sphere]:toggleResourceGroup(microResource[strlower(ss.curSpecName)][1])
        elseif (table.getn(microResource[strlower(ss.curSpecName)][1]) > 0) then
          self.spheres[sphere]:toggleResourceGroup(select(2, microResource[strlower(ss.curSpecName)][1].getMinMax(microResource[strlower(ss.curSpecName)][1][1])))
        else
          self.spheres[sphere]:toggleResourceGroup(false)
        end

        if microResource[strlower(ss.curSpecName)][2] and (microResource[strlower(ss.curSpecName)][2].buffGroup) then
          self.spheres[sphere]:toggleSecondaryResourceGroup(microResource[strlower(ss.curSpecName)][2])
        elseif microResource[strlower(ss.curSpecName)][2] and (table.getn(microResource[strlower(ss.curSpecName)][2]) > 0) then
          self.spheres[sphere]:toggleSecondaryResourceGroup(select(2, microResource[strlower(ss.curSpecName)][2].getMinMax(microResource[strlower(ss.curSpecName)][2][1])))
        else
          self.spheres[sphere]:toggleSecondaryResourceGroup(false)
        end
      elseif microResource[strlower(ss.curSpecName)].buffGroup then
        -- depricated
        self.spheres[sphere]:toggleResourceGroup         (true)
        self.spheres[sphere]:toggleSecondaryResourceGroup(false)
      else
        -- depricated
        self.spheres[sphere]:toggleResourceGroup         (select(2, microResource[strlower(ss.curSpecName)].getMinMax(microResource[strlower(ss.curSpecName)][1])))
        self.spheres[sphere]:toggleSecondaryResourceGroup(false)
      end
    end
  end
end

function mtLayout:TrackPet(track)
  if track and not self.spheres.pet then
    self.spheres.pet = ss.Sphere:New()
    self.spheres.pet:initialize(ss.db.pet,UIParent,"active")

    ss.Config.previewSphereList     = ss.Config.previewSphereList or {}
    ss.Config.previewSphereList.pet = {"Pet", "Pet"}
  elseif track and self.spheres.pet then
    self.spheres.pet:setResource(ss.db.pet)
    self.spheres.pet:show       (true)

    ss.Config.previewSphereList.pet = {"Pet", "Pet"}
  elseif not track and self.spheres.pet then
    self.spheres.pet:show(false)
    ss.Config.previewSphereList.pet = nil
  end
end

function mtLayout:UpdateMicroSphereTextures(texture, sphere)
  sphere = sphere or "health"
  self.spheres[sphere]:updateResourceGroupTextures(1, texture)
  self.spheres[sphere]:updateResourceGroupTextures(2, texture)
end

function mtLayout:UpdateScale()
  for k,v in pairs(self.spheres) do
    v:UpdateScale()
  end
end

function mtLayout:Refresh()
  ss.profile.modeInfo.mainResource.modeSpec       = ss.db.mainResource.modes[ss.curSpec]       and ss.curSpec or "defaultSpec"
  ss.profile.modeInfo.additionalResource.modeSpec = ss.db.additionalResource.modes[ss.curSpec] and ss.curSpec or "defaultSpec"
  ss.profile.modeInfo.health.modeSpec             = ss.db.health.modes[ss.curSpec]             and ss.curSpec or "defaultSpec"

  self.spheres.health      :setResource(ss.db.health)
  self.spheres.mainResource:setResource(ss.db.mainResource)
  self:TrackAdditionalResource(ss.db.track["additionalResource"] and ss.ClassResources.hasSecondaryResource())

  if ss.ClassResources.hasSecondaryResource() then
    ss.Config.buttonFrame.UsePowerTrackerCheckButton:Show()
  else
    ss.Config.buttonFrame.UsePowerTrackerCheckButton:Hide()
  end

  self:ToggleMicroSpheres()
  self:ToggleMicroSpheres("mainResource")
end

function mtLayout:Shapeshift(shapeshift)
  if shapeshift ~= ss.curShapeshift then
    ss.curShapeshift = shapeshift

    for k,v in pairs(self.spheres) do
      if ss.db[k].modes[ss.profile.modeInfo[k].modeSpec] and ss.db[k].modes[ss.profile.modeInfo[k].modeSpec][shapeshift] then

        if k == "health" and self.inCombat then
          v:Set("prevMode", ss.db[k].modes[ss.profile.modeInfo[k].modeSpec][shapeshift])
          ss.profile.modeInfo[k].mode = shapeshift
        else
          v:setMode(ss.db[k].modes[ss.profile.modeInfo[k].modeSpec][shapeshift], shapeshift);
        end
      end
    end

    self:AddMicroSpheres()
    self:AddMicroSpheres("mainResource")
  end
end

function mtLayout:StartCombat()
  if not self.inCombat then
    self.inCombat = true

    if ss.global.track.combat then
      for k,v in pairs(self.spheres) do
        local configName = v:Get("configName")

        if ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec] and ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec]["combat"] then
          if (configName ~= "pet") and (configName == "health" or configName == "vehicle" or ss.curClass ~= "druid") then
            v:setMode(ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec]["combat"]);
          end
        end
      end
    end
  end
end

ss["Layout"] = setmetatable({}, { __index = mtLayout });
