-- DeathSound - DeathSound.lua
-- WoW Midnight 12.0.5

local ADDON_NAME     = "DeathSound"
local SOUND_PATH     = "Interface\\AddOns\\DeathSound\\Sounds\\"
local PREFIX         = "|cff00ccff[DeathSound]|r "
local DROPDOWN_WIDTH = 160
local TESTBTN_OFFSET = 220

local DEFAULTS = {
    enabled      = true,
    gameSoundID  = "",
    randomSound  = false,
    soundName    = "",   -- gespeicherter Name des gewaehlten Sounds
    useGameSound = false,
}

local function L(key) return DeathSoundLocale[key] end

-- Modul-State
local currentSoundHandle = nil
local dropdownRef        = nil

-- ============================================================
-- Core
-- ============================================================

-- Gibt den Index des gespeicherten Namens in der Liste zurueck (Fallback: 1)
local function ResolveSoundIndex()
    local db   = DeathSoundDB
    local list = DEATHSOUND_SOUND_LIST or {}
    if db.soundName and db.soundName ~= "" then
        for i, entry in ipairs(list) do
            if entry.name == db.soundName then return i end
        end
    end
    return 1
end

local function StopCurrentSound()
    if currentSoundHandle then
        StopSound(currentSoundHandle)
        currentSoundHandle = nil
    end
end

local function PlaySelectedSound(force)
    if not force and not DeathSoundDB.enabled then return end

    local db = DeathSoundDB

    if db.useGameSound then
        local id = tonumber(db.gameSoundID)
        if not id or id <= 0 then
            print(PREFIX .. L("MSG_INVALID_ID"))
            return
        end
        StopCurrentSound()
        local ok, handle = PlaySound(id, "Master")
        if ok then
            currentSoundHandle = handle
        else
            print(PREFIX .. L("MSG_ID_ERROR") .. tostring(id))
        end
        return
    end

    local list = DEATHSOUND_SOUND_LIST
    if not list or #list == 0 then
        print(PREFIX .. L("MSG_NO_SOUNDS"))
        return
    end

    local idx
    if db.randomSound and #list > 1 then
        local curIdx = ResolveSoundIndex()
        repeat idx = math.random(1, #list) until idx ~= curIdx
        db.soundName = list[idx].name
        if dropdownRef then
            UIDropDownMenu_SetText(dropdownRef, list[idx].name)
        end
    else
        idx = ResolveSoundIndex()
    end

    StopCurrentSound()
    local ok, handle = PlaySoundFile(SOUND_PATH .. list[idx].file, "Master")
    if ok then
        currentSoundHandle = handle
    else
        print(PREFIX .. L("MSG_FILE_ERROR") .. SOUND_PATH .. list[idx].file)
        print(PREFIX .. L("MSG_FILE_HINT"))
    end
end

-- ============================================================
-- Events
-- ============================================================

local buildOptionsPanel
local frame  = CreateFrame("Frame")
local isDead = false

frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("PLAYER_DEAD")
frame:RegisterEvent("PLAYER_ALIVE")
frame:RegisterEvent("PLAYER_UNGHOST")

frame:SetScript("OnEvent", function(self, event, arg1)
    if event == "ADDON_LOADED" and arg1 == ADDON_NAME then
        if type(DeathSoundDB) ~= "table" then DeathSoundDB = {} end
        for k, v in pairs(DEFAULTS) do
            if DeathSoundDB[k] == nil then DeathSoundDB[k] = v end
        end
        -- Migration: alter soundIndex -> soundName
        local list = DEATHSOUND_SOUND_LIST or {}
        if (DeathSoundDB.soundName == "" or DeathSoundDB.soundName == nil) then
            local oldIdx = DeathSoundDB.soundIndex
            if oldIdx and list[oldIdx] then
                DeathSoundDB.soundName = list[oldIdx].name
            elseif list[1] then
                DeathSoundDB.soundName = list[1].name
            end
        end
        DeathSoundDB.soundIndex = nil  -- alten Key aufraeumen
        buildOptionsPanel()
        self:UnregisterEvent("ADDON_LOADED")

    elseif event == "PLAYER_DEAD" then
        if not isDead then
            isDead = true
            PlaySelectedSound()
        end

    elseif event == "PLAYER_ALIVE" or event == "PLAYER_UNGHOST" then
        isDead = false
    end
end)

-- ============================================================
-- Options Panel
-- ============================================================

buildOptionsPanel = function()
    local db = DeathSoundDB

    local panel = CreateFrame("Frame")
    panel.name  = ADDON_NAME

    -- ---- Titel ----
    local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 16, -16)
    title:SetText("|cff00ccff" .. L("ADDON_TITLE") .. "|r")

    local subtitle = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -4)
    subtitle:SetText(L("ADDON_SUBTITLE"))

    local sep = panel:CreateTexture(nil, "ARTWORK")
    sep:SetColorTexture(0.3, 0.3, 0.3, 0.8)
    sep:SetSize(560, 1)
    sep:SetPoint("TOPLEFT", subtitle, "BOTTOMLEFT", 0, -12)

    -- ---- Haupt-Checkbox ----
    local cb = CreateFrame("CheckButton", "DeathSoundEnabledCB", panel, "InterfaceOptionsCheckButtonTemplate")
    cb:SetPoint("TOPLEFT", sep, "BOTTOMLEFT", 0, -16)
    cb.Text:SetText(L("OPT_ENABLE"))
    cb:SetChecked(db.enabled)
    cb:SetScript("OnClick", function(self) db.enabled = self:GetChecked() end)
    cb:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L("OPT_ENABLE_TOOLTIP"), 1, 1, 1)
        GameTooltip:Show()
    end)
    cb:SetScript("OnLeave", function() GameTooltip:Hide() end)

    -- ---- Kombinierter Info-Text (Sounds + Bilder) ----
    local infoSounds = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    infoSounds:SetPoint("TOPLEFT", cb, "BOTTOMLEFT", 4, -14)
    infoSounds:SetJustifyH("LEFT")
    infoSounds:SetWidth(540)
    infoSounds:SetText("|cff888888" .. L("OPT_INFO_PATH") .. "  |cffffffff" .. L("OPT_INFO_PATH_VALUE"))

    local infoImages = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    infoImages:SetPoint("TOPLEFT", infoSounds, "BOTTOMLEFT", 0, -4)
    infoImages:SetJustifyH("LEFT")
    infoImages:SetWidth(540)
    infoImages:SetText("|cff888888" .. L("OPT_INFO_PATH_IMG") .. "  |cffffffff" .. L("OPT_INFO_PATH_VALUE_IMG"))

    local infoReg = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    infoReg:SetPoint("TOPLEFT", infoImages, "BOTTOMLEFT", 0, -4)
    infoReg:SetJustifyH("LEFT")
    infoReg:SetWidth(540)
    infoReg:SetText("|cff888888" .. L("OPT_INFO_REGISTER_COMBINED"))

    -- ============================================================
    -- Tab-Buttons
    -- ============================================================
    local tabSound = CreateFrame("Button", "DeathSoundTabSound", panel, "UIPanelButtonTemplate")
    tabSound:SetSize(120, 28)
    tabSound:SetPoint("TOPLEFT", infoReg, "BOTTOMLEFT", -4, -14)
    tabSound:SetText(L("TAB_SOUND"))

    local tabImage = CreateFrame("Button", "DeathSoundTabImage", panel, "UIPanelButtonTemplate")
    tabImage:SetSize(120, 28)
    tabImage:SetPoint("LEFT", tabSound, "RIGHT", 6, 0)
    tabImage:SetText(L("TAB_IMAGE"))

    local tabGroup = CreateFrame("Button", "DeathSoundTabGroup", panel, "UIPanelButtonTemplate")
    tabGroup:SetSize(120, 28)
    tabGroup:SetPoint("LEFT", tabImage, "RIGHT", 6, 0)
    tabGroup:SetText(L("TAB_GROUP"))

    -- Tab-Separator
    local tabSep = panel:CreateTexture(nil, "ARTWORK")
    tabSep:SetColorTexture(0.25, 0.25, 0.25, 0.6)
    tabSep:SetSize(560, 1)
    tabSep:SetPoint("TOPLEFT", tabSound, "BOTTOMLEFT", 0, -8)

    -- ============================================================
    -- Content-Frame: Sound
    -- ============================================================
    local soundFrame = CreateFrame("Frame", nil, panel)
    soundFrame:SetPoint("TOPLEFT", tabSep, "BOTTOMLEFT", 0, -8)
    soundFrame:SetSize(560, 400)

    local fileCB = CreateFrame("CheckButton", "DeathSoundFileCB", soundFrame, "InterfaceOptionsCheckButtonTemplate")
    fileCB:SetPoint("TOPLEFT", soundFrame, "TOPLEFT", 0, 0)
    fileCB.Text:SetText(L("OPT_USE_FILE"))
    fileCB:SetChecked(not db.useGameSound)

    local ddLabel = soundFrame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    ddLabel:SetPoint("TOPLEFT", fileCB, "BOTTOMLEFT", 4, -8)
    ddLabel:SetText(L("OPT_SELECT_SOUND"))

    local dd = CreateFrame("Frame", "DeathSoundDropdown", soundFrame, "UIDropDownMenuTemplate")
    dd:SetPoint("TOPLEFT", ddLabel, "BOTTOMLEFT", -15, -4)
    UIDropDownMenu_SetWidth(dd, DROPDOWN_WIDTH)
    dropdownRef = dd

    if dd.Text then
        dd.Text:ClearAllPoints()
        dd.Text:SetPoint("LEFT",  dd, "LEFT",  22, 2)
        dd.Text:SetPoint("RIGHT", dd, "RIGHT", -30, 2)
        dd.Text:SetJustifyH("LEFT")
    end

    local function RefreshDropdown()
        local currentList = DEATHSOUND_SOUND_LIST or {}
        local idx = ResolveSoundIndex()
        UIDropDownMenu_SetText(dd, currentList[idx] and currentList[idx].name or "---")
    end

    UIDropDownMenu_Initialize(dd, function()
        local currentList = DEATHSOUND_SOUND_LIST or {}
        if #currentList == 0 then
            local info    = UIDropDownMenu_CreateInfo()
            info.text     = L("DD_NO_SOUNDS")
            info.disabled = true
            UIDropDownMenu_AddButton(info)
            return
        end
        for i, entry in ipairs(currentList) do
            local info        = UIDropDownMenu_CreateInfo()
            info.text         = (entry.name == db.soundName) and ("|cffffd700" .. entry.name .. "|r") or entry.name
            info.value        = i
            info.notCheckable = true
            info.func         = function()
                db.soundName = entry.name
                RefreshDropdown()
                CloseDropDownMenus()
            end
            UIDropDownMenu_AddButton(info)
        end
    end)

    RefreshDropdown()

    local ddOverlay = CreateFrame("Button", "DeathSoundDropdownOverlay", dd)
    ddOverlay:SetPoint("TOPLEFT",     dd, "TOPLEFT",     15, -5)
    ddOverlay:SetPoint("BOTTOMRIGHT", dd, "BOTTOMRIGHT", -5,  5)
    ddOverlay:SetFrameLevel(dd:GetFrameLevel() + 2)
    ddOverlay:SetScript("OnClick", function()
        ToggleDropDownMenu(1, nil, dd, dd, 0, 0)
    end)

    local testFileBtn = CreateFrame("Button", "DeathSoundTestButton", soundFrame, "UIPanelButtonTemplate")
    testFileBtn:SetSize(120, 26)
    testFileBtn:SetPoint("TOPLEFT", ddLabel, "BOTTOMLEFT", TESTBTN_OFFSET, -6)
    testFileBtn:SetText(L("OPT_TEST_BUTTON"))
    testFileBtn:SetScript("OnClick", function() PlaySelectedSound(true) end)
    testFileBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L("OPT_TEST_TOOLTIP"), 1, 1, 1)
        GameTooltip:Show()
    end)
    testFileBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    local UpdateModeUI  -- forward declaration

    local randomCB = CreateFrame("CheckButton", "DeathSoundRandomCB", soundFrame, "InterfaceOptionsCheckButtonTemplate")
    randomCB:SetPoint("LEFT", testFileBtn, "RIGHT", 12, 0)
    randomCB.Text:SetText(L("OPT_RANDOM"))
    randomCB:SetChecked(db.randomSound)
    randomCB:SetScript("OnClick", function(self)
        db.randomSound = self:GetChecked()
        UpdateModeUI()
    end)
    randomCB:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L("OPT_RANDOM_TOOLTIP"), 1, 1, 1)
        GameTooltip:Show()
    end)
    randomCB:SetScript("OnLeave", function() GameTooltip:Hide() end)

    local idCB = CreateFrame("CheckButton", "DeathSoundIDCB", soundFrame, "InterfaceOptionsCheckButtonTemplate")
    idCB:SetPoint("TOPLEFT", fileCB, "BOTTOMLEFT", 0, -70)
    idCB.Text:SetText(L("OPT_USE_ID"))
    idCB:SetChecked(db.useGameSound)

    local idLabel = soundFrame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    idLabel:SetPoint("TOPLEFT", idCB, "BOTTOMLEFT", 0, -10)
    idLabel:SetText(L("OPT_ID_LABEL"))

    local idBox = CreateFrame("EditBox", "DeathSoundIDBox", soundFrame, "InputBoxTemplate")
    idBox:SetSize(120, 26)
    idBox:SetPoint("TOPLEFT", idLabel, "BOTTOMLEFT", 0, -6)
    idBox:SetAutoFocus(false)
    idBox:SetNumeric(true)
    idBox:SetMaxLetters(10)
    idBox:SetText(db.gameSoundID or "")
    local idSnapshot = db.gameSoundID or ""
    idBox:SetScript("OnEditFocusGained", function() idSnapshot = db.gameSoundID or "" end)
    idBox:SetScript("OnTextChanged",     function(self) db.gameSoundID = self:GetText() end)
    idBox:SetScript("OnEnterPressed",    function(self) self:ClearFocus() end)
    idBox:SetScript("OnEscapePressed",   function(self)
        db.gameSoundID = idSnapshot
        self:SetText(idSnapshot)
        self:ClearFocus()
    end)

    panel:SetScript("OnHide", function()
        db.gameSoundID = idBox:GetText()
    end)

    local testIDBtn = CreateFrame("Button", "DeathSoundTestIDButton", soundFrame, "UIPanelButtonTemplate")
    testIDBtn:SetSize(120, 26)
    testIDBtn:SetPoint("LEFT", idBox, "RIGHT", 10, 0)
    testIDBtn:SetText(L("OPT_TEST_BUTTON"))
    testIDBtn:SetScript("OnClick", function()
        local id = tonumber(idBox:GetText())
        if not id or id <= 0 then
            print(PREFIX .. L("MSG_INVALID_ID"))
            return
        end
        StopCurrentSound()
        local ok, handle = PlaySound(id, "Master")
        if ok then currentSoundHandle = handle end
    end)
    testIDBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L("OPT_TEST_TOOLTIP"), 1, 1, 1)
        GameTooltip:Show()
    end)
    testIDBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)

    UpdateModeUI = function()
        local useID     = db.useGameSound
        local useRandom = db.randomSound
        local fileDimmed = useID
        local ddDimmed   = useID or useRandom

        ddLabel:SetAlpha(fileDimmed and 0.4 or 1)
        dd:SetAlpha(ddDimmed and 0.4 or 1)
        ddOverlay:EnableMouse(not ddDimmed)
        testFileBtn:SetEnabled(not fileDimmed)
        randomCB:SetEnabled(not fileDimmed)
        randomCB:SetAlpha(fileDimmed and 0.4 or 1)

        local idAlpha = useID and 1 or 0.4
        idBox:SetEnabled(useID)
        idBox:SetAlpha(idAlpha)
        idLabel:SetAlpha(idAlpha)
        testIDBtn:SetEnabled(useID)

        fileCB:SetChecked(not useID)
        idCB:SetChecked(useID)
    end

    fileCB:SetScript("OnClick", function()
        db.useGameSound = false
        UpdateModeUI()
    end)

    idCB:SetScript("OnClick", function()
        db.useGameSound = true
        UpdateModeUI()
    end)

    UpdateModeUI()

    -- ============================================================
    -- Content-Frame: Image
    -- ============================================================
    local imageFrame = CreateFrame("Frame", "DeathSoundImageFrame", panel)
    imageFrame:SetPoint("TOPLEFT", tabSep, "BOTTOMLEFT", 0, -8)
    imageFrame:SetSize(560, 400)
    imageFrame:Hide()

    if DeathSound_BuildOverlaySection then
        DeathSound_BuildOverlaySection(imageFrame)
    end

    -- ============================================================
    -- Content-Frame: Group
    -- ============================================================
    local groupFrame = CreateFrame("Frame", "DeathSoundGroupFrame", panel)
    groupFrame:SetPoint("TOPLEFT", tabSep, "BOTTOMLEFT", 0, -8)
    groupFrame:SetSize(560, 400)
    groupFrame:Hide()

    if DeathSound_BuildPartySection then
        DeathSound_BuildPartySection(groupFrame)
    end

    -- ============================================================
    -- Tab-Switch Logik
    -- ============================================================
    local function SetTab(active)
        soundFrame:SetShown(active == "sound")
        imageFrame:SetShown(active == "image")
        groupFrame:SetShown(active == "group")

        tabSound:SetText(active == "sound" and "|cff00ccff" .. L("TAB_SOUND") .. "|r" or "|cff888888" .. L("TAB_SOUND") .. "|r")
        tabImage:SetText(active == "image" and "|cff00ccff" .. L("TAB_IMAGE") .. "|r" or "|cff888888" .. L("TAB_IMAGE") .. "|r")
        tabGroup:SetText(active == "group" and "|cff00ccff" .. L("TAB_GROUP") .. "|r" or "|cff888888" .. L("TAB_GROUP") .. "|r")
    end

    tabSound:SetScript("OnClick", function() SetTab("sound") end)
    tabImage:SetScript("OnClick", function() SetTab("image") end)
    tabGroup:SetScript("OnClick", function() SetTab("group") end)

    SetTab("sound")  -- Sound-Tab standardmaessig aktiv

    -- Panel registrieren
    local category = Settings.RegisterCanvasLayoutCategory(panel, ADDON_NAME)
    Settings.RegisterAddOnCategory(category)
    panel.category = category
    DeathSound_OptionsPanel = panel
end

-- ============================================================
-- Slash Commands
-- ============================================================

SLASH_DEATHSOUND1 = "/deathsound"
SLASH_DEATHSOUND2 = "/ds"

SlashCmdList["DEATHSOUND"] = function(msg)
    msg = strtrim(msg or ""):lower()

    if msg == "test" then
        PlaySelectedSound(true)

    elseif msg == "on" then
        DeathSoundDB.enabled = true
        print(PREFIX .. L("MSG_ENABLED"))

    elseif msg == "off" then
        DeathSoundDB.enabled = false
        print(PREFIX .. L("MSG_DISABLED"))

    else
        if DeathSound_OptionsPanel and DeathSound_OptionsPanel.category then
            Settings.OpenToCategory(DeathSound_OptionsPanel.category:GetID())
        else
            print(PREFIX .. L("MSG_HELP"))
            print(L("MSG_HELP_OPEN"))
            print(L("MSG_HELP_TEST"))
            print(L("MSG_HELP_ON"))
            print(L("MSG_HELP_OFF"))
        end
    end
end
