-- ============================================================
--  rOrbs – Custom Template Creator  (rewrite)
-- ============================================================
--
--  How preview works (simple):
--
--    1. User enters DisplayInfo ID, clicks Preview.
--    2. We create a small tmpl table and store it in
--       ns.orbTemplates["_preview_"].
--    3. engine:Apply(orbType, "_preview_") loads the model.
--    4. When the user moves a slider we write the new value
--       directly into the preview tmpl table and call
--       engine:Refresh(orbType).  That's it – no special
--       UpdatePreview function, no drift, no complexity.
--    5. Save Template: copies tmpl values into rOrbsDB,
--       calls engine:Apply() with the real saved key.
--    6. My Templates dropdown: calls engine:Apply() with
--       the saved key – same as any built-in template.
-- ============================================================

local _, ns = ...

local M = "Interface\\AddOns\\rOrbs\\media\\"

local custom = {}
ns.CustomTemplateCreator = custom

-- active preview per orbType
custom._active = {}   -- [orbType] = true/false

-- ---- DB helpers -----------------------------------------
local function DB()
  rOrbsDB = rOrbsDB or {}
  rOrbsDB.customTemplates = rOrbsDB.customTemplates or {}
  return rOrbsDB.customTemplates
end

-- ---- Sorted list ----------------------------------------
function custom:RebuildList()
  ns.customTemplateList = {}
  for key, data in pairs(DB()) do
    table.insert(ns.customTemplateList, { key = key, label = data.label or key })
  end
  table.sort(ns.customTemplateList, function(a, b) return a.label < b.label end)
  table.insert(ns.customTemplateList, 1, { key = "custom-none", label = "None (Custom)" })
end

function custom:Get(key)
  if not key or key == "custom-none" then return nil end
  return DB()[key]
end

-- ---- Save -----------------------------------------------
function custom:Save(name, state)
  if not name or name == "" then return false end
  local key = name:lower():gsub("[^%w%-_]", "-"):gsub("%-+", "-")
  if key == "" or key == "none" or key == "custom-none" then
    key = "custom-" .. tostring(GetTime()):gsub("%.", "")
  end
  DB()[key] = {
    label         = name,
    displayInfoID = state.displayInfoID or 0,
    camScale      = state.camScale      or 1.0,
    modelOpacity  = state.modelOpacity  or 1.0,
    posAdjustX    = state.posAdjustX    or 0,
    posAdjustZ    = state.posAdjustZ    or 0,
    statusBarColor   = state.statusBarColor   or {1,1,1,1},
    sparkColor       = state.sparkColor       or {1,1,1,1},
    statusBarTexture = state.statusBarTexture or (M.."orb_filling16"),
  }
  self:RebuildList()
  return true, key
end

-- ---- Delete ---------------------------------------------
function custom:Delete(key)
  if not key or key == "custom-none" then return false end
  if DB()[key] then DB()[key] = nil; self:RebuildList(); return true end
  return false
end

-- ---- StartPreview ---------------------------------------
-- Creates a mutable preview tmpl table, stores it in ns.orbTemplates["_preview_"],
-- and loads it onto the orb.
function custom:StartPreview(orbType, displayInfoID, camScale, posAdjustZ)
  if not displayInfoID or displayInfoID == 0 then return end

  local tmpl = {
    displayInfoID  = displayInfoID,
    camScale       = camScale    or 1.0,
    modelOpacity   = 1.0,
    posAdjustX     = 0,
    posAdjustZ     = posAdjustZ  or 0,
    statusBarColor = {1,1,1,1},
    sparkColor     = {1,1,1,1},
    statusBarTexture = M.."orb_filling16",
    _isPreview     = true,
  }

  ns.orbTemplates = ns.orbTemplates or {}
  ns.orbTemplates["_preview_"] = tmpl

  if ns.OrbTemplateEngine then
    ns.OrbTemplateEngine:Apply(orbType, "_preview_", false)
  end
  if rOrbsDB then rOrbsDB["tmplShow_"..orbType] = true end
  self._active[orbType] = true
  return tmpl
end

-- Legacy alias
custom.Preview = custom.StartPreview

-- ---- LiveUpdate -----------------------------------------
-- Called by GUI sliders OnValueChanged.  Writes new values into the
-- existing preview tmpl table (no model reload) and refreshes.
function custom:LiveUpdate(orbType, camScale, posAdjustZ, posAdjustX)
  if not self._active[orbType] then return end
  local tmpl = ns.orbTemplates and ns.orbTemplates["_preview_"]
  if not tmpl then return end

  if camScale    ~= nil then tmpl.camScale    = camScale    end
  if posAdjustZ  ~= nil then tmpl.posAdjustZ  = posAdjustZ  end
  if posAdjustX  ~= nil then tmpl.posAdjustX  = posAdjustX  end

  -- Also keep orb._tmpl pointing at the same table (it already does since Apply
  -- stored a reference, but make sure)
  local orb
  if orbType == "HEALTH"        then orb = ns.HealthOrb
  elseif orbType == "POWER"         then orb = ns.PowerOrb
  elseif orbType == "TARGET_HEALTH" then orb = ns.TargetHealthOrb
  elseif orbType == "TOT_HEALTH"    then orb = ns.ToTHealthOrb
  end
  if orb then
    orb._tmpl           = tmpl
    orb._templateConfig = tmpl
    if orb.model then orb.model._tmpl = tmpl end
  end

  if ns.OrbTemplateEngine then ns.OrbTemplateEngine:Refresh(orbType) end
end

-- Legacy alias used by existing GUI code
custom.UpdatePreview = custom.LiveUpdate

-- ---- Reset to center ------------------------------------
function custom:ResetPreviewToCenter(orbType)
  if not self._active[orbType] then return end
  local tmpl = ns.orbTemplates and ns.orbTemplates["_preview_"]
  if not tmpl then return end
  tmpl.camScale    = 1.0
  tmpl.posAdjustZ  = 0
  tmpl.posAdjustX  = 0
  if rOrbsDB then
    rOrbsDB["tmplScale_"  ..orbType] = 1.0
    rOrbsDB["tmplOffsetX_"..orbType] = 0
    rOrbsDB["tmplOffsetZ_"..orbType] = 0
    rOrbsDB["tmplOpacity_"..orbType] = 1.0
  end
  if ns.OrbTemplateEngine then ns.OrbTemplateEngine:Refresh(orbType) end
end

-- ---- StopPreview ----------------------------------------
function custom:StopPreview(orbType)
  self._active[orbType] = false
  ns.orbTemplates["_preview_"] = nil
  local orb
  if orbType == "HEALTH"        then orb = ns.HealthOrb
  elseif orbType == "POWER"         then orb = ns.PowerOrb
  elseif orbType == "TARGET_HEALTH" then orb = ns.TargetHealthOrb
  elseif orbType == "TOT_HEALTH"    then orb = ns.ToTHealthOrb
  end
  if orb and ns.OrbTemplateEngine then ns.OrbTemplateEngine:RemoveTemplate(orb) end
  if rOrbsDB then
    rOrbsDB["orbTemplate_"..orbType] = "none"
    rOrbsDB["tmplShow_"..orbType]    = false
  end
end

-- ---- Init -----------------------------------------------
ns.RegisterInit("rOrbs_CustomTemplates", function()
  DB()
  custom:RebuildList()
end)
