local NS = rawget(_G, "MCDVoiceCooldownNS") or {}
_G.MCDVoiceCooldownNS = NS

NS.UI = NS.UI or {}
NS.UI.MainFrame = NS.UI.MainFrame or {}

local MainFrame = NS.UI.MainFrame
local Widgets = NS.UI.Widgets
local Skin = NS.UI.Skin
local L = NS.L or function(key, ...) if select("#", ...) > 0 then return string.format(tostring(key), ...) end return tostring(key) end

function MainFrame:EnsureFrame()
    if self.frame then
        return self.frame
    end

    local frame = CreateFrame("Frame", "MCDVoiceCooldownMainFrame", UIParent, "BackdropTemplate")
    frame:SetSize(1040, 700)
    frame:SetPoint("CENTER")
    frame:SetFrameStrata("DIALOG")
    frame:EnableMouse(true)
    frame:SetMovable(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetScript("OnDragStart", frame.StartMoving)
    frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
    frame:SetClampedToScreen(true)
    frame:Hide()
    Widgets:ApplyPanelChrome(frame, { footerHeight = 50 })
    tinsert(UISpecialFrames, frame:GetName())

    local header = CreateFrame("Frame", nil, frame)
    header:SetSize(420, 40)
    header:SetPoint("TOP", frame, "TOP", 0, -10)

    local logo = header:CreateTexture(nil, "ARTWORK")
    logo:SetSize(34, 34)
    logo:SetPoint("LEFT", header, "LEFT", 0, -1)
    logo:SetTexture(NS.ADDON_ICON or "Interface\\AddOns\\MCDVoiceCooldown\\AppIcon.png")
    logo:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    local title = Widgets:CreateLabel(header, NS.ADDON_DISPLAY_NAME or L("ADDON_DISPLAY_NAME"), "GameFontNormalLarge")
    title:SetPoint("LEFT", logo, "RIGHT", 10, 0)
    title:SetJustifyH("LEFT")
    if Skin then
        Skin:StyleFont(title, "title")
    end

    local function LayoutHeader()
        local titleWidth = 360
        if title.GetStringWidth then
            titleWidth = math.min(math.max((title:GetStringWidth() or 0) + 6, 180), 540)
        end
        title:SetWidth(titleWidth)
        header:SetWidth(34 + 10 + titleWidth)
    end
    LayoutHeader()
    frame:HookScript("OnShow", LayoutHeader)

    local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
    close:SetSize(28, 28)
    close:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -10, -10)
    if Skin and Skin.SkinCloseButton then
        Skin:SkinCloseButton(close)
    end
    close:SetScript("OnClick", function()
        self:Close()
    end)

    local summary = Widgets:CreateLabel(frame, "", "GameFontHighlight")
    summary:SetPoint("TOPLEFT", frame, "TOPLEFT", 24, -62)
    summary:SetPoint("RIGHT", frame, "RIGHT", -22, 0)
    if Skin then
        Skin:StyleFont(summary, "muted")
    end

    local addBtn = Widgets:CreateButton(frame, L("BTN_ADD_VOICE"), 112, 32)
    addBtn:SetPoint("TOPLEFT", summary, "BOTTOMLEFT", 0, -16)

    local addGroupBtn = Widgets:CreateButton(frame, L("BTN_ADD_COLLECTION"), 112, 32)
    addGroupBtn:SetPoint("LEFT", addBtn, "RIGHT", 8, 0)

    local editBtn = Widgets:CreateButton(frame, L("BTN_EDIT"), 104, 32)
    editBtn:SetPoint("LEFT", addGroupBtn, "RIGHT", 8, 0)

    local deleteBtn = Widgets:CreateButton(frame, L("BTN_DELETE"), 104, 32)
    deleteBtn:SetPoint("LEFT", editBtn, "RIGHT", 8, 0)

    local refreshBtn = Widgets:CreateButton(frame, L("BTN_REFRESH"), 104, 32)
    refreshBtn:SetPoint("LEFT", deleteBtn, "RIGHT", 8, 0)

    local importBtn = Widgets:CreateButton(frame, L("BTN_IMPORT"), 104, 32)
    importBtn:SetPoint("LEFT", refreshBtn, "RIGHT", 8, 0)

    local exportAllBtn = Widgets:CreateButton(frame, L("BTN_EXPORT_FULL"), 112, 32)
    exportAllBtn:SetPoint("LEFT", importBtn, "RIGHT", 8, 0)

    local listHost = CreateFrame("Frame", nil, frame, "BackdropTemplate")
    listHost:SetPoint("TOPLEFT", addBtn, "BOTTOMLEFT", 0, -18)
    listHost:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -24, 24)
    Widgets:ApplyPanelChrome(listHost, { inset = true, noFooter = true, topHeight = 20 })

    local savedList = NS.UI.SavedList:Create(listHost)

    addBtn:SetScript("OnClick", function()
        NS.UI.EditorFrame:OpenForNew()
    end)
    addGroupBtn:SetScript("OnClick", function()
        self:OpenCollectionNameDialog()
    end)
    editBtn:SetScript("OnClick", function()
        local selectedKey = tostring(NS.AceOptions:GetState().selectedKey or "")
        if NS.AceOptions and type(NS.AceOptions.IsGroupKey) == "function" and NS.AceOptions:IsGroupKey(selectedKey) then
            self:OpenRenameCollectionDialog(selectedKey)
        else
            NS.UI.EditorFrame:OpenForEdit()
        end
    end)
    deleteBtn:SetScript("OnClick", function()
        local selectedKey = tostring(NS.AceOptions:GetState().selectedKey or "")
        if NS.AceOptions and type(NS.AceOptions.IsGroupKey) == "function" and NS.AceOptions:IsGroupKey(selectedKey) then
            NS.AceOptions:DeleteCollection(selectedKey)
        else
            NS.AceOptions:DeleteSelectedEntry()
        end
        self:Refresh()
    end)
    refreshBtn:SetScript("OnClick", function()
        self:Refresh()
    end)
    importBtn:SetScript("OnClick", function()
        self:OpenImportDialog()
    end)
    exportAllBtn:SetScript("OnClick", function()
        if NS.AceOptions and type(NS.AceOptions.ExportFullString) == "function" then
            self:OpenExportDialog(L("EXPORT_FULL_TITLE"), NS.AceOptions:ExportFullString())
        end
    end)

    savedList:SetOnSelectionChanged(function(key, entryType)
        local state = NS.AceOptions:GetState()
        state.selectedKey = key
        state.entryType = entryType or state.entryType or "cooldown"
        -- 选择普通条目时，必须清除当前选中的合集。
        -- 否则先点过合集后，再点普通条目，后续“新增语音”仍会错误创建到旧合集内。
        if not (NS.AceOptions and type(NS.AceOptions.IsGroupKey) == "function" and NS.AceOptions:IsGroupKey(key)) then
            state.selectedCollectionKey = nil
        end
        NS.AceOptions:LoadSelectedEntry()
        self:Refresh()
    end)

    self.frame = frame
    self.summary = summary
    self.addBtn = addBtn
    self.addGroupBtn = addGroupBtn
    self.editBtn = editBtn
    self.deleteBtn = deleteBtn
    self.refreshBtn = refreshBtn
    self.importBtn = importBtn
    self.exportAllBtn = exportAllBtn
    self.savedList = savedList
    return frame
end


function MainFrame:EnsureCollectionDialog()
    if self.collectionDialog then
        return self.collectionDialog
    end

    local parent = self:EnsureFrame()
    local dialog = CreateFrame("Frame", "MCDVoiceCooldownCollectionNameDialog", parent, "BackdropTemplate")
    dialog:SetSize(660, 420)
    dialog:SetPoint("CENTER", parent, "CENTER", 0, 18)
    dialog:SetFrameStrata("FULLSCREEN_DIALOG")
    dialog:SetToplevel(true)
    dialog:EnableMouse(true)
    dialog:Hide()
    Widgets:ApplyPanelChrome(dialog, { footerHeight = 58 })

    local title = Widgets:CreateLabel(dialog, L("TITLE_ADD_COLLECTION"), "GameFontNormalLarge")
    title:SetPoint("TOP", dialog, "TOP", 0, -18)
    title:SetWidth(460)
    title:SetJustifyH("CENTER")
    if Skin then
        Skin:StyleFont(title, "title")
    end

    local nameLabel = Widgets:CreateLabel(dialog, L("COLLECTION_NAME"), "GameFontNormal")
    nameLabel:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -70)
    if Skin then
        Skin:StyleFont(nameLabel, "accent")
    end

    local editBox = Widgets:CreateEditBox(dialog, 592, 32, false)
    editBox:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -98)

    local iconLabel = Widgets:CreateLabel(dialog, L("COLLECTION_ICON_ID"), "GameFontNormal")
    iconLabel:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -150)
    if Skin then
        Skin:StyleFont(iconLabel, "accent")
    end

    local iconEditBox = Widgets:CreateEditBox(dialog, 210, 32, true)
    iconEditBox:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -176)

    local iconPreviewBorder = CreateFrame("Frame", nil, dialog, "BackdropTemplate")
    iconPreviewBorder:SetSize(42, 42)
    iconPreviewBorder:SetPoint("LEFT", iconEditBox, "RIGHT", 14, 0)
    if Skin and Skin.ApplyWindowChrome then
        Skin:ApplyWindowChrome(iconPreviewBorder, { inset = true, noFooter = true, noTopLine = true, topHeight = 0 })
    end

    local iconPreview = iconPreviewBorder:CreateTexture(nil, "ARTWORK")
    iconPreview:SetSize(32, 32)
    iconPreview:SetPoint("CENTER", iconPreviewBorder, "CENTER", 0, 0)
    iconPreview:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    local iconHint = Widgets:CreateLabel(dialog, L("COLLECTION_ICON_HINT"), "GameFontHighlightSmall")
    iconHint:SetPoint("LEFT", iconPreviewBorder, "RIGHT", 12, 0)
    iconHint:SetPoint("RIGHT", dialog, "RIGHT", -34, 0)
    iconHint:SetHeight(42)
    iconHint:SetJustifyH("LEFT")
    iconHint:SetJustifyV("MIDDLE")
    if iconHint.SetWordWrap then
        iconHint:SetWordWrap(true)
    end
    if Skin then
        Skin:StyleFont(iconHint, "muted")
    end

    local hint = Widgets:CreateLabel(dialog, L("COLLECTION_HINT"), "GameFontHighlightSmall")
    hint:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -258)
    hint:SetPoint("RIGHT", dialog, "RIGHT", -34, 0)
    hint:SetHeight(56)
    hint:SetJustifyH("LEFT")
    hint:SetJustifyV("TOP")
    if hint.SetWordWrap then
        hint:SetWordWrap(true)
    end
    if Skin then
        Skin:StyleFont(hint, "muted")
    end

    local save = Widgets:CreateButton(dialog, L("BTN_CREATE"), 118, 32)
    save:SetPoint("BOTTOMLEFT", dialog, "BOTTOMLEFT", 34, 20)

    local cancel = Widgets:CreateButton(dialog, L("BTN_CANCEL"), 118, 32)
    cancel:SetPoint("LEFT", save, "RIGHT", 10, 0)

    local function UpdateIconPreview()
        local texture = NS.AceOptions:ResolveCollectionIcon(iconEditBox:GetText())
        iconPreview:SetTexture(texture)
    end

    local function SubmitCollectionDialog()
        local name = tostring(editBox:GetText() or "")
        local iconID = tostring(iconEditBox:GetText() or "")
        local ok = false
        if dialog.mode == "rename" then
            ok = NS.AceOptions:RenameCollection(dialog.groupKey, name, iconID)
        else
            if dialog.parentGroupKey and NS.AceOptions and type(NS.AceOptions.GetState) == "function" then
                local state = NS.AceOptions:GetState()
                state.selectedCollectionKey = tostring(dialog.parentGroupKey or "")
                if tostring(dialog.parentGroupKey or "") ~= "" then
                    state.selectedKey = tostring(dialog.parentGroupKey or "")
                end
            end
            ok = NS.AceOptions:CreateCollection(name, iconID, dialog.parentGroupKey)
        end
        if ok then
            dialog:Hide()
            dialog.mode = "create"
            dialog.groupKey = nil
            dialog.parentGroupKey = nil
            self:Refresh()
        end
    end

    save:SetScript("OnClick", SubmitCollectionDialog)
    cancel:SetScript("OnClick", function()
        dialog:Hide()
    end)
    editBox:SetScript("OnEnterPressed", function(box)
        box:ClearFocus()
        SubmitCollectionDialog()
    end)
    iconEditBox:SetScript("OnTextChanged", UpdateIconPreview)
    iconEditBox:SetScript("OnEnterPressed", function(box)
        box:ClearFocus()
        SubmitCollectionDialog()
    end)
    editBox:SetScript("OnEscapePressed", function(box)
        box:ClearFocus()
        dialog:Hide()
    end)
    iconEditBox:SetScript("OnEscapePressed", function(box)
        box:ClearFocus()
        dialog:Hide()
    end)

    dialog.title = title
    dialog.saveButton = save
    dialog.editBox = editBox
    dialog.iconEditBox = iconEditBox
    dialog.UpdateIconPreview = UpdateIconPreview
    dialog.mode = "create"
    dialog.groupKey = nil
    self.collectionDialog = dialog
    return dialog
end


local function CreateMultilineBox(parent, width, height)
    local scrollFrame = CreateFrame("ScrollFrame", nil, parent, "UIPanelScrollFrameTemplate")
    scrollFrame:SetSize(width, height)
    local editBox = CreateFrame("EditBox", nil, scrollFrame)
    editBox:SetMultiLine(true)
    editBox:SetAutoFocus(false)
    editBox:SetFontObject("ChatFontNormal")
    editBox:SetSize(width - 28, height)
    editBox:SetTextInsets(8, 8, 8, 8)
    editBox:SetScript("OnEscapePressed", function(self)
        self:ClearFocus()
    end)
    scrollFrame:SetScrollChild(editBox)
    if Skin and Skin.SkinEditBox then
        Skin:SkinEditBox(editBox)
    end
    return scrollFrame, editBox
end

function MainFrame:EnsureImportExportDialog()
    if self.importExportDialog then
        return self.importExportDialog
    end

    local parent = self:EnsureFrame()
    local dialog = CreateFrame("Frame", "MCDVoiceCooldownImportExportDialog", parent, "BackdropTemplate")
    dialog:SetSize(720, 500)
    dialog:SetPoint("CENTER", parent, "CENTER", 0, 10)
    dialog:SetFrameStrata("FULLSCREEN_DIALOG")
    dialog:SetToplevel(true)
    dialog:EnableMouse(true)
    dialog:Hide()
    Widgets:ApplyPanelChrome(dialog, { footerHeight = 58 })

    local title = Widgets:CreateLabel(dialog, L("TITLE_IMPORT_EXPORT"), "GameFontNormalLarge")
    title:SetPoint("TOP", dialog, "TOP", 0, -18)
    title:SetWidth(520)
    title:SetJustifyH("CENTER")
    if Skin then
        Skin:StyleFont(title, "title")
    end

    local desc = Widgets:CreateLabel(dialog, "", "GameFontHighlightSmall")
    desc:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -60)
    desc:SetPoint("RIGHT", dialog, "RIGHT", -34, 0)
    desc:SetHeight(44)
    desc:SetJustifyH("LEFT")
    desc:SetJustifyV("TOP")
    if desc.SetWordWrap then
        desc:SetWordWrap(true)
    end
    if Skin then
        Skin:StyleFont(desc, "muted")
    end

    local scrollFrame, editBox = CreateMultilineBox(dialog, 650, 300)
    scrollFrame:SetPoint("TOPLEFT", dialog, "TOPLEFT", 34, -112)

    local importBtn = Widgets:CreateButton(dialog, L("BTN_IMPORT"), 118, 32)
    importBtn:SetPoint("BOTTOMLEFT", dialog, "BOTTOMLEFT", 34, 20)

    local selectBtn = Widgets:CreateButton(dialog, L("BTN_SELECT_ALL"), 118, 32)
    selectBtn:SetPoint("LEFT", importBtn, "RIGHT", 10, 0)

    local closeBtn = Widgets:CreateButton(dialog, L("BTN_CLOSE"), 118, 32)
    closeBtn:SetPoint("LEFT", selectBtn, "RIGHT", 10, 0)

    importBtn:SetScript("OnClick", function()
        if NS.AceOptions and type(NS.AceOptions.ImportString) == "function" then
            if NS.AceOptions:ImportString(editBox:GetText() or "") then
                dialog:Hide()
                self:Refresh()
            end
        end
    end)
    selectBtn:SetScript("OnClick", function()
        editBox:SetFocus()
        editBox:HighlightText()
    end)
    closeBtn:SetScript("OnClick", function()
        dialog:Hide()
    end)

    dialog.title = title
    dialog.desc = desc
    dialog.editBox = editBox
    dialog.importBtn = importBtn
    dialog.selectBtn = selectBtn
    self.importExportDialog = dialog
    return dialog
end

function MainFrame:OpenExportDialog(titleText, exportText)
    local dialog = self:EnsureImportExportDialog()
    dialog.title:SetText(tostring(titleText or L("TITLE_EXPORT")))
    dialog.desc:SetText(L("EXPORT_DESC"))
    dialog.editBox:SetText(tostring(exportText or ""))
    dialog.importBtn:Hide()
    dialog.selectBtn:ClearAllPoints()
    dialog.selectBtn:SetPoint("BOTTOMLEFT", dialog, "BOTTOMLEFT", 34, 20)
    dialog:Show()
    dialog:Raise()
    dialog.editBox:SetFocus()
    dialog.editBox:HighlightText()
end

function MainFrame:OpenImportDialog()
    local dialog = self:EnsureImportExportDialog()
    dialog.title:SetText(L("TITLE_IMPORT_SETTINGS"))
    dialog.desc:SetText(L("IMPORT_DESC"))
    dialog.editBox:SetText("")
    dialog.importBtn:Show()
    dialog.importBtn:ClearAllPoints()
    dialog.importBtn:SetPoint("BOTTOMLEFT", dialog, "BOTTOMLEFT", 34, 20)
    dialog.selectBtn:ClearAllPoints()
    dialog.selectBtn:SetPoint("LEFT", dialog.importBtn, "RIGHT", 10, 0)
    dialog:Show()
    dialog:Raise()
    dialog.editBox:SetFocus()
end

function MainFrame:OpenCollectionNameDialog()
    local dialog = self:EnsureCollectionDialog()
    dialog.mode = "create"
    dialog.groupKey = nil
    dialog.parentGroupKey = nil
    if NS.AceOptions and type(NS.AceOptions.GetState) == "function" then
        local state = NS.AceOptions:GetState()
        local selectedKey = tostring(state.selectedCollectionKey or "")
        if selectedKey == "" and NS.AceOptions.IsGroupKey and NS.AceOptions:IsGroupKey(state.selectedKey) then
            selectedKey = tostring(state.selectedKey or "")
        end
        if selectedKey ~= "" and NS.AceOptions.IsGroupKey and NS.AceOptions:IsGroupKey(selectedKey) then
            dialog.parentGroupKey = selectedKey
        end
    end
    if dialog.title then
        dialog.title:SetText(L("TITLE_ADD_COLLECTION"))
    end
    if dialog.saveButton then
        dialog.saveButton:SetText(L("BTN_CREATE"))
    end
    dialog.editBox:SetText("")
    if dialog.iconEditBox then
        dialog.iconEditBox:SetText("")
    end
    if type(dialog.UpdateIconPreview) == "function" then
        dialog.UpdateIconPreview()
    end
    dialog:Show()
    dialog:Raise()
    dialog.editBox:SetFocus()
end


function MainFrame:OpenCollectionNameDialogForGroup(groupKey)
    groupKey = tostring(groupKey or "")
    if groupKey == "" then
        return self:OpenCollectionNameDialog()
    end
    if NS.AceOptions and type(NS.AceOptions.IsGroupKey) == "function" and NS.AceOptions:IsGroupKey(groupKey) then
        local state = NS.AceOptions:GetState()
        state.selectedKey = groupKey
        state.selectedCollectionKey = groupKey
        if self.savedList and type(self.savedList.SetSelectedKey) == "function" then
            self.savedList:SetSelectedKey(groupKey)
        end
    end
    return self:OpenCollectionNameDialog()
end

function MainFrame:OpenNewVoiceInCollection(groupKey)
    groupKey = tostring(groupKey or "")
    if groupKey ~= "" and NS.AceOptions and type(NS.AceOptions.IsGroupKey) == "function" and NS.AceOptions:IsGroupKey(groupKey) then
        local state = NS.AceOptions:GetState()
        state.selectedKey = groupKey
        state.selectedCollectionKey = groupKey
        if self.savedList and type(self.savedList.SetSelectedKey) == "function" then
            self.savedList:SetSelectedKey(groupKey)
        end
    end
    if NS.UI and NS.UI.EditorFrame and type(NS.UI.EditorFrame.OpenForNew) == "function" then
        NS.UI.EditorFrame:OpenForNew()
    end
end

function MainFrame:OpenRenameCollectionDialog(groupKey)
    local dialog = self:EnsureCollectionDialog()
    local info = NS.AceOptions and type(NS.AceOptions.GetCollectionInfo) == "function" and NS.AceOptions:GetCollectionInfo(groupKey) or nil
    if type(info) ~= "table" then
        return false
    end

    dialog.mode = "rename"
    dialog.groupKey = tostring(groupKey or "")
    if dialog.title then
        dialog.title:SetText(L("TITLE_RENAME_COLLECTION"))
    end
    if dialog.saveButton then
        dialog.saveButton:SetText(L("BTN_SAVE"))
    end
    dialog.editBox:SetText(tostring(info.name or ""))
    if dialog.iconEditBox then
        dialog.iconEditBox:SetText(info.iconID and tostring(info.iconID) or "")
    end
    if type(dialog.UpdateIconPreview) == "function" then
        dialog.UpdateIconPreview()
    end
    dialog:Show()
    dialog:Raise()
    dialog.editBox:SetFocus()
    dialog.editBox:HighlightText()
    return true
end

function MainFrame:SetSelectedKey(key)
    self:EnsureFrame()
    self.savedList:SetSelectedKey(key)
    NS.AceOptions:GetState().selectedKey = key
end

function MainFrame:GetSelectedKey()
    if not self.savedList then
        return nil
    end
    return self.savedList:GetSelectedKey()
end

function MainFrame:Refresh()
    if not self.frame then
        return
    end

    local state = NS.AceOptions:GetState()
    self.summary:SetText(NS.AceOptions:GetCurrentScopeSummary())
    self.savedList:SetSelectedKey(state.selectedKey)
    self.savedList:Refresh()

    local hasSelected = tostring(state.selectedKey or "") ~= ""
    self.editBtn:SetEnabled(hasSelected)
    self.deleteBtn:SetEnabled(hasSelected)
end

function MainFrame:Open()
    local frame = self:EnsureFrame()
    NS.AceOptions:SyncScopeToCurrentSpec()
    NS.AceOptions:EnsureValidScope()
    self:Refresh()
    frame:Show()
    frame:Raise()
    return true
end

function MainFrame:Close()
    if self.frame then
        self.frame:Hide()
    end
    if NS.UI and NS.UI.EditorFrame then
        NS.UI.EditorFrame:Close()
    end
end
