-- ============================================================================
-- Vamoose's Companion - NerglishGen v2
-- Phoneme-level nerglish (murloc language) generator for Murgle.
-- Based on canonical vocabulary from the Traveler novels, Hearthstone,
-- and HotS Murky dialogue. Core phoneme set: m-r-g-l with gemination,
-- reduplication, and vowel-sparse syllable assembly.
-- ============================================================================

VC = VC or {}
VC.NerglishGen = {}

-- ============================================================================
-- PHONEME TABLES
-- ============================================================================

-- Word-initial consonant clusters, weighted by canonical frequency.
-- Duplicates = higher weight (mr- is overwhelmingly dominant).
local ONSETS = {
    "mr", "mr", "mr", "mrr", "mrrr", "mrggl", "mgl",   -- nasal-rhotic (heavy)
    "fl", "fll", "flll", "gl", "grl",                    -- liquid (medium)
    "ml", "rr", "gr", "bl", "sr",                        -- supporting (light)
}
local ONSETS_N = #ONSETS

-- Optional vowel nuclei (~30% of syllables get one). Weighted toward u.
local NUCLEI = { "u", "u", "u", "a", "a", "uu", "aa" }
local NUCLEI_N = #NUCLEI

-- Word-ending consonant clusters.
local CODAS = {
    "gl", "rgl", "glgl", "rl", "rk", "lm", "gk",
    "lg", "rr", "lgl", "rm", "rgl", "rl", "gl",
}
local CODAS_N = #CODAS

-- Canonical vocabulary from Traveler novels / Blizzard sources.
-- Spliced into sentences at ~30% frequency to anchor generated text.
local ANCHORS = {
    "mrgle",        -- yes / acknowledgement
    "murrgl",       -- (general murloc sound)
    "mrrrggk",      -- magic
    "mrrrgll",      -- sorry
    "mmmurlok",     -- murloc
    "mmmrrglllm",   -- friend
    "mmmrrggllm",   -- aunt
    "mmmrrrggglm",  -- (family term)
    "flllurlog",    -- move / walk
    "fllurlokkr",   -- fisherman
    "mgrrrl",       -- fishing nets
    "mmm",          -- tasty (prefix)
    "mmmm",         -- good (enough)
    "mmmml",        -- right / correct
    "uuua",         -- honor
    "klun",         -- clan
    "furl",         -- feral
    "rwlrwl",       -- (liquid vocalization)
}
local ANCHORS_N = #ANCHORS

-- Sentence-ending exclamations (canonical).
local EXCLAMATIONS = {
    "aaaaaughibbrgubugbugrguburgle",
    "rwlrwlrwlrwl",
    "mrgglglgl",
    "mrglglglgl",
    "mrgllll glrrm gl",
    "blrrg",
    "glrgl",
}
local EXCLAIM_N = #EXCLAMATIONS

-- Short linking connectors (canonical).
local CONNECTORS = { "n", "nk", "skr", "shng", "srng" }
local CONNECTOR_N = #CONNECTORS

-- ============================================================================
-- PHONEME ENGINE
-- ============================================================================

local random = math.random

local function pickFrom(tbl, n)
    return tbl[random(1, n)]
end

-- Build a single syllable: onset + maybe-vowel + coda
local function buildSyllable()
    local syl = pickFrom(ONSETS, ONSETS_N)
    if random(1, 100) <= 30 then
        syl = syl .. pickFrom(NUCLEI, NUCLEI_N)
    end
    syl = syl .. pickFrom(CODAS, CODAS_N)
    return syl
end

-- Apply gemination: double or triple a consonant run (~20% chance)
local function maybeGeminate(word)
    if random(1, 5) ~= 1 then return word end
    -- Pick a random consonant to extend
    local targets = { "rr", "ll", "gg", "mm" }
    local t = targets[random(1, 4)]
    local single = t:sub(1, 1)
    -- Find the consonant and extend it
    local pos = word:find(single, 1, true)
    if pos then
        local extra = random(1, 2)
        word = word:sub(1, pos) .. single:rep(extra) .. word:sub(pos + 1)
    end
    return word
end

-- Apply reduplication: repeat last syllable or whole word (~10% chance)
local function maybeReduplicate(word)
    if random(1, 10) ~= 1 then return word end
    if #word <= 4 then
        return word .. word -- short word: full repeat (mrgl -> mrglmrgl)
    else
        -- Repeat last 3-4 chars
        local tail = word:sub(-random(3, 4))
        return word .. tail
    end
end

-- Generate a single procedural nerglish word (1-2 syllables, capped at 12 chars).
local function buildWord()
    local sylCount = random(1, 2)
    local parts = {}
    for i = 1, sylCount do
        parts[i] = buildSyllable()
    end
    local word = table.concat(parts)
    word = maybeGeminate(word)
    word = maybeReduplicate(word)
    if #word > 12 then word = word:sub(1, 12) end
    return word
end

-- Pick either a generated word (~70%) or a canonical anchor (~30%).
local function nextWord()
    if random(1, 100) <= 30 then
        return pickFrom(ANCHORS, ANCHORS_N)
    end
    return buildWord()
end

local function capitalize(s)
    return s:sub(1, 1):upper() .. s:sub(2)
end

-- ============================================================================
-- SENTENCE TEMPLATES
-- ============================================================================

-- Build a word list of the given count.
local function buildWordList(count)
    local words = {}
    for i = 1, count do
        words[i] = nextWord()
    end
    return words
end

-- Template 1 (60%): Standard sentence
local function tplStandard(minW, maxW)
    local count = random(minW, maxW)
    local words = buildWordList(count)

    -- Connector splice (25% chance, not first/last)
    if count >= 3 and random(1, 4) == 1 then
        local pos = random(2, count - 1)
        table.insert(words, pos, pickFrom(CONNECTORS, CONNECTOR_N))
    end

    -- Random CAPS emphasis (15% chance)
    if random(1, 100) <= 15 then
        local idx = random(1, #words)
        words[idx] = words[idx]:upper()
    end

    -- Exclamation append (20% chance)
    local exclaim = random(1, 5) == 1
    if exclaim then
        words[#words + 1] = pickFrom(EXCLAMATIONS, EXCLAIM_N)
    end

    words[1] = capitalize(words[1])
    local punct = exclaim and "!" or (random(1, 4) == 1 and "?" or ".")
    return table.concat(words, " ") .. punct
end

-- Template 2 (15%): Repeated emphasis (canonical "mrrg mrrg mrrrg" pattern)
local function tplRepeated()
    local base = nextWord()
    local intense = maybeGeminate(base)
    if intense == base then
        intense = base .. base:sub(-random(2, 3))
    end
    return capitalize(base) .. " " .. base .. " " .. intense:upper() .. "!"
end

-- Template 3 (10%): Question
local function tplQuestion(minW, maxW)
    local count = random(math.max(2, minW), maxW)
    local words = buildWordList(count)
    words[1] = capitalize(words[1])
    return table.concat(words, " ") .. "?"
end

-- Template 4 (10%): Exclamation-led
local function tplExclamationLed(minW, maxW)
    local excl = pickFrom(EXCLAMATIONS, EXCLAIM_N)
    local count = random(math.max(2, minW), math.max(3, maxW - 2))
    local words = buildWordList(count)
    words[1] = capitalize(words[1])
    return capitalize(excl) .. "! " .. table.concat(words, " ") .. "."
end

-- Template 5 (5%): Short grunt (1-2 words)
local function tplGrunt()
    local count = random(1, 2)
    local words = buildWordList(count)
    words[1] = capitalize(words[1])
    local punct = random(1, 2) == 1 and "." or "!"
    return table.concat(words, " ") .. punct
end

-- ============================================================================
-- PUBLIC API
-- ============================================================================

-- Generate a single random nerglish word.
function VC.NerglishGen:Word()
    return nextWord()
end

-- Generate a nerglish sentence with structural variety.
-- minWords/maxWords default to 3-8.
function VC.NerglishGen:Sentence(minWords, maxWords)
    minWords = minWords or 3
    maxWords = maxWords or 8

    local roll = random(1, 100)
    -- Repeated/Grunt templates only for short sentences (<=5 words expected)
    local allowShort = maxWords <= 5
    if roll <= 60 then
        return tplStandard(minWords, maxWords)
    elseif roll <= 75 and allowShort then
        return tplRepeated()
    elseif roll <= 85 then
        return tplQuestion(minWords, maxWords)
    elseif roll <= 95 then
        return tplExclamationLed(minWords, maxWords)
    elseif allowShort then
        return tplGrunt()
    else
        return tplStandard(minWords, maxWords)
    end
end

-- Generate N sentences joined with a space.
function VC.NerglishGen:Paragraph(sentenceCount)
    sentenceCount = sentenceCount or 3
    local parts = {}
    for i = 1, sentenceCount do
        parts[i] = self:Sentence()
    end
    return table.concat(parts, " ")
end

-- Generate a Murgle-style quote: "NERGLISH (englishTranslation)"
-- Nerglish length loosely correlates with the translation length.
function VC.NerglishGen:Quote(englishTranslation)
    local wordCount = 0
    for _ in englishTranslation:gmatch("%S+") do
        wordCount = wordCount + 1
    end

    local minW, maxW
    if wordCount <= 5 then
        minW, maxW = 3, 5
    elseif wordCount <= 12 then
        minW, maxW = 5, 9
    else
        minW, maxW = 8, 14
    end

    local nerglish = self:Sentence(minW, maxW)
    nerglish = nerglish:gsub("[%.%?!]$", "")
    return nerglish .. ". (" .. englishTranslation .. ")"
end

-- ============================================================================
-- SCURRY-TO-MURGLE CONVERSION
-- ============================================================================
-- Fills any Murgle category that has no hand-crafted quotes by converting
-- Scurry quotes: generate nerglish as the quote text (pure garbling).
-- Called once at init after all data files are loaded.

function VC.NerglishGen:PopulateMurgleFromScurry()
    if not VC_QuoteDB then return end
    local scurry = VC_QuoteDB.scurry
    if not scurry then return end
    VC_QuoteDB.murgle = VC_QuoteDB.murgle or {}
    local murgle = VC_QuoteDB.murgle

    for cat, quotes in pairs(scurry) do
        if type(quotes) == "table" and (not murgle[cat] or #murgle[cat] == 0) then
            murgle[cat] = {}
            for i, sq in ipairs(quotes) do
                local wc = 0
                for _ in sq.text:gmatch("%S+") do wc = wc + 1 end
                local minW = wc <= 5 and 3 or (wc <= 12 and 5 or 8)
                local maxW = wc <= 5 and 5 or (wc <= 12 and 9 or 14)
                murgle[cat][i] = {
                    id = sq.id:gsub("^s_", "mu_"),
                    text = self:Sentence(minW, maxW),
                    quality = sq.quality,
                    tags = sq.tags,
                }
            end
        end
    end
end

-- ============================================================================
-- SLASH COMMAND INTEGRATION
-- ============================================================================

function VC.NerglishGen:HandleSlash()
    -- Pick a random Scurry quote and generate matching nerglish
    if VC_QuoteDB and VC_QuoteDB.scurry then
        local all = {}
        for _, quotes in pairs(VC_QuoteDB.scurry) do
            if type(quotes) == "table" then
                for _, q in ipairs(quotes) do all[#all + 1] = q.text end
            end
        end
        if #all > 0 then
            local src = all[random(1, #all)]
            local wc = 0
            for _ in src:gmatch("%S+") do wc = wc + 1 end
            local minW = wc <= 5 and 3 or (wc <= 12 and 5 or 8)
            local maxW = wc <= 5 and 5 or (wc <= 12 and 9 or 14)
            print("|cFF00CCFF[Murgle]|r " .. self:Sentence(minW, maxW))
            return
        end
    end
    print("|cFF00CCFF[Murgle]|r " .. self:Sentence())
end
