-- UI/WarBoard_ShardPill.lua
-- Shard readout pinned to the War Board frame's top-right corner (next to the close
-- button). Faction crest + "SHARD: N" (from WB.ShardDetector); the pill grows to fit.

local addonName, WB = ...

WB.ShardPill = WB.ShardPill or {}
local SP = WB.ShardPill

-- Faction crest atlases (from interface/glues/charactercreate/charactercreatetest),
-- with the addon's emblem atlases as a fallback if the test atlas isn't present.
local FACTION_LOGO = {
    Horde    = "charcreatetest-logo-horde",
    Alliance = "charcreatetest-logo-alliance",
}
local FALLBACK_LOGO = {
    Horde    = "HordeSymbol",
    Alliance = "AllianceSymbol",
}

local PILL_H   = 32   -- pill height
local ICON_H   = 22   -- crest height (width derived from its aspect ratio)
local PAD_L    = 9    -- gap before the crest
local ICON_GAP = 7    -- gap between crest and text
local PAD_R    = 14   -- gap after the text

local pill, iconTex, label, boardParent
local detached = false

local function PillDB()
    WarBoardCharDB = WarBoardCharDB or {}
    WarBoardCharDB.shardPill = WarBoardCharDB.shardPill or {}
    return WarBoardCharDB.shardPill
end

local function MyFaction()
    if WB.faction then return WB.faction end
    return (UnitFactionGroup("player") == "Alliance") and "Alliance" or "Horde"
end

local function ResolveLogo(faction)
    local name = FACTION_LOGO[faction]
    if name and C_Texture and C_Texture.GetAtlasInfo and C_Texture.GetAtlasInfo(name) then
        return name
    end
    return FALLBACK_LOGO[faction] or "HordeSymbol"
end

local function ApplyLogo(faction)
    local atlas = ResolveLogo(faction)
    iconTex:SetAtlas(atlas)
    local info = C_Texture.GetAtlasInfo(atlas)
    local aspect = (info and info.width and info.height and info.height > 0) and (info.width / info.height) or 1
    -- Keep the crest from getting absurdly wide if the atlas is a wordmark.
    aspect = math.min(aspect, 1.4)
    iconTex:SetSize(ICON_H * aspect, ICON_H)
end

-- Grow/shrink the pill to fit the current text (anchored top-right, so it extends left).
local function UpdateWidth()
    if not pill then return end
    local textW = (label:GetStringWidth() or 0)
    local iconW = iconTex:GetWidth() or ICON_H
    pill:SetWidth(PAD_L + iconW + ICON_GAP + textW + PAD_R)
end

local function AnchorToBoard()
    if not pill or not boardParent then return end
    pill:ClearAllPoints()
    local block = WB.UI and WB.UI.warEffortPanel
    if block then
        pill:SetPoint("BOTTOM", block, "TOP", 0, 3)
    else
        pill:SetPoint("TOPRIGHT", boardParent, "TOPRIGHT", -64, -35)
    end
end

local function SaveDetachedPosition()
    if not pill then return end
    local x, y = pill:GetCenter()
    local ux, uy = UIParent:GetCenter()
    if not x or not y or not ux or not uy then return end
    local db = PillDB()
    db.detachedX = x - ux
    db.detachedY = y - uy
end

local function AnchorDetached(useCurrentPosition)
    if not pill then return end
    local db = PillDB()
    local x, y = db.detachedX, db.detachedY
    if useCurrentPosition then
        local cx, cy = pill:GetCenter()
        local ux, uy = UIParent:GetCenter()
        if cx and cy and ux and uy then x, y = cx - ux, cy - uy end
    end
    pill:ClearAllPoints()
    if x and y then
        pill:SetPoint("CENTER", UIParent, "CENTER", x, y)
    else
        pill:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -90, -170)
    end
    SaveDetachedPosition()
end

function SP.SetDetached(enabled)
    enabled = enabled and true or false
    if detached == enabled and pill then
        local expectedParent = enabled and UIParent or boardParent
        if pill:GetParent() == expectedParent then return end
    end
    detached = enabled
    if not pill then return end

    if detached then
        local db = PillDB()
        local useCurrentPosition = db.detachedX == nil or db.detachedY == nil
        pill:SetParent(UIParent)
        AnchorDetached(useCurrentPosition)
        pill:SetFrameStrata("HIGH")
        pill:SetFrameLevel(20)
        pill:SetMovable(true)
        pill:SetClampedToScreen(true)
        if db.hidden then pill:Hide() else pill:Show() end
    else
        pill:SetParent(boardParent)
        pill:SetFrameStrata(boardParent:GetFrameStrata())
        pill:SetFrameLevel(boardParent:GetFrameLevel() + 10)
        pill:SetMovable(false)
        AnchorToBoard()
        if PillDB().hidden then pill:Hide() else pill:Show() end
    end
end

function SP.IsDetached()
    return detached
end

-- Set the displayed shard. nil/empty shows the unresolved placeholder.
function SP.SetShard(shardID)
    if not label then return end
    if shardID ~= nil and tostring(shardID) ~= "" then
        label:SetText("SHARD: " .. tostring(shardID))
    else
        label:SetText("SHARD: --")
    end
    UpdateWidth()
end

-- Build the pill as a child of the War Board frame, pinned to its top-right corner.
function SP.Create(parent)
    if pill then return end
    parent = parent or WB.UI and WB.UI.frame
    if not parent then return end
    boardParent = parent
    local faction = MyFaction()

    pill = CreateFrame("Button", "WarBoardShardPill", parent, "BackdropTemplate")
    pill:SetHeight(PILL_H)
    pill:SetWidth(120)
    -- Centered over the War Effort Progress block (so it stays "even" with it) and
    -- pinned by its bottom, just above the block. The center anchor means the pill
    -- grows symmetrically outward from the middle as the shard number populates.
    AnchorToBoard()

    pill:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        edgeSize = 14,
        insets   = { left = 4, right = 4, top = 4, bottom = 4 },
    })
    pill:SetBackdropColor(0.03, 0.03, 0.04, 0.92)
    pill:SetBackdropBorderColor(0.82, 0.66, 0.32, 0.95)  -- thin gold frame
    pill:RegisterForClicks("LeftButtonUp")
    pill:RegisterForDrag("LeftButton")
    pill:SetScript("OnClick", function(self)
        if self.wasDragged then return end
        if WB.ShardMatcher and WB.ShardMatcher.Show then
            WB.ShardMatcher.Show()
        end
    end)
    pill:SetScript("OnDragStart", function(self)
        if not detached then return end
        self.wasDragged = true
        GameTooltip:Hide()
        self:StartMoving()
    end)
    pill:SetScript("OnDragStop", function(self)
        if not detached then return end
        self:StopMovingOrSizing()
        SaveDetachedPosition()
        AnchorDetached(false)
        C_Timer.After(0, function() self.wasDragged = nil end)
    end)
    pill:SetScript("OnEnter", function(self)
        self:SetBackdropColor(0.08, 0.07, 0.05, 0.96)
        self:SetBackdropBorderColor(1.00, 0.82, 0.38, 1.00)
        GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
        GameTooltip:SetText("Open Shard Matcher", 1.00, 0.82, 0.38)
        if detached then GameTooltip:AddLine("Drag to move", 0.78, 0.76, 0.70) end
        GameTooltip:Show()
    end)
    pill:SetScript("OnLeave", function(self)
        self:SetBackdropColor(0.03, 0.03, 0.04, 0.92)
        self:SetBackdropBorderColor(0.82, 0.66, 0.32, 0.95)
        GameTooltip:Hide()
    end)

    iconTex = pill:CreateTexture(nil, "ARTWORK")
    iconTex:SetPoint("LEFT", pill, "LEFT", PAD_L, 0)
    ApplyLogo(faction)

    label = pill:CreateFontString(nil, "OVERLAY")
    label:SetPoint("LEFT", iconTex, "RIGHT", ICON_GAP, 0)
    label:SetFont(STANDARD_TEXT_FONT, 12, "")
    label:SetTextColor(0.96, 0.92, 0.80)

    -- Seed from whatever the detector already resolved.
    local cur = WB.ShardDetector and WB.ShardDetector.GetShardID and WB.ShardDetector:GetShardID()
    SP.SetShard(cur)

    -- Honour saved visibility.
    if WarBoardCharDB and WarBoardCharDB.shardPill and WarBoardCharDB.shardPill.hidden then
        pill:Hide()
    end

    SP.SetDetached(WB.Options and WB.Options.Get and WB.Options.Get("detachShardTracker"))
end

-- Show / hide the pill (persisted).
function SP.Toggle()
    if not pill then return end
    local db = PillDB()
    if pill:IsShown() then
        pill:Hide()
        db.hidden = true
    else
        pill:Show()
        db.hidden = false
    end
end

function SP.IsShown()
    return pill and pill:IsShown()
end
