local _, GF = ...

GF.RowContextMenu = {}
local RCM = GF.RowContextMenu

local ROW_CTX_MENU_MAX_W = 165
local ROW_CTX_TITLE_ROW_GAP = 3
local ROW_CTX_ACTION_GAP = 4
local ROW_CTX_TITLE_BOTTOM_GAP = 6
local ROW_CTX_TOP_GAP = 10
local ROW_CTX_BOTTOM_GAP = 10
local ROW_CTX_TITLE_COLOR = { 1, 0.82, 0, 1 }
local ROW_CTX_NORMAL_COLOR = { 1, 1, 1, 1 }
local ROW_CTX_DISABLED_COLOR = { 0.5, 0.5, 0.5, 1 }
local ROW_CTX_SIGN_UP_COLOR = { 0, 1, 0, 1 }

local buttonTopPads = {}
local buttonExtraAfter = {}

local function applyMenuTextColor(text, item)
	if not text or not text.SetTextColor then
		return
	end
	local color = item and item.textColor
	if not color then
		if item and item.isTitle then
			color = ROW_CTX_TITLE_COLOR
		elseif item and item.disabled then
			color = ROW_CTX_DISABLED_COLOR
		else
			color = ROW_CTX_NORMAL_COLOR
		end
	end
	text:SetTextColor(color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1)
end

local function whisperLeader(leaderName)
	if type(leaderName) ~= "string" or leaderName == "" then
		return
	end
	if ChatFrameUtil and ChatFrameUtil.SendTell then
		ChatFrameUtil.SendTell(leaderName)
	elseif ChatFrame_OpenChat then
		ChatFrame_OpenChat("/w " .. leaderName .. " ", SELECTED_DOCK_FRAME)
	end
end

local function clampMenuWidth()
	local list = _G.DropDownList1
	if not list or not list:IsShown() then
		return
	end
	local buttonH = _G.UIDROPDOWNMENU_BUTTON_HEIGHT or 16
	local y = -ROW_CTX_TOP_GAP
	local contentH = 0
	list:SetWidth(ROW_CTX_MENU_MAX_W + 25)
	for i = 1, _G.UIDROPDOWNMENU_MAXBUTTONS or 8 do
		local btn = _G["DropDownList1Button" .. i]
		if btn and btn:IsShown() then
			local item = RCM.pendingItems and RCM.pendingItems[i]
			local pad = buttonTopPads[i] or ROW_CTX_ACTION_GAP
			local rowH = pad + buttonH
			local x = 17
			local _, _, _, curX = btn:GetPoint(1)
			if curX then
				x = curX
			end
			btn:ClearAllPoints()
			btn:SetPoint("TOPLEFT", btn:GetParent(), "TOPLEFT", x, y)
			y = y - rowH
			contentH = contentH + rowH
			local extraAfter = buttonExtraAfter[i] or 0
			if extraAfter > 0 then
				y = y - extraAfter
				contentH = contentH + extraAfter
			end
			btn:SetWidth(ROW_CTX_MENU_MAX_W)
			local text = _G["DropDownList1Button" .. i .. "NormalText"]
			if text then
				text:SetWordWrap(false)
				text:SetMaxLines(1)
				text:SetWidth(ROW_CTX_MENU_MAX_W - 20)
			end
			if GF.Font then
				if i == 1 then
					local titleText = _G["DropDownList1Button" .. i .. "NormalText"]
					if titleText and GF.Font.ApplyToMenuFontString then
						GF.Font.ApplyToMenuFontString(titleText, "GameFontNormalSmall")
					end
				elseif GF.Font.ApplyToDropdownButton then
					GF.Font.ApplyToDropdownButton(btn, "GameFontHighlightSmall")
				end
			end
			applyMenuTextColor(text, item)
		end
	end
	list:SetHeight(contentH + ROW_CTX_TOP_GAP + ROW_CTX_BOTTOM_GAP)
end

local function closeMenu()
	if CloseMenus then
		CloseMenus()
	end
end

local function showMenu(menuItems)
	if not (UIDropDownMenu_Initialize and ToggleDropDownMenu and UIDropDownMenu_CreateInfo and UIDropDownMenu_AddButton) then
		return
	end
	local menuFrame = RCM.dropdown or CreateFrame("Frame", "GroupFinderAddonRowContextMenu", UIParent, "UIDropDownMenuTemplate")
	RCM.dropdown = menuFrame
	RCM.pendingItems = menuItems
	if CloseMenus then
		CloseMenus()
	end
	local function initialize(_, level)
		local pending = RCM.pendingItems or {}
		buttonTopPads = {}
		buttonExtraAfter = {}
		for idx, item in ipairs(pending) do
			local info = UIDropDownMenu_CreateInfo()
			info.text = item.text
			info.notCheckable = true
			info.leftPadding = 2
			info.topPadding = item.isTitle and ROW_CTX_TITLE_ROW_GAP or ROW_CTX_ACTION_GAP
			if item.isTitle then
				info.isTitle = true
				info.notClickable = true
				info.disabled = true
				buttonTopPads[idx] = ROW_CTX_TITLE_ROW_GAP
				buttonExtraAfter[idx] = ROW_CTX_TITLE_BOTTOM_GAP
			else
				buttonTopPads[idx] = ROW_CTX_ACTION_GAP
				info.func = item.func
				info.disabled = item.disabled
			end
			UIDropDownMenu_AddButton(info, level)
		end
	end
	UIDropDownMenu_Initialize(menuFrame, initialize, "MENU")
	local list = _G.DropDownList1
	if list then
		list.onShow = clampMenuWidth
	end
	ToggleDropDownMenu(1, nil, menuFrame, "cursor", 0, 0)
	clampMenuWidth()
end

function RCM:BuildMenuItems(row, index, resultID, info)
	local L = GF.L or {}
	local titleText = (row and row._titleText) or info.name or "?"
	local items = {
		{
			isTitle = true,
			text = titleText,
		},
		{
			text = L.SIGN_UP or "Sign Up",
			textColor = ROW_CTX_SIGN_UP_COLOR,
			func = function()
				if GF.Apply and GF.Apply.ShowDialogForIndex then
					GF.Apply:ShowDialogForIndex(index)
				end
			end,
		},
		{
			text = L.CTX_WHISPER_LEADER or WHISPER_LEADER or "Whisper leader",
			disabled = not info.leaderName,
			func = function()
				whisperLeader(info.leaderName)
			end,
		},
	}
	if GF.Blocklist and GF.Blocklist.IsEnabled and GF.Blocklist:IsEnabled() then
		items[#items + 1] = {
			text = L.CTX_BLOCK_LEADER or "Block leader",
			disabled = not info.leaderName,
			func = function()
				GF.Blocklist:BlockLeaderFromSearchResult(resultID, info)
			end,
		}
		items[#items + 1] = {
			text = L.CTX_BLOCK_TITLE or "Block same title",
			disabled = not (info.leaderName and info.name),
			func = function()
				GF.Blocklist:BlockSameTitleFromSearchResult(resultID, info)
			end,
		}
	end
	if LFGList_ReportListing then
		items[#items + 1] = {
			text = L.CTX_REPORT or LFG_LIST_REPORT_GROUP_FOR or "Report",
			func = function()
				LFGList_ReportListing(resultID, info.leaderName)
			end,
		}
	end
	if LFGList_ReportAdvertisement then
		items[#items + 1] = {
			text = L.CTX_REPORT_ADVERTISEMENT or "Report advertisement",
			func = function()
				LFGList_ReportAdvertisement(resultID)
				if GF.Blocklist and GF.Blocklist.IsEnabled and GF.Blocklist:IsEnabled() then
					GF.Blocklist:BlockAdvertisementFromSearchResult(resultID, info)
				end
			end,
		}
	end
	items[#items + 1] = {
		text = L.CANCEL or "Cancel",
		func = closeMenu,
	}
	return items
end

function RCM:ShowForRow(row)
	if not row or not row.resultIndex then
		return
	end
	if GF.FindGroupTab and GF.FindGroupTab.SetSelectedRow then
		GF.FindGroupTab:SetSelectedRow(row)
	end
	local index = row.resultIndex
	local resultID = GF.Result:GetResultID(index)
	if not resultID then
		return
	end
	local info = C_LFGList.GetSearchResultInfo(resultID)
	if not info then
		return
	end
	showMenu(self:BuildMenuItems(row, index, resultID, info))
end
