-- PaladinHolyPower - modules/model_animation.lua
-- Two PlayerModel layers behind each Holy Power icon (custom style).
-- Model size = icon size * (1 + MULT). Sits one frame level below icons.

local PHP = _G.PaladinHolyPower
if not PHP then return end

local M = {}
PHP.ModelAnimations = M

-- State
M.created = false
M.alpha = 1
M.alwaysVisible = false
M.modelAnimations = {} -- [i] = { layer1Model, layer2Model }

-- Model assets
local MODEL_ID_1 = 1062276
local MODEL_ID_2 = 1261307

-- Per-layer extra scale (final = icon * (1 + MULT))
local MULT1 = 1.65
local MULT2 = 1.50

-- Optional small per-layer offsets (x=depth, y=left/right, z=up/down)
local OFFSETS = {
  [1] = { x = 0,      y = 0,   z = 0 },
  [2] = { x = -0.4,   y = 0,   z = 0 },
}

-- Internal helpers ----------------------------------------------------

local function anchorAndSize(model, icon, extra, fixedSize)
  local w = fixedSize or (icon and icon:GetWidth()) or 48
  local s = w * (1 + (extra or 0))
  if s < 4 then s = 4 end
  model:ClearAllPoints()
  model:SetPoint("CENTER", icon or model:GetParent(), "CENTER", 0, 0)
  model:SetSize(s, s)
end

local function applyOffsets(model)
  local off = OFFSETS[model._layer]
  if off and model.SetPosition then
    model:SetPosition(off.x or 0, off.y or 0, off.z or 0)
  end
end

local function armAnimation(model)
  if model._animHooked then return end
  model:SetScript("OnUpdate", function(self, dt)
    self._t = (self._t or 0) + dt * 1000
    self:SetSequenceTime(0, self._t % 1000)
  end)
  model._animHooked = true
end

local function redraw(model)
  model:SetModel(model._modelId)
  model:SetSequence(0)
  model._t = model._t or 0
  applyOffsets(model)
  armAnimation(model)
end

local function showModel(model, a)
  if not model:IsShown() then redraw(model); model:Show() end
  model:SetAlpha(a or 1)
end

local function hideModel(model)
  if model:IsShown() then model:Hide() end
end

-- Public API ----------------------------------------------------------

function M.CreateModelAnimations(parent, count)
  if M.created or not parent or not parent.icons then return end
  M.created = true
  wipe(M.modelAnimations)

  local strata = parent:GetFrameStrata()
  local lvl = (parent:GetFrameLevel() or 2) - 1
  if lvl < 1 then lvl = 1 end

  for i = 1, count do
    local icon = parent.icons[i]
    local bucket = {}

    for layer = 1, 2 do
      local id = (layer == 1) and MODEL_ID_1 or MODEL_ID_2
      local ex = (layer == 1) and MULT1      or MULT2

      local m = CreateFrame("PlayerModel",
        (parent:GetName() or "PHP_HPBar").."_Model"..i.."_"..layer, parent)
      m:SetFrameStrata(strata)
      m:SetFrameLevel(lvl)
      m._modelId = id
      m._layer = layer

      anchorAndSize(m, icon, ex)
      showModel(m, M.alpha)

      bucket[#bucket + 1] = m
    end

    M.modelAnimations[i] = bucket
  end
end

function M.UpdateLayout(parent, iconSize)
  if not M.created or not parent or not parent.icons then return end

  local strata = parent:GetFrameStrata()
  local lvl = (parent:GetFrameLevel() or 2) - 1
  if lvl < 1 then lvl = 1 end

  for i, bucket in ipairs(M.modelAnimations) do
    local icon = parent.icons[i]
    if icon and bucket then
      for layerIdx, m in ipairs(bucket) do
        m:SetFrameStrata(strata)
        m:SetFrameLevel(lvl)
        local ex = (layerIdx == 1) and MULT1 or MULT2
        anchorAndSize(m, icon, ex, iconSize)
        applyOffsets(m)
        m:SetAlpha(M.alpha)
      end
    end
  end
end

function M.SetAlwaysVisible(flag)
  M.alwaysVisible = not not flag
end

function M.UpdateVisibility(count, hp)
  if not M.created then return end
  hp = math.max(0, tonumber(hp) or 0)
  for i = 1, count do
    local bucket = M.modelAnimations[i]
    if bucket then
      local visible = M.alwaysVisible or (i <= hp)
      for _, m in ipairs(bucket) do
        if visible then showModel(m, M.alpha) else hideModel(m) end
      end
    end
  end
end

function M.HideAllModelAnimations()
  if not M.created then return end
  for _, bucket in ipairs(M.modelAnimations) do
    for _, m in ipairs(bucket) do hideModel(m) end
  end
end

function M.RearmVisible()
  if not M.created then return end
  for _, bucket in ipairs(M.modelAnimations) do
    for _, m in ipairs(bucket) do
      if m:IsShown() then redraw(m); m:SetAlpha(M.alpha) end
    end
  end
end

function M.SetAlpha(a)
  a = tonumber(a) or 1
  if a < 0 then a = 0 elseif a > 1 then a = 1 end
  M.alpha = a
  if not M.created then return end
  for _, bucket in ipairs(M.modelAnimations) do
    for _, m in ipairs(bucket) do m:SetAlpha(a) end
  end
end

return M