-----------------------------------------------------
-- 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",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: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()
  elseif self.healthArtwork or self.mainResourceArtwork then
    if self.healthArtwork then self.healthArtwork:Hide() end
    if self.mainResourceArtwork then self.mainResourceArtwork:Hide() 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: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:AddMicroSpheres(sphere)
  sphere = sphere or "health"
  self.spheres[sphere]:toggleResourceGroup(false)
  self.spheres[sphere]:toggleSecondaryResourceGroup(false)
  local microResource = (sphere == "mainResource") and ss.MicroSphereData.getSecondary() or ss.MicroSphereData.get()

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

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

            if v[ss.curShapeshift][2].buffGroup then
              self.spheres[sphere]:toggleSecondaryResourceGroup(v[ss.curShapeshift][2])
            elseif table.getn(v[ss.curShapeshift][2]) > 0 then
              self.spheres[sphere]:toggleResourceGroup(select(2, v[ss.curShapeshift][2].getMinMax(v[ss.curShapeshift][2][1])))
            else
              self.spheres[sphere]:toggleSecondaryResourceGroup(false)
            end
          elseif v[ss.curShapeshift].buffGroup then
            -- depricated
            self.spheres[sphere]:toggleResourceGroup(v[ss.curShapeshift])
            self.spheres[sphere]:toggleSecondaryResourceGroup(false)
          else
            -- depricated
            self.spheres[sphere]:toggleResourceGroup(select(2, v[ss.curShapeshift].getMinMax(v[ss.curShapeshift][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
  end

  self:ToggleMicroSpheres(nil, sphere)
end

function mtLayout:ToggleMicroSpheres(override, sphere)
  sphere = sphere or "health"
  local microResource = (sphere == "mainResource") and ss.MicroSphereData.getSecondary() or ss.MicroSphereData.get()

  if microResource then
    if strlower(ss.curClass) == "druid" then
      return
    elseif microResource[strlower(ss.curSpecName)] and 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(override or microResource[strlower(ss.curSpecName)][1])
      elseif table.getn(microResource[strlower(ss.curSpecName)][1]) > 0 then
        self.spheres[sphere]:toggleResourceGroup(override or 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(override or 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(override or 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)] and microResource[strlower(ss.curSpecName)].buffGroup then
      -- depricated
      self.spheres[sphere]:toggleResourceGroup(override or microResource[strlower(ss.curSpecName)])
      self.spheres[sphere]:toggleSecondaryResourceGroup(false)
    elseif microResource[strlower(ss.curSpecName)] then
      -- depricated
      self.spheres[sphere]:toggleResourceGroup(override or select(2, microResource[strlower(ss.curSpecName)].getMinMax(microResource[strlower(ss.curSpecName)][1])))
      self.spheres[sphere]:toggleSecondaryResourceGroup(false)
    end
  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:OnSpecializationChanged()
  self:Refresh()
  self:AddMicroSpheres()
  self:AddMicroSpheres("mainResource")
end

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

function mtLayout:SetScale(val)
  val = val/100
  self.spheres.health:Get("sphere"):SetScale(val)
  self.spheres.mainResource:Get("sphere"):SetScale(val)
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 strlower(ss.curClass) == "druid" then
    self:Shapeshift(ss.ShapeshiftToString.parse(GetShapeshiftFormID() or 0))
  elseif strlower(ss.curClass) == "hunter" or strlower(ss.curClass) == "warlock" then
    self:TrackPet(true)
    self:TrackPet(false)
  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(nil, "mainResource")
end

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

    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 strlower(ss.curClass) ~= "druid") then
            v:setMode(ss.db[configName].modes[ss.profile.modeInfo[configName].modeSpec]["combat"]);
          end
        end
      end
    end
  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 strlower(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: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 strlower(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 strlower(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:Shapeshift(shapeshift)
  ss.curShapeshift = shapeshift

  --TODO: Dont update health sphere
  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

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