-- =====================================================================
-- LiveStrat — Tools.lua
-- La colonne d'outils à droite du tableau : outils de dessin, palette,
-- marqueurs de rôle, diffusion et panneau des droits.
-- ns.tool = { mode = "P"|"N"|"A"|"C"|"T"|"M", color = 1-8, role = 1-3 }
-- =====================================================================
local ADDON, ns = ...
local L = ns.L

local Tools = {}
ns.modules.Tools = Tools

ns.tool = { mode = "P", color = 1, role = 3 }

local function btn(parent, label, w, onClick)
    local b = ns.CreateModernButton(parent, w or 128, 24, label)
    b:SetScript("OnClick", onClick)
    return b
end

function Tools:Attach(f)
    local col = CreateFrame("Frame", nil, f)
    col:SetSize(140, 460)
    col:SetPoint("TOPRIGHT", -10, -40)
    self.col = col

    -- ----- BOUTONS À ICÔNES façon Paint ------------------------------
    -- Les glyphes d'OUTILS sont DESSINÉS (lignes vectorielles) sur le
    -- bouton : un vrai trait pour « Trait », une vraie flèche, un vrai
    -- cercle — nets à toute échelle, zéro dépendance de texture.
    local GLYPH = { 0.92, 0.92, 0.95 }
    local function seg(b, x1, y1, x2, y2)
        local ln = b:CreateLine(nil, "OVERLAY")
        ln:SetTexture("Interface\\Buttons\\WHITE8x8")
        ln:SetVertexColor(GLYPH[1], GLYPH[2], GLYPH[3], 0.95)
        ln:SetThickness(2)
        ln:SetStartPoint("TOPLEFT", b, x1, -y1)
        ln:SetEndPoint("TOPLEFT", b, x2, -y2)
    end
    local function iconBtn(label, onClick, paint)
        local b = ns.CreateModernButton(col, 28, 28)
        b:SetScript("OnClick", onClick)
        b:SetScript("OnEnter", function(s)
            s._hover = true s:Repaint()
            GameTooltip:SetOwner(s, "ANCHOR_RIGHT")
            GameTooltip:SetText(label)
            GameTooltip:Show()
        end)
        b:SetScript("OnLeave", function(s)
            s._hover = nil s:Repaint()
            GameTooltip:Hide()
        end)
        if paint then paint(b) end
        return b
    end
    local function grid(items, anchor, dy)
        local first
        for i, it in ipairs(items) do
            it.btn:ClearAllPoints()
            if i == 1 then
                it.btn:SetPoint("TOPLEFT", anchor, (anchor == col) and "TOPLEFT" or "BOTTOMLEFT",
                    (anchor == col) and 6 or 0, (anchor == col) and -4 or (dy or -10))
                first = it.btn
            elseif (i - 1) % 4 == 0 then
                it.btn:SetPoint("TOPLEFT", items[i - 4].btn, "BOTTOMLEFT", 0, -4)
            else
                it.btn:SetPoint("LEFT", items[i - 1].btn, "RIGHT", 4, 0)
            end
        end
        return first
    end

    self.toolBtns = {}
    local function toolClick(mode)
        return function() ns.tool.mode = mode Tools:UpdateToolUI() end
    end
    local toolDefs = {
        { "S", L["Déplacer"], function(b)   -- curseur-flèche façon éditeur
            seg(b, 10, 6, 10, 20) seg(b, 10, 6, 19, 15)
            seg(b, 10, 20, 13, 16) seg(b, 19, 15, 14, 15)
            seg(b, 13, 16, 16, 21) seg(b, 14, 15, 16, 21)
        end },
        { "P", L["Crayon"], function(b)   -- petite courbe libre
            seg(b, 6, 21, 11, 12) seg(b, 11, 12, 16, 17) seg(b, 16, 17, 22, 7)
        end },
        { "N", L["Trait"], function(b) seg(b, 6, 21, 22, 7) end },
        { "A", L["Flèche"], function(b)
            seg(b, 6, 21, 21, 8) seg(b, 21, 8, 14, 9) seg(b, 21, 8, 20, 15)
        end },
        { "C", L["Cercle"], function(b)
            local cx, cy, r = 14, 14, 8
            local px, py
            for i = 0, 12 do
                local a = i / 12 * 2 * math.pi
                local x = cx + math.cos(a) * r
                local y = cy + math.sin(a) * r
                if px then seg(b, px, py, x, y) end
                px, py = x, y
            end
        end },
        { "T", L["Texte"], function(b)
            local fs = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
            fs:SetPoint("CENTER")
            fs:SetText("T")
        end },
        { "E", L["Gomme"], function(b)   -- gomme inclinée
            seg(b, 7, 18, 13, 9) seg(b, 13, 9, 21, 13)
            seg(b, 21, 13, 15, 22) seg(b, 15, 22, 7, 18)
            seg(b, 10, 14, 17, 17)
        end },
    }
    local toolItems = {}
    self._toolPainters = {}
    self._toolLabels = {}
    for _, d in ipairs(toolDefs) do
        local b = iconBtn(d[2], toolClick(d[1]), d[3])
        self.toolBtns[d[1]] = b
        self._toolPainters[d[1]] = d[3]
        self._toolLabels[d[1]] = d[2]
        toolItems[#toolItems + 1] = { btn = b }
    end
    -- ANNULER (action, pas un mode) : flèche de retour + Ctrl+Z.
    local undoBtn = iconBtn(L["Annuler (Ctrl+Z)"], function()
        ns.modules.Board:Undo()
    end, function(b)
        seg(b, 20, 11, 9, 11) seg(b, 9, 11, 13, 7) seg(b, 9, 11, 13, 15)
        seg(b, 20, 11, 20, 17) seg(b, 20, 17, 13, 19)
    end)
    toolItems[#toolItems + 1] = { btn = undoBtn }
    grid(toolItems, col)
    -- ancre de la grille suivante : PREMIER bouton de la dernière rangée
    -- (le dernier bouton peut être en 2e colonne — décalait tout, vécu)
    local lastRowFirst = toolItems[math.floor((#toolItems - 1) / 4) * 4 + 1].btn
    local prev = lastRowFirst

    -- Marqueurs de rôle : les LOGOS officiels (bouclier/croix/épées),
    -- tête de mort pour Boss, petite tête grise pour Add.
    local ROLE_TC = {
        [1] = { 0, 19 / 64, 22 / 64, 41 / 64 },
        [2] = { 20 / 64, 39 / 64, 1 / 64, 20 / 64 },
        [3] = { 20 / 64, 39 / 64, 22 / 64, 41 / 64 },
    }
    local function roleClick(role)
        return function()
            ns.tool.mode = "M"
            ns.tool.role = role
            -- étiquette auto : le nom de la cible si c'est un joueur du
            -- groupe (« le tank Kaya ICI » en un clic)
            local tn = UnitExists("target") and UnitInParty("target")
                and UnitName("target") or ""
            ns.tool.label = (role <= 3) and tn or ""
            Tools:UpdateToolUI()
        end
    end
    local function roundTex(bb, t)
        local mask = bb:CreateMaskTexture()
        mask:SetTexture("Interface\\CharacterFrame\\TempPortraitAlphaMask",
            "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
        mask:SetAllPoints(t)
        t:AddMaskTexture(mask)
    end
    local roleDefs = {
        { 1, L["Tank"] }, { 2, L["Soigneur"] }, { 3, L["DPS"] },
        { 4, L["Boss"] }, { 5, L["Add"] },
        { 6, L["Soak"] }, { 7, L["Dispel"] }, { 8, L["Flaque"] },
        { 9, L["Kick"] },
        -- Icônes de raid officielles (11-18 = étoile → tête de mort)
        { 11, RAID_TARGET_1 or "Étoile" }, { 12, RAID_TARGET_2 or "Cercle" },
        { 13, RAID_TARGET_3 or "Losange" }, { 14, RAID_TARGET_4 or "Triangle" },
        { 15, RAID_TARGET_5 or "Lune" }, { 16, RAID_TARGET_6 or "Carré" },
        { 17, RAID_TARGET_7 or "Croix" }, { 18, RAID_TARGET_8 or "Tête de mort" },
    }
    local roleItems = {}
    for _, d in ipairs(roleDefs) do
        local role, label = d[1], d[2]
        local b = iconBtn(label, roleClick(role), function(bb)
            local t = bb:CreateTexture(nil, "OVERLAY")
            t:SetPoint("CENTER")
            if role <= 3 then
                t:SetSize(20, 20)
                t:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES")
                local tc = ROLE_TC[role]
                t:SetTexCoord(tc[1], tc[2], tc[3], tc[4])
            elseif role == 6 then      -- soak : disque vert
                t:SetSize(18, 18)
                t:SetTexture("Interface\\Buttons\\WHITE8x8")
                t:SetVertexColor(0.25, 0.95, 0.45, 0.7)
                roundTex(bb, t)
            elseif role == 8 then      -- flaque : disque violet
                t:SetSize(19, 19)
                t:SetTexture("Interface\\Buttons\\WHITE8x8")
                t:SetVertexColor(0.50, 0.20, 0.75, 0.8)
                roundTex(bb, t)
            elseif role == 7 then      -- dispel
                t:SetSize(19, 19)
                t:SetTexture("Interface\\Icons\\Spell_Holy_DispelMagic")
                roundTex(bb, t)
            elseif role == 9 then      -- kick
                t:SetSize(19, 19)
                t:SetTexture("Interface\\Icons\\Ability_Kick")
                roundTex(bb, t)
            elseif role >= 11 and role <= 18 then
                t:SetSize(20, 20)
                t:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
                local idx = role - 10
                local lft = ((idx - 1) % 4) * 0.25
                local tp = math.floor((idx - 1) / 4) * 0.25
                t:SetTexCoord(lft, lft + 0.25, tp, tp + 0.25)
            else
                t:SetSize(role == 4 and 22 or 15, role == 4 and 22 or 15)
                local okA = pcall(t.SetAtlas, t, "DungeonSkull")
                if not okA then
                    t:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcon_8")
                end
                if role == 5 then t:SetVertexColor(0.75, 0.75, 0.75) end
            end
        end)
        self.toolBtns["M" .. role] = b
        roleItems[#roleItems + 1] = { btn = b }
    end
    grid(roleItems, prev, -12)
    prev = roleItems[#roleItems].btn

    -- Palette : pastilles RONDES (texture pleine + masque circulaire du
    -- portrait Blizzard), anneau blanc sur la couleur active.
    -- (alignement : TOUT s'ancre en BOTTOMLEFT de l'élément précédent —
    -- l'ancrage centré sur le petit bouton « Add » décalait tout, vécu)
    local pal = CreateFrame("Frame", nil, col)
    pal:SetSize(124, 56)
    -- ancrage : 1er bouton de la DERNIÈRE rangée de rôles (3 rangées
    -- maintenant — l'ancrage sur la 1re rangée chevauchait, vécu)
    local lastRoleRowFirst = roleItems[math.floor((#roleItems - 1) / 4) * 4 + 1].btn
    pal:SetPoint("TOPLEFT", lastRoleRowFirst, "BOTTOMLEFT", 0, -12)
    self.swatches = {}
    for i, c in ipairs(ns.modules.Board.COLORS) do
        local s = CreateFrame("Button", nil, pal)
        s:SetSize(24, 24)
        s:SetPoint("TOPLEFT", ((i - 1) % 4) * 32, -math.floor((i - 1) / 4) * 28)
        -- ANNEAU de sélection : un DISQUE blanc masqué, légèrement plus
        -- grand, SOUS la pastille — un vrai anneau net, zéro atlas
        -- (l'atlas doré ne s'affichait pas, vécu). La pastille active
        -- grossit aussi (18→22) : impossible de la rater.
        s.ring = s:CreateTexture(nil, "BORDER")
        s.ring:SetPoint("CENTER")
        s.ring:SetSize(28, 28)
        s.ring:SetColorTexture(1, 1, 1, 1)
        local rmask = s:CreateMaskTexture()
        rmask:SetTexture("Interface\\CharacterFrame\\TempPortraitAlphaMask",
            "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
        rmask:SetAllPoints(s.ring)
        s.ring:AddMaskTexture(rmask)
        s.ring:Hide()
        s.fill = s:CreateTexture(nil, "ARTWORK")
        s.fill:SetPoint("CENTER")
        s.fill:SetSize(18, 18)
        s.fill:SetColorTexture(c[1], c[2], c[3], 1)
        local mask = s:CreateMaskTexture()
        mask:SetTexture("Interface\\CharacterFrame\\TempPortraitAlphaMask",
            "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
        mask:SetAllPoints(s.fill)
        s.fill:AddMaskTexture(mask)
        s:SetScript("OnClick", function()
            ns.tool.color = i
            Tools:UpdateToolUI()
        end)
        self.swatches[i] = s
    end
    prev = pal

    -- Actions
    local clear = btn(col, L["Tout effacer"], 124, function()
        if not ns.CanDraw() then return end
        -- CONFIRMATION (un mé-clic du chef détruisait la page, vécu de
        -- justesse) — et l'effacement ne touche que la PHASE courante.
        if not StaticPopupDialogs.LIVESTRAT_CLEAR then
            StaticPopupDialogs.LIVESTRAT_CLEAR = {
                text = "|cff33ccffLiveStrat|r — " .. L["Effacer TOUT le plan de cette phase ?"],
                button1 = YES, button2 = NO,
                timeout = 0, whileDead = true, hideOnEscape = true,
                OnAccept = function()
                    ns.modules.Board:ClearAll()
                    ns.modules.Sync:SendClear()
                end,
            }
        end
        StaticPopup_Show("LIVESTRAT_CLEAR")
    end)
    clear:SetPoint("TOPLEFT", pal, "BOTTOMLEFT", 0, -12)
    prev = clear

    local bcast = btn(col, L["Envoyer au groupe"], 124, function()
        if not ns.CanDraw() then return end
        if not IsInGroup() then
            print("LiveStrat : " .. L["Hors groupe : rien à envoyer — le plan sera demandé automatiquement quand tu seras en groupe."])
            return
        end
        ns.modules.Sync:SendACL()
        ns.modules.Sync:SendMapContext()
        ns.modules.Sync:SendFullBoard()
        ns.modules.Sync:AnnounceState()
        -- Compte + RETOUR VISIBLE (vécu : « aucun message n'est parti »
        -- — si, mais rien ne le disait).
        local tot, missing = 0, 0
        local prefix = IsInRaid() and "raid" or "party"
        for i = 1, GetNumGroupMembers() do
            local unit = prefix .. i
            if UnitExists(unit) and not UnitIsUnit(unit, "player") then
                tot = tot + 1
                if not ns.present[ns.FullName(unit)] then
                    missing = missing + 1
                end
            end
        end
        print(("LiveStrat : " .. L["plan envoyé à %d membre(s) — %d sans l'addon."])
            :format(tot, missing))
        -- Ligne d'invitation pour les sans-addon (max 1 / 5 min).
        if missing > 0 and (not Tools._lastInvite
            or GetTime() - Tools._lastInvite > 300) then
            Tools._lastInvite = GetTime()
            SendChatMessage(L["LiveStrat : plan tactique diffusé — installez l'addon LiveStrat pour le voir."],
                IsInRaid() and "RAID" or "PARTY")
        end
    end)
    bcast:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -4)
    bcast:SetScript("OnEnter", function(s)
        s._hover = true s:Repaint()
        GameTooltip:SetOwner(s, "ANCHOR_RIGHT")
        GameTooltip:SetText(L["Envoyer au groupe"])
        GameTooltip:AddLine(L["Renvoie le plan COMPLET à tout le groupe — pour resynchroniser un retardataire ou partager un plan préparé à l'avance. En dessin normal, tout part déjà en direct."], 1, 1, 1, true)
        GameTooltip:Show()
    end)
    bcast:SetScript("OnLeave", function(s)
        s._hover = nil s:Repaint()
        GameTooltip:Hide()
    end)
    self.bcastBtn = bcast

    -- Inviter le groupe à OUVRIR son tableau (popup + son chez eux).
    local invite = btn(col, L["Inviter à ouvrir"], 124, function()
        if not ns.CanDraw() then return end
        if not IsInGroup() then
            print("LiveStrat : " .. L["Hors groupe : rien à envoyer — le plan sera demandé automatiquement quand tu seras en groupe."])
            return
        end
        ns.modules.Board:_broadcastContext()
        ns.modules.Sync:SendOpenInvite()
        print("LiveStrat : " .. L["invitation à ouvrir le tableau envoyée."])
    end)
    invite:SetPoint("TOPLEFT", bcast, "BOTTOMLEFT", 0, -4)
    self.inviteBtn = invite

    -- EXPORT / IMPORT du plan par chaîne (partage Discord entre RL).
    local exportB = btn(col, L["Exporter"], 60, function()
        if not StaticPopupDialogs.LIVESTRAT_EXPORT then
            StaticPopupDialogs.LIVESTRAT_EXPORT = {
                text = "|cff33ccffLiveStrat|r — " .. L["Chaîne du plan (Ctrl+C) :"],
                button1 = DONE, hasEditBox = true,
                timeout = 0, whileDead = true, hideOnEscape = true,
                OnShow = function(self)
                    -- (Midnight : le champ s'appelle EditBox — majuscule)
                    local eb = self.EditBox or self.editBox
                    eb:SetText(self.data or "")
                    eb:HighlightText()
                    eb:SetFocus()
                end,
                EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
            }
        end
        local dlg = StaticPopup_Show("LIVESTRAT_EXPORT")
        if dlg then
            dlg.data = ns.modules.Board:ExportString()
            local eb = dlg.EditBox or dlg.editBox
            eb:SetText(dlg.data)
            eb:HighlightText()
        end
    end)
    exportB:SetPoint("TOPLEFT", invite, "BOTTOMLEFT", 0, -4)
    local importB = btn(col, L["Importer"], 60, function()
        if not ns.CanDraw() then return end
        if not StaticPopupDialogs.LIVESTRAT_IMPORT then
            StaticPopupDialogs.LIVESTRAT_IMPORT = {
                text = "|cff33ccffLiveStrat|r — " .. L["Colle la chaîne du plan :"],
                button1 = OKAY, button2 = CANCEL, hasEditBox = true,
                timeout = 0, whileDead = true, hideOnEscape = true,
                OnAccept = function(self)
                    local eb = self.EditBox or self.editBox
                    ns.modules.Board:ImportString(eb:GetText())
                end,
                EditBoxOnEnterPressed = function(self)
                    ns.modules.Board:ImportString(self:GetText())
                    self:GetParent():Hide()
                end,
                EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
            }
        end
        StaticPopup_Show("LIVESTRAT_IMPORT")
    end)
    importB:SetPoint("LEFT", exportB, "RIGHT", 4, 0)
    -- (les droits vivent maintenant dans la colonne « En direct » à
    -- GAUCHE de la fenêtre — voir Board:UpdateViewersUI)

    self:UpdateToolUI()
    self:UpdatePermissionUI()
    self:_buildMiniBar(f)
end

-- MINI-BARRE du mode combat : outils essentiels + couleur cyclable —
-- le chef doit pouvoir dessiner même en fenêtre réduite (vécu).
function Tools:_buildMiniBar(f)
    local bar = CreateFrame("Frame", nil, f)
    bar:SetSize(210, 24)
    bar.btns = {}
    local prev
    for _, mode in ipairs({ "S", "P", "N", "A", "C", "T" }) do
        local b = ns.CreateModernButton(bar, 24, 24)
        local paint = self._toolPainters[mode]
        if paint then paint(b) end
        b:SetScript("OnClick", function()
            ns.tool.mode = mode
            Tools:UpdateToolUI()
        end)
        b:SetScript("OnEnter", function(s)
            s._hover = true s:Repaint()
            GameTooltip:SetOwner(s, "ANCHOR_TOP")
            GameTooltip:SetText(Tools._toolLabels[mode] or mode)
            GameTooltip:Show()
        end)
        b:SetScript("OnLeave", function(s)
            s._hover = nil s:Repaint()
            GameTooltip:Hide()
        end)
        if prev then b:SetPoint("LEFT", prev, "RIGHT", 3, 0)
        else b:SetPoint("LEFT", bar, "LEFT", 0, 0) end
        bar.btns[mode] = b
        prev = b
    end
    -- Couleur ACTIVE, cyclable au clic.
    local cb = ns.CreateModernButton(bar, 24, 24)
    cb.fill = cb:CreateTexture(nil, "OVERLAY")
    cb.fill:SetPoint("CENTER")
    cb.fill:SetSize(14, 14)
    local mask = cb:CreateMaskTexture()
    mask:SetTexture("Interface\\CharacterFrame\\TempPortraitAlphaMask",
        "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
    mask:SetAllPoints(cb.fill)
    cb.fill:AddMaskTexture(mask)
    cb:SetScript("OnClick", function()
        ns.tool.color = ns.tool.color % #ns.modules.Board.COLORS + 1
        Tools:UpdateToolUI()
    end)
    cb:SetPoint("LEFT", prev, "RIGHT", 8, 0)
    bar.colorBtn = cb
    bar:Hide()
    self.mini = bar
end

function Tools:UpdateToolUI()
    for key, b in pairs(self.toolBtns) do
        local active = (key == ns.tool.mode)
            or (ns.tool.mode == "M" and key == "M" .. (ns.tool.role or 3))
        b:SetActive(active)
    end
    for i, s in pairs(self.swatches) do
        s.ring:SetShown(i == ns.tool.color)
        s.fill:SetSize(i == ns.tool.color and 22 or 18, i == ns.tool.color and 22 or 18)
    end
    -- mini-barre du mode combat
    if self.mini then
        for mode, b in pairs(self.mini.btns) do
            b:SetActive(mode == ns.tool.mode)
        end
        local c = ns.modules.Board.COLORS[ns.tool.color] or { 1, 1, 1 }
        self.mini.colorBtn.fill:SetColorTexture(c[1], c[2], c[3], 1)
    end
end

-- Les droits vivent dans la colonne « En direct » (Board) — ici, seule
-- la visibilité du bouton Diffuser dépend encore des droits.
function Tools:UpdatePermissionUI()
    if not self.col then return end
    self.bcastBtn:SetShown(ns.CanDraw())
    if self.inviteBtn then self.inviteBtn:SetShown(ns.CanDraw()) end
end
