-- EmoteMenu.lua (core)
-- Core data, persistence, and helpers. UI is in EmoteMenuUI.lua

local ADDON_NAME, EmoteMenu = ...
EmoteMenu = EmoteMenu or {}

-- Fallback data if EmoteMenuDB is not loaded for any reason
local DEFAULT_DATA = {
    categories = {
        { name = "General", emotes = { {cmd="wave",label="Wave"}, {cmd="cheer",label="Cheer"}, {cmd="clap",label="Clap"}, {cmd="dance",label="Dance"}, {cmd="laugh",label="Laugh"}, {cmd="salute",label="Salute"}, {cmd="shrug",label="Shrug"} } },
        { name = "Friendly", emotes = { {cmd="hug",label="Hug"}, {cmd="kiss",label="Kiss"}, {cmd="pat",label="Pat"}, {cmd="comfort",label="Comfort"}, {cmd="welcome",label="Welcome"} } },
        { name = "Expression", emotes = { {cmd="angry",label="Angry"}, {cmd="cry",label="Cry"}, {cmd="frown",label="Frown"}, {cmd="gasp",label="Gasp"}, {cmd="grin",label="Grin"}, {cmd="yawn",label="Yawn"} } },
    }
}

EmoteMenu.DB = EmoteMenuDB or DEFAULT_DATA

-- Favorites (persisted)
EmoteMenu.favorites = EmoteMenu.favorites or {}
EmoteMenu.favoritesSet = EmoteMenu.favoritesSet or {}

function EmoteMenu.LoadFavorites()
    EmoteMenuSaved = EmoteMenuSaved or { favorites = {} }
    EmoteMenu.favorites = EmoteMenuSaved.favorites or {}
    EmoteMenu.favoritesSet = {}
    for _, cmd in ipairs(EmoteMenu.favorites) do EmoteMenu.favoritesSet[cmd] = true end
end

function EmoteMenu.SaveFavorites()
    EmoteMenuSaved = EmoteMenuSaved or {}
    local seen, out = {}, {}
    for _, cmd in ipairs(EmoteMenu.favorites or {}) do
        if not seen[cmd] then table.insert(out, cmd); seen[cmd] = true end
    end
    EmoteMenuSaved.favorites = out
    EmoteMenu.favorites = out
    EmoteMenu.favoritesSet = {}
    for _, cmd in ipairs(out) do EmoteMenu.favoritesSet[cmd] = true end
end

-- Hidden (persisted)
EmoteMenu.hidden = EmoteMenu.hidden or {}
EmoteMenu.hiddenSet = EmoteMenu.hiddenSet or {}

function EmoteMenu.LoadHidden()
    EmoteMenuSaved = EmoteMenuSaved or {}
    EmoteMenu.hidden = EmoteMenuSaved.hidden or {}
    EmoteMenu.hiddenSet = {}
    for _, cmd in ipairs(EmoteMenu.hidden) do EmoteMenu.hiddenSet[cmd] = true end
end

function EmoteMenu.SaveHidden()
    EmoteMenuSaved = EmoteMenuSaved or {}
    local seen, out = {}, {}
    for _, cmd in ipairs(EmoteMenu.hidden) do
        if not seen[cmd] then table.insert(out, cmd); seen[cmd] = true end
    end
    EmoteMenuSaved.hidden = out
    EmoteMenu.hidden = out
    EmoteMenu.hiddenSet = {}
    for _, cmd in ipairs(out) do EmoteMenu.hiddenSet[cmd] = true end
end

-- Per-category order (persisted)
EmoteMenu.catOrder = EmoteMenu.catOrder or {}

function EmoteMenu.LoadOrder()
    EmoteMenuSaved = EmoteMenuSaved or {}
    EmoteMenu.catOrder = EmoteMenuSaved.order or {}
end

function EmoteMenu.SaveOrder()
    EmoteMenuSaved = EmoteMenuSaved or {}
    EmoteMenuSaved.order = EmoteMenu.catOrder
end

function EmoteMenu.SaveOrderForCategory(catName, cat)
    if not catName or not cat or not cat.emotes then return end
    local list = {}
    for _, e in ipairs(cat.emotes) do if e.cmd then table.insert(list, e.cmd) end end
    EmoteMenu.catOrder[catName] = list
    EmoteMenu.SaveOrder()
end

function EmoteMenu.ApplyOrderToCategory(cat)
    if not cat or not cat.emotes or not cat.name then return end
    local order = EmoteMenu.catOrder[cat.name]
    if not order or #order == 0 then return end
    local idxMap = {}
    for i, cmd in ipairs(order) do idxMap[cmd] = i end
    local origIndex = {}
    for i, e in ipairs(cat.emotes) do origIndex[e] = i end
    table.sort(cat.emotes, function(a, b)
        local ia = idxMap[a.cmd]
        local ib = idxMap[b.cmd]
        if ia and ib then return ia < ib end
        if ia and not ib then return true end
        if not ia and ib then return false end
        return origIndex[a] < origIndex[b]
    end)
end

function EmoteMenu.ApplyOrderToAllCategories()
    for _, cat in ipairs(EmoteMenu.DB.categories or {}) do
        EmoteMenu.ApplyOrderToCategory(cat)
    end
end

-- Utility to run an emote command safely
function EmoteMenu.RunEmote(cmd)
    if not cmd or cmd == "" then return end
    if DoEmote then
        DoEmote(cmd)
    else
        RunMacroText("/" .. cmd)
    end
end

-- Build an "Other" category from EmoteMenuAll global (if present)
EmoteMenu.otherCategoryIndex = EmoteMenu.otherCategoryIndex or nil
function EmoteMenu.BuildOtherCategory()
    if not EmoteMenuAll or not EmoteMenuAll.emotes then return end
    local DB = EmoteMenu.DB
    local present = {}
    for _, cat in ipairs(DB.categories or {}) do
        for _, e in ipairs(cat.emotes or {}) do
            present[e.cmd] = true
        end
    end
    local others = {}
    for _, e in ipairs(EmoteMenuAll.emotes) do
        if e.cmd and not present[e.cmd] then table.insert(others, e) end
    end
    if EmoteMenu.otherCategoryIndex and DB.categories[EmoteMenu.otherCategoryIndex] then
        DB.categories[EmoteMenu.otherCategoryIndex].name = "Other"
        DB.categories[EmoteMenu.otherCategoryIndex].emotes = others
    else
        table.insert(DB.categories, { name = "Other", emotes = others })
        EmoteMenu.otherCategoryIndex = #DB.categories
    end
end
