local ADDON_NAME, ns = ...

-- DB version
local DB_VERSION = 2

-- Skins + Defaults keep here (shared)
ns.SKINS = {
    { name = "Base (Orange)",      texture = "Interface\\AddOns\\pom\\skins\\base.tga", ignoreColor = true },
    { name = "Yellow",             texture = "Interface\\AddOns\\pom\\skins\\yellow.tga", ignoreColor = true },
    { name = "Cool Blue",          texture = "Interface\\AddOns\\pom\\skins\\coolblue.tga", ignoreColor = true },
    { name = "Gray",               texture = "Interface\\AddOns\\pom\\skins\\gray.tga", ignoreColor = true },
    { name = "Statusbar 1",        texture = "Interface\\AddOns\\pom\\skins\\statusbar1.tga", ignoreColor = true },
    { name = "MiniBoss",           texture = "Interface\\AddOns\\pom\\skins\\miniboss1.tga", ignoreColor = true },
    { name = "Status: Hostile",    texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_hostile_256x32.tga", ignoreColor = true },
    { name = "Status: Friendly",   texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_friendly_256x32.tga", ignoreColor = true },
    { name = "Status: Neutral",    texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_neutral_256x32.tga", ignoreColor = true },
    { name = "Class: Warrior",     texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_warrior_256x32.tga", ignoreColor = true },
    { name = "Class: Paladin",     texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_paladin_256x32.tga", ignoreColor = true },
    { name = "Class: Hunter",      texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_hunter_256x32.tga", ignoreColor = true },
    { name = "Class: Rogue",       texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_rogue_256x32.tga", ignoreColor = true },
    { name = "Class: Priest",      texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_priest_256x32.tga", ignoreColor = true },
    { name = "Class: Death Knight",texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_deathknight_256x32.tga", ignoreColor = true },
    { name = "Class: Shaman",      texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_shaman_256x32.tga", ignoreColor = true },
    { name = "Class: Mage",        texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_mage_256x32.tga", ignoreColor = true },
    { name = "Class: Warlock",     texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_warlock_256x32.tga", ignoreColor = true },
    { name = "Class: Monk",        texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_monk_256x32.tga", ignoreColor = true },
    { name = "Class: Druid",       texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_druid_256x32.tga", ignoreColor = true },
    { name = "Class: Demon Hunter",texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_demonhunter_256x32.tga", ignoreColor = true },
    { name = "Class: Evoker",      texture = "Interface\\AddOns\\pom\\skins\\robui_statusbar_evoker_256x32.tga", ignoreColor = true },
    { name = "Flat (Plater)",      texture = "Interface\\Buttons\\WHITE8x8",             ignoreColor = false },
    { name = "Smooth",             texture = "Interface\\TargetingFrame\\UI-StatusBar",  ignoreColor = false },
    { name = "Blizzard Raid",      texture = "Interface\\RaidFrame\\Raid-Bar-Hp-Fill",   ignoreColor = false },
}

ns.DEFAULTS = {
    dbVersion = DB_VERSION,
    colors = {
        normal         = { r=0.8, g=0.8, b=0.8 },
        plusOne        = { r=1.0, g=0.5, b=0.0 },
        highlevel      = { r=0.8, g=0.0, b=1.0 },
        caster         = { r=1.0, g=0.4, b=0.8 },
        melee          = { r=0.0, g=0.6, b=1.0 },
        threatHigh     = { r=1.0, g=0.0, b=0.0 },
        threatMedium   = { r=1.0, g=1.0, b=0.0 },
        threatLow      = { r=0.5, g=0.5, b=0.5 },
        threatTankSafe = { r=0.2, g=0.8, b=0.2 },
    },
    skins = { normal=23, plusOne=23, highlevel=23, caster=23, melee=23 },
    heights = { normal=16, plusOne=18, highlevel=20, caster=18, melee=18 },

    fontPath="Fonts\\FRIZQT__.TTF",
    fontSize=10,
    fontOutline="OUTLINE",

    hideClassIcon=true,
    alwaysTargetGlow=true,
    targetScale=1.15,
    showTargetArrow=true,
    arrowPointingOut=false,
    flashAggro=true,
    flashDuration=0,
    showThreatPerc=true,
    showQuestIcon=true,
    showQuestProg=true,
    colorBarByThreat=true,
    tankModeEnabled=true,
    nameAnchor="LEFT",

    globalScale=1.0,

    castBarHeight=10,
    castBarScale=1.0,
    castTextSize=10,

    buffSize=20,
    debuffSize=20,

    targetBorderColor={ r=1.0, g=0.82, b=0.0, a=1.0 },
}

local U = ns.util
local Mixins = ns.mixins
local Config = ns.config

local function Apply(frame)
    if not frame or frame:IsForbidden() then return end
    if not U.IsNameplateUnit(frame.unit) then return end

    if not frame.POM_Mixin then
        frame.POM_Mixin = Mixins:New(frame, ns.SKINS)
    end

    U.KillBlizzard(frame, PlateOMaticDB)

    frame.POM_Mixin:UpdateVisuals()
    frame.POM_Mixin:UpdateQuest()
    frame.POM_Mixin:UpdateName()
    frame.POM_Mixin:UpdateHealth()
    frame.POM_Mixin:UpdateCastbarLayout()
    if U.IsSafeUnit(frame.unit) then frame.POM_Mixin:UpdateState() end
end

local function InitDB()
    _G.PlateOMaticDB = _G.PlateOMaticDB or {}
    U.CopyDefaults(ns.DEFAULTS, _G.PlateOMaticDB)

    if not PlateOMaticDB.dbVersion then PlateOMaticDB.dbVersion = 0 end
    if PlateOMaticDB.dbVersion < DB_VERSION then
        print("|cFF00FF00Plate-o-Matic:|r Migrating DB to v" .. DB_VERSION)
        PlateOMaticDB.dbVersion = DB_VERSION
    end
end

-- Settings window
local function CreateMenu()
    if ns._menu then
        ns._menu:SetShown(not ns._menu:IsShown())
        return
    end

    local f = CreateFrame("Frame", "POM_MenuFrame", UIParent, "BasicFrameTemplateWithInset")
    f:SetSize(1020, 760)
    f:SetPoint("CENTER")
    f:SetMovable(true); f:EnableMouse(true); f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    if f.TitleText then f.TitleText:SetText("Plate-o-Matic") end

    local function applyAll()
        U.RefreshAllPlates(Apply)
        if ns.preview and ns.preview.frame and ns.preview.frame.Refresh then
            ns.preview.frame:Refresh()
        end
    end

    Config:Build(f, ns.SKINS, applyAll)

    ns._menu = f
    f:Show()
end

-- Hooks
hooksecurefunc("CompactUnitFrame_UpdateAll", Apply)
hooksecurefunc("CompactUnitFrame_UpdateHealth", Apply)
hooksecurefunc("CompactUnitFrame_UpdateName", Apply)
hooksecurefunc("CompactUnitFrame_UpdateStatusText", Apply)
hooksecurefunc("CompactUnitFrame_UpdateHealthBorder", function(frame)
    if frame and not frame:IsForbidden() and U.IsNameplateUnit(frame.unit) then
        U.KillBlizzard(frame, PlateOMaticDB)
    end
end)
hooksecurefunc("CompactUnitFrame_UpdateSelectionHighlight", function(frame)
    if frame and not frame:IsForbidden() and U.IsNameplateUnit(frame.unit) then
        if frame.selectionHighlight then U.LockAlpha(frame.selectionHighlight) end
    end
end)
hooksecurefunc("CompactUnitFrame_UpdateAuras", function(frame)
    if not frame or frame:IsForbidden() or not U.IsNameplateUnit(frame.unit) then return end
    local bScale = (PlateOMaticDB.buffSize or 20) / 18
    local dScale = (PlateOMaticDB.debuffSize or 20) / 18
    if frame.BuffFrame then frame.BuffFrame:SetScale(bScale) end
    if frame.DebuffFrame then frame.DebuffFrame:SetScale(dScale) end
    if frame.AurasFrame then
        if frame.AurasFrame.BuffListFrame then frame.AurasFrame.BuffListFrame:SetScale(bScale) end
        if frame.AurasFrame.DebuffListFrame then frame.AurasFrame.DebuffListFrame:SetScale(dScale) end
    end
end)

local ev = CreateFrame("Frame")
ev:RegisterEvent("PLAYER_LOGIN")
ev:RegisterEvent("NAME_PLATE_UNIT_ADDED")
ev:RegisterEvent("PLAYER_TARGET_CHANGED")
ev:SetScript("OnEvent", function(_, event, unit)
    if event == "PLAYER_LOGIN" then
        if C_CVar then
            C_CVar.SetCVar("nameplateShowAll", "1")
            C_CVar.SetCVar("nameplateShowEnemies", "1")
        end
        InitDB()
        print("|cFF00FF00Plate-o-Matic:|r Loaded.")
    elseif event == "NAME_PLATE_UNIT_ADDED" then
        local plate = C_NamePlate.GetNamePlateForUnit(unit)
        if plate and plate.UnitFrame then Apply(plate.UnitFrame) end
    elseif event == "PLAYER_TARGET_CHANGED" then
        U.RefreshAllPlates(Apply)
    end
end)

SLASH_PLATEOMATIC1 = "/pom"
SlashCmdList["PLATEOMATIC"] = function(msg)
    if msg == "reset" then
        PlateOMaticDB = nil
        C_UI.Reload()
        return
    end
    CreateMenu()
end
