local _, GF = ...

local Dialog = {}
GF.BlacklistConfirmDialog = Dialog

local WHITE = GF.WHITE_TEXTURE
local DIALOG_WIDTH = 520
local DIALOG_HEIGHT = 132
local DIALOG_ICON_SIZE = 64
local DIALOG_MESSAGE_MAX_WIDTH = DIALOG_WIDTH - DIALOG_ICON_SIZE * 2
local DIALOG_MESSAGE_PADDING = 8
local DIALOG_MESSAGE_TOP = -24
local DIALOG_MESSAGE_HEIGHT = 34
local DIALOG_BUTTON_WIDTH = GF.PANEL_CONFIRM_BUTTON_W
	or GF.PANEL_BUTTON_STANDARD_W or 72
local DIALOG_BUTTON_HEIGHT = 26
local DIALOG_BUTTON_FONT_SIZE = GF.PANEL_CONFIRM_BUTTON_FONT_SIZE or 14
local DIALOG_BUTTON_GAP = 36
local DIALOG_BUTTON_TOP_GAP = -16
local MAIN_WINDOW_ALPHA = 0.64

local function T(key, fallback)
	local locale = GF.L or {}
	return locale[key] or fallback or key
end

local function setFontSize(fontString, size)
	if not fontString or not fontString.GetFont or not fontString.SetFont then
		return
	end
	local path, _, flags = fontString:GetFont()
	if path then
		fontString:SetFont(path, size or 12, flags or "")
	end
end

local function applyButtonFontSize(button, size)
	local fontString = button and button.GetFontString
		and button:GetFontString()
	if not fontString then
		return
	end
	fontString._gfFontSizeOverride = size
	if GF.Font and GF.Font.ApplyToFontString then
		GF.Font.ApplyToFontString(fontString, "GameFontNormal")
	else
		setFontSize(fontString, size)
	end
end

local function setMainWindowAlpha(dialog, transparent)
	local mainFrame = GF.MainFrame and GF.MainFrame.frame
	if not (mainFrame and mainFrame.SetAlpha) then
		return
	end
	if transparent then
		if dialog._previousMainAlpha == nil then
			dialog._previousMainAlpha = mainFrame.GetAlpha
				and mainFrame:GetAlpha() or 1
		end
		mainFrame:SetAlpha(MAIN_WINDOW_ALPHA)
	elseif dialog._previousMainAlpha ~= nil then
		local previous = tonumber(dialog._previousMainAlpha) or 1
		dialog._previousMainAlpha = nil
		mainFrame:SetAlpha(previous)
	end
end

local function layoutDialog(dialog)
	local message = dialog.Message
	local icon = dialog.Icon
	local yes = dialog.YesButton
	local no = dialog.NoButton
	local dialogWidth = dialog:GetWidth() or DIALOG_WIDTH
	local textWidth = DIALOG_MESSAGE_MAX_WIDTH
	if message and message.GetStringWidth then
		textWidth = math.ceil(message:GetStringWidth() or 0)
		if textWidth <= 0 then
			textWidth = DIALOG_MESSAGE_MAX_WIDTH
		end
	end
	textWidth = math.min(textWidth, DIALOG_MESSAGE_MAX_WIDTH)
	message:ClearAllPoints()
	message:SetPoint("TOP", dialog, "TOP", 0, DIALOG_MESSAGE_TOP)
	message:SetSize(
		textWidth + DIALOG_MESSAGE_PADDING * 2,
		DIALOG_MESSAGE_HEIGHT)
	local leftBorderX = -dialogWidth / 2
	local textLeftX = -textWidth / 2
	local iconCenterX = (leftBorderX + textLeftX) / 2
	icon:ClearAllPoints()
	icon:SetPoint("CENTER", dialog, "CENTER", iconCenterX, 0)
	yes:ClearAllPoints()
	yes:SetPoint(
		"TOP",
		message,
		"BOTTOM",
		-((DIALOG_BUTTON_WIDTH + DIALOG_BUTTON_GAP) / 2),
		DIALOG_BUTTON_TOP_GAP)
	no:ClearAllPoints()
	no:SetPoint(
		"TOP",
		message,
		"BOTTOM",
		(DIALOG_BUTTON_WIDTH + DIALOG_BUTTON_GAP) / 2,
		DIALOG_BUTTON_TOP_GAP)
end

local function refreshDialogLocale(dialog)
	if not dialog then
		return
	end
	local request = dialog.request or {}
	if dialog.Message then
		dialog.Message:SetText(T(
			request.messageKey,
			request.messageFallback or ""))
	end
	if dialog.YesButton then
		dialog.YesButton:SetText(T(
			request.yesKey or "BLOCKLIST_CONFIRM_YES",
			request.yesFallback or "Yes"))
	end
	if dialog.NoButton then
		dialog.NoButton:SetText(T(
			request.noKey or "BLOCKLIST_CONFIRM_NO",
			request.noFallback or "No"))
	end
	layoutDialog(dialog)
end

local function playCheckSound()
	if GF.UI and GF.UI.PlayUISound then
		GF.UI.PlayUISound("check")
	end
end

local function createDialog()
	local dialog = CreateFrame(
		"Frame",
		"GroupFinderAddonBlacklistRemoveDialog",
		UIParent,
		"BackdropTemplate")
	dialog:SetSize(DIALOG_WIDTH, DIALOG_HEIGHT)
	dialog:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	dialog:SetFrameStrata("DIALOG")
	dialog:SetFrameLevel(1000)
	dialog:SetToplevel(true)
	dialog:EnableMouse(true)
	dialog:Hide()
	if dialog.SetBackdrop then
		dialog:SetBackdrop({
			bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
			edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
			tile = true,
			tileSize = 32,
			edgeSize = 32,
			insets = { left = 11, right = 12, top = 12, bottom = 11 },
		})
		dialog:SetBackdropColor(0, 0, 0, 0.9)
		dialog:SetBackdropBorderColor(0.82, 0.82, 0.82, 1)
	else
		dialog.Background = dialog:CreateTexture(nil, "BACKGROUND")
		dialog.Background:SetAllPoints(dialog)
		dialog.Background:SetTexture(WHITE)
		dialog.Background:SetVertexColor(0, 0, 0, 0.9)
	end
	dialog.Icon = dialog:CreateTexture(nil, "ARTWORK")
	dialog.Icon:SetSize(DIALOG_ICON_SIZE, DIALOG_ICON_SIZE)
	dialog.Icon:SetTexture(GF.BLACKLIST_ICON_TEXTURE)
	dialog.Message = dialog:CreateFontString(
		nil, "OVERLAY", "GameFontHighlightLarge")
	dialog.Message:SetJustifyH("CENTER")
	dialog.Message:SetJustifyV("MIDDLE")
	dialog.Message:SetTextColor(1, 1, 1, 1)
	dialog.Message:SetWordWrap(false)
	setFontSize(dialog.Message, 20)
	dialog.YesButton = GF.UI.CreatePanelButton(
		dialog, T("BLOCKLIST_CONFIRM_YES", "Yes"), DIALOG_BUTTON_WIDTH)
	dialog.YesButton:SetSize(DIALOG_BUTTON_WIDTH, DIALOG_BUTTON_HEIGHT)
	applyButtonFontSize(dialog.YesButton, DIALOG_BUTTON_FONT_SIZE)
	dialog.NoButton = GF.UI.CreatePanelButton(
		dialog, T("BLOCKLIST_CONFIRM_NO", "No"), DIALOG_BUTTON_WIDTH)
	dialog.NoButton:SetSize(DIALOG_BUTTON_WIDTH, DIALOG_BUTTON_HEIGHT)
	applyButtonFontSize(dialog.NoButton, DIALOG_BUTTON_FONT_SIZE)
	dialog.YesButton:SetScript("OnClick", function()
		playCheckSound()
		local request = dialog.request
		if not request then
			return
		end
		local accepted = type(request.onAccept) ~= "function"
			or request.onAccept() == true
		if accepted and dialog.request == request then
			dialog._acceptedRequest = request
			dialog:Hide()
		end
	end)
	dialog.NoButton:SetScript("OnClick", function()
		playCheckSound()
		dialog:Hide()
	end)
	dialog:SetScript("OnShow", function(self)
		layoutDialog(self)
		setMainWindowAlpha(self, true)
		if self.EnableKeyboard then
			self:EnableKeyboard(true)
		end
	end)
	dialog:SetScript("OnHide", function(self)
		setMainWindowAlpha(self, false)
		local request = self.request
		local accepted = request ~= nil
			and self._acceptedRequest == request
		self.request = nil
		self._acceptedRequest = nil
		if self.EnableKeyboard then
			self:EnableKeyboard(false)
		end
		if not accepted and request
			and type(request.onCancel) == "function"
		then
			request.onCancel()
		end
	end)
	dialog:SetScript("OnKeyDown", function(self, key)
		if key == "ESCAPE" then
			self:Hide()
		end
	end)
	if GF.UI and GF.UI.InstallPopupOpenAnimation then
		GF.UI.InstallPopupOpenAnimation(dialog, { preset = "dialog" })
	end
	return dialog
end

local function ensureDialog()
	if not Dialog.frame then
		Dialog.frame = createDialog()
	end
	return Dialog.frame
end

function Dialog:Show(options)
	local dialog = ensureDialog()
	if dialog:IsShown() then
		dialog:Hide()
	end
	dialog.request = type(options) == "table" and options or {}
	refreshDialogLocale(dialog)
	dialog:ClearAllPoints()
	dialog:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	dialog:Show()
	if dialog.Raise then
		dialog:Raise()
	end
	return true
end

function Dialog:Hide()
	if self.frame and self.frame:IsShown() then
		self.frame:Hide()
		return true
	end
	return false
end

function Dialog:RefreshLocale()
	if self.frame then
		refreshDialogLocale(self.frame)
	end
end
