local _AddonName, _EchoRaidTools = ...
local _InviteTools = _EchoRaidTools:NewModule("InviteTools")

function _InviteTools:DisbandRaid(keepguild)
	for unit in _EchoRaidTools.IterateGroup() do
		if not UnitIsUnit(unit, "player") then
			if keepguild and UnitIsInMyGuild(unit) then
				-- do nothing
			else
				UninviteUnit(unit)
			end
		end
	end
end
local function getGuildRank(unit)
	if not UnitIsInMyGuild(unit) then
		return nil
	end
	local rankIndex = select(3, GetGuildInfo(unit))
	if rankIndex then
		return rankIndex
	else
		for i = 1, GetNumGuildMembers() do
			local name, _, rankIndex2 = GetGuildRosterInfo(i)
			local unitName = UnitName(unit)
			if (name == unitName) or (Ambiguate(name, "none") == unitName) then
				return rankIndex2
			end
		end
	end
end

-- ADDON BASICS
SLASH_ECHORTDISBAND = "/rtdis"
SlashCmdList["SLASH_ECHORTDISBAND"] = function(msg)
	_InviteTools:DisbandRaid(msg == "guild")
end

function _InviteTools:ADDON_LOADED(addonName)
	if addonName ~= _AddonName then
		return
	end
	if _InviteTools.initialized then
		return
	end
	if type(EchoRaidToolsDB.InviteTools) ~= "table" then
		EchoRaidToolsDB.InviteTools = {}
	end
	if type(EchoRaidToolsDB.InviteTools.AcceptSuggested) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.AcceptSuggested = true
	end
	if type(EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends = false
	end
	if type(EchoRaidToolsDB.InviteTools.PromoteToAssistant) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.PromoteToAssistant = false
	end
	if type(EchoRaidToolsDB.InviteTools.InviteWhispers) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.InviteWhispers = true
	end
	if type(EchoRaidToolsDB.InviteTools.GuildRanksInvite) ~= "table" then
		EchoRaidToolsDB.InviteTools.GuildRanksInvite = {}
	end
	if type(EchoRaidToolsDB.InviteTools.GuildRanksAssist) ~= "table" then
		EchoRaidToolsDB.InviteTools.GuildRanksAssist = {}
	end
	if type(EchoRaidToolsDB.InviteTools.GuildRanks) ~= "table" then
		EchoRaidToolsDB.InviteTools.GuildRanks = {}
	end
	if type(EchoRaidToolsDB.InviteTools.AutoAcceptFromGuild) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.AutoAcceptFromGuild = true
	end
	if type(EchoRaidToolsDB.InviteTools.AutoAcceptFromFriends) ~= "boolean" then
		EchoRaidToolsDB.InviteTools.AutoAcceptFromFriends = true
	end
	if type(EchoRaidToolsDB.InviteTools.InviteWhisperKeywords) ~= "string" then
		EchoRaidToolsDB.InviteTools.InviteWhisperKeywords = "inv"
	end

	local whisperStrings = {}
	local function getWhisperStrings()
		whisperStrings = {}
		for word in string.gmatch(EchoRaidToolsDB.InviteTools.InviteWhisperKeywords, '[^,%c%s{}%[%]"]+') do
			if #word > 0 then
				table.insert(whisperStrings, word:lower())
			end
		end
	end
	getWhisperStrings()

	local eventFrame = CreateFrame("Frame")
	eventFrame:RegisterEvent("GROUP_INVITE_CONFIRMATION")
	eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
	eventFrame:RegisterEvent("CHAT_MSG_WHISPER")
	eventFrame:RegisterEvent("CHAT_MSG_BN_WHISPER")
	eventFrame:RegisterEvent("PARTY_INVITE_REQUEST")
	local RosterUpdateLastTime
	eventFrame:SetScript("OnEvent", function(self, event, ...)
		if
			event == "GROUP_INVITE_CONFIRMATION"
			and (IsInRaid() or IsInGroup())
			and UnitIsGroupLeader("player")
			and (EchoRaidToolsDB.InviteTools.AcceptSuggested or EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends)
		then
			local guid = GetNextPendingInviteConfirmation()
			if not guid then
				return
			end
			local confirmationType, name, inviteeGUID, noRole, willConvertToRaid, level, spec, itemLevel =
				GetInviteConfirmationInfo(guid)
			--local outReferredByGuid, outReferredByName = C_PartyInfo.GetInviteReferralInfo(guid)

			local isFriend = C_FriendList.IsFriend(inviteeGUID)
			local isGuildMember = IsGuildMember(inviteeGUID)
			if
				(isFriend and EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends)
				or (isGuildMember and EchoRaidToolsDB.InviteTools.AcceptSuggested)
			then
				RespondToInviteConfirmation(guid, true)
				StaticPopup_Hide("GROUP_INVITE_CONFIRMATION", guid)

				print(
					format(
						"|cffff3333EchoRaidTools|r: Auto-accepting suggested invite to %s (%s)",
						name,
						isFriend and isGuildMember and "friend+guild" or isFriend and "friend" or "guild"
					)
				)
			end
		elseif
			event == "GROUP_ROSTER_UPDATE"
			and (not InCombatLockdown())
			and IsInRaid()
			and UnitIsGroupLeader("player")
			and EchoRaidToolsDB.InviteTools.PromoteToAssistant
			and (not RosterUpdateLastTime or (GetTime() - RosterUpdateLastTime) > 0.4)
		then
			RosterUpdateLastTime = GetTime()
			for unit in _EchoRaidTools.IterateGroup() do
				if (not UnitIsUnit(unit, "player")) and UnitIsInMyGuild(unit) and (not UnitIsGroupAssistant(unit)) then
					local rankIndex = getGuildRank(unit)
					if EchoRaidToolsDB.InviteTools.GuildRanksAssist[rankIndex] then
						PromoteToAssistant(unit)
					end
				end
			end
		elseif
			(event == "CHAT_MSG_WHISPER" or event == "CHAT_MSG_BN_WHISPER")
			and EchoRaidToolsDB.InviteTools.InviteWhispers
			and (((IsInRaid() or IsInGroup()) and UnitIsGroupLeader("player")) or not (IsInRaid() or IsInGroup()))
		then
			local msg, sender, _, _, _, _, _, _, _, _, _, guid = ...
			if (not guid) or issecretvalue(guid) then return end
			if IsGuildMember(guid) then
				for _, word in ipairs(whisperStrings) do
					if msg:lower():match("^" .. word .. "%f[%A]") then
						if GetNumGroupMembers() >= 4 and not IsInRaid() then
							C_PartyInfo.ConvertToRaid()
						end
						C_Timer.After(math.random(), function()
							C_PartyInfo.InviteUnit(sender)
						end)
						break
					end
				end
			end
		elseif event == "PARTY_INVITE_REQUEST" then
			local name, isTank, isHealer, isDamage, isNativeRealm, allowMultipleRoles, inviterGUID, questSessionActive =
				...
			if
				(IsGuildMember(inviterGUID) and EchoRaidToolsDB.InviteTools.AutoAcceptFromGuild)
				or (C_FriendList.IsFriend(inviterGUID) and EchoRaidToolsDB.InviteTools.AutoAcceptFromFriends)
			then
				AcceptGroup()

				StaticPopup_Hide("PARTY_INVITE")
				print("|cffff3333EchoRaidTools|r: Auto-accepted party invite from " .. name)
			end
		end
	end)

	function _InviteTools:GetNavigationButtons() end

	function _InviteTools:GetConfig()
		if _EchoRaidTools.panels.InviteToolsModule then
			return _EchoRaidTools.panels.InviteToolsModule
		end

		--main panel creation
		local window = CreateFrame("FRAME", nil, _EchoRaidTools.panels.main, "EchoRaidToolsMainConfigWindow")
		window.Header.HeaderText:SetText("Invite Tools")
		window.Header.EnableModule:Hide()
		window.Header.HeaderText:ClearAllPoints()
		window.Header.HeaderText:SetPoint("LEFT", 10, 0)

		local panel = CreateFrame("FRAME", nil, window, "EchoRaidToolsMainConfigPanel")

		local function onShowHandler() end
		panel:SetScript("OnShow", onShowHandler)
		panel:SetScript("OnHide", function() end)

		-- Call the show handler immediately since OnShow won't fire on initial creation
		onShowHandler()

		panel:SetPoint("TOPLEFT", window.Header, "BOTTOMLEFT")
		panel:SetPoint("BOTTOMRIGHT")
		local mainContainer = panel.ScrollFrame.ScrollingPanel
		_InviteTools.controlParent = mainContainer
		_InviteTools.mainWindow = window
		_InviteTools.mainPanel = panel
		_InviteTools.mainWindow.currentPanel = panel

		panel.ScrollFrame:SetVerticalScroll(0)
		local Resize = function() end
		panel:SetScript("OnSizeChanged", Resize)

		_EchoRaidTools.panels.InviteToolsModule = window

		--local ScrollingPanel = CreateFrame("Frame", nil, mainContainer, "EchoRaidToolsMainConfigPanel")
		--ScrollingPanel:SetAllPoints()
		--ScrollingPanel:Show()

		local function newCheckbutton(label, description, onClick, parent)
			local checkbutton = CreateFrame("CheckButton", nil, parent, "EchoRaidToolsConfig_CheckButton")
			checkbutton:SetSize(24, 24)
			checkbutton.CheckButton:SetScript("OnClick", function(self)
				local tick = self:GetChecked()
				onClick(self, not not tick)
				if tick then
					PlaySound(856)
				else
					PlaySound(857)
				end
			end)
			checkbutton.TopText:SetText(label)
			checkbutton.TopText:Show()
			checkbutton.tooltip = description
			checkbutton.CheckButton.tooltip = description
			return checkbutton
		end

		local autoAcceptLabel = mainContainer:CreateFontString(nil, "ARTWORK", "GameFontNormal")
		autoAcceptLabel:SetPoint("TOPLEFT", mainContainer, "TOPLEFT", 20, -20)
		autoAcceptLabel:SetText("Auto-Accept Incoming Invites")
		local AutoAcceptFromGuildCheckbox = newCheckbutton(
			"Guild",
			"Automatically accept any invite incoming from a guild member",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.AutoAcceptFromGuild = checked
			end,
			mainContainer
		)
		AutoAcceptFromGuildCheckbox:SetPoint("TOPLEFT", autoAcceptLabel, "BOTTOMLEFT", 0, -18)
		AutoAcceptFromGuildCheckbox.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.AutoAcceptFromGuild)
		local AutoAcceptFromFriendsCheckbox = newCheckbutton(
			"Friends",
			"Automatically accept any invite incoming from a friend",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.AutoAcceptFromFriends = checked
			end,
			mainContainer
		)
		AutoAcceptFromFriendsCheckbox:SetPoint("LEFT", AutoAcceptFromGuildCheckbox, "RIGHT", 40, 0)
		AutoAcceptFromFriendsCheckbox.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.AutoAcceptFromFriends)

		local inviteWhispersCheckbox = newCheckbutton(
			"Invite Whispers from Guild with a keyword",
			"Automatically invite guild members who whisper you a chosen keyword while you are group leader.",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.InviteWhispers = checked
			end,
			mainContainer
		)
		inviteWhispersCheckbox:SetPoint("TOPLEFT", AutoAcceptFromGuildCheckbox, "BOTTOMLEFT", 0, -18)
		inviteWhispersCheckbox.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.InviteWhispers)
		local inviteWhispersEditBox = CreateFrame("Frame", nil, mainContainer, "EchoRaidToolsConfig_EditBox")
		inviteWhispersEditBox:SetPoint("LEFT", inviteWhispersCheckbox, "RIGHT", 40, 0)
		inviteWhispersEditBox:SetSize(200, 24)
		inviteWhispersEditBox.Editbox:SetAutoFocus(false)
		inviteWhispersEditBox.Editbox:SetText(EchoRaidToolsDB.InviteTools.InviteWhisperKeywords)
		inviteWhispersEditBox.tooltip =
			"Keywords to trigger auto-invite when whispered (separate multiple keywords with spaces)"
		inviteWhispersEditBox.Editbox.tooltip =
			"Keywords to trigger auto-invite when whispered (separate multiple keywords with spaces)"
		inviteWhispersEditBox.Editbox:SetScript("OnEnterPressed", function(self)
			local text = self:GetText()
			EchoRaidToolsDB.InviteTools.InviteWhisperKeywords = text
			self:ClearFocus()
			getWhisperStrings()
		end)
		inviteWhispersEditBox.Editbox:SetScript("OnEscapePressed", function(self)
			self:SetText(EchoRaidToolsDB.InviteTools.InviteWhisperKeywords)
			self:ClearFocus()
		end)

		local suggestedLabel = mainContainer:CreateFontString(nil, "ARTWORK", "GameFontNormal")
		suggestedLabel:SetPoint("TOPLEFT", inviteWhispersCheckbox, "BOTTOMLEFT", 0, -10)
		suggestedLabel:SetText("Auto-Accept \"Suggested\" Invites of...")
		local suggestedCheckbox = newCheckbutton(
			"Guild",
			"If a guild member is suggested while you are group leader, automatically accept it.",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.AcceptSuggested = checked
			end,
			mainContainer
		)
		suggestedCheckbox:SetPoint("TOPLEFT", suggestedLabel, "BOTTOMLEFT", 0, -18)
		suggestedCheckbox.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.AcceptSuggested)
		local suggestedFriendsCheckbox = newCheckbutton(
			"Friends",
			"If a friend is suggested while you are group leader, automatically accept it.",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends = checked
			end,
			mainContainer
		)
		suggestedFriendsCheckbox:SetPoint("LEFT", suggestedCheckbox, "RIGHT", 40, 0)
		suggestedFriendsCheckbox.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.AcceptSuggestedFriends)

		local PromoteToAssistantCheckbutton = newCheckbutton(
			"Promote selected ranks' guild members to Assistant",
			"Automatically promote guild members of the ranks selected to Assistant role.",
			function(_, checked)
				EchoRaidToolsDB.InviteTools.PromoteToAssistant = checked
			end,
			mainContainer
		)
		PromoteToAssistantCheckbutton:SetPoint("TOPLEFT", suggestedCheckbox, "BOTTOMLEFT", 0, -25)
		PromoteToAssistantCheckbutton.CheckButton:SetChecked(EchoRaidToolsDB.InviteTools.PromoteToAssistant)
		local PromoteGuildRankDropdown = CreateFrame("FRAME", nil, mainContainer, "EchoRaidToolsConfig_Dropdown")
		PromoteGuildRankDropdown:SetPoint("LEFT", PromoteToAssistantCheckbutton, "LEFT", 50, 0)
		PromoteGuildRankDropdown:SetSize(200, 38)
		local items2 = {
			togglesEnabled = true,
		}
		for i = 1, GuildControlGetNumRanks() do
			local rankName = GuildControlGetRankName(i)
			if rankName then
				table.insert(items2, {
					label = rankName,
					value = i - 1,
					onclick = function(button, down, value, self)
						local newChecked = self.CheckButton:GetChecked()
						EchoRaidToolsDB.InviteTools.GuildRanksAssist[i - 1] = newChecked
					end,
					toggle = function(checked, button, down, value)
						EchoRaidToolsDB.InviteTools.GuildRanksAssist[i - 1] = checked
					end,
					checked = EchoRaidToolsDB.InviteTools.GuildRanksAssist[i - 1],
				})
			end
		end
		PromoteGuildRankDropdown:SetupSelections(items2, 0)

		local inviteGuildButton = CreateFrame("Button", nil, mainContainer, "EchoRaidToolsConfig_Button")
		inviteGuildButton:SetPoint("TOPLEFT", PromoteToAssistantCheckbutton, "BOTTOMLEFT", 0, -40)
		inviteGuildButton:SetSize(200, 38)
		inviteGuildButton.TopText:Show()
		inviteGuildButton.TopText:SetText("Invite Guild (selected ranks)")
		inviteGuildButton.Button:SetText("Invite Guild")
		local GuildRankDropdown = CreateFrame("FRAME", nil, mainContainer, "EchoRaidToolsConfig_Dropdown")
		GuildRankDropdown:SetPoint("LEFT", inviteGuildButton, "RIGHT", 20, 0)
		GuildRankDropdown.TopText:SetText("Guild Ranks")
		GuildRankDropdown.TopText:Show()
		GuildRankDropdown:SetSize(200, 38)
		local items = {
			togglesEnabled = true,
		}
		for i = 1, GuildControlGetNumRanks() do
			local rankName = GuildControlGetRankName(i)
			if rankName then
				table.insert(items, {
					label = rankName,
					value = i-1,
					onclick = function(button, down, value, self)
						local newChecked = self.CheckButton:GetChecked()
						EchoRaidToolsDB.InviteTools.GuildRanks[i-1] = newChecked
					end,
					toggle = function(checked, button, down, value)
						EchoRaidToolsDB.InviteTools.GuildRanks[i-1] = checked
					end,
					checked = EchoRaidToolsDB.InviteTools.GuildRanks[i-1],
				})
			end
		end
		GuildRankDropdown:SetupSelections(items, 0)
		inviteGuildButton.Button:SetScript("OnClick", function()
			local rank = GuildRankDropdown:GetSelectedValue()
			local guildSize = GetNumGuildMembers()
			for i = 1, guildSize do
				local name, _, rankIndex, _, _, _, _, _, online = GetGuildRosterInfo(i)
				if online and EchoRaidToolsDB.InviteTools.GuildRanks[rankIndex] then
					if GetNumGroupMembers() >= 5 and not IsInRaid() then
						C_PartyInfo.ConvertToRaid()
					end
					print("Inviting " .. name)
					C_Timer.After(math.random(), function()
						C_PartyInfo.InviteUnit(name)
					end)
				end
			end
		end)

		local inviteBoxLabel = mainContainer:CreateFontString(nil, "ARTWORK", "GameFontNormal")
		inviteBoxLabel:SetPoint("TOPLEFT", inviteGuildButton, "BOTTOMLEFT", 0, -20)
		inviteBoxLabel:SetText("Invite list or names")
		local InviteBox = CreateFrame("Frame", nil, mainContainer, "EchoRaidToolsConfig_ScrollingEditBoxTemplate")
		InviteBox:SetPoint("TOPLEFT", inviteBoxLabel, "BOTTOMLEFT", 0, -2)
		InviteBox:SetSize(500, 100)
		InviteBox.ScrollingEditBox.ScrollBox.EditBox:SetAutoFocus(false)
		local InviteBoxButton = CreateFrame("Button", nil, mainContainer, "EchoRaidToolsConfig_Button")
		InviteBoxButton:SetPoint("TOPRIGHT", InviteBox, "BOTTOMRIGHT", 0, -2)
		InviteBoxButton:SetSize(100, 38)
		InviteBoxButton.Button:SetText("Invite")
		local function invitelist()
			local text = InviteBox.ScrollingEditBox:GetText()
			for name in string.gmatch(text, '[^,%c%s{}%[%]"]+') do
				if #name > 0 then
					if GetNumGroupMembers() >= 4 and not IsInRaid() then
						C_PartyInfo.ConvertToRaid()
					end
					print("Inviting " .. name)

					C_Timer.After(math.random(), function()
						C_PartyInfo.InviteUnit(name)
					end)
				end
			end
		end
		InviteBoxButton.Button:SetScript("OnClick", function()
			invitelist()
		end)
		InviteBox.ScrollingEditBox:RegisterCallback("OnEnterPressed", invitelist, self)

		local DisbandButton = CreateFrame("Button", nil, mainContainer, "EchoRaidToolsConfig_Button")
		DisbandButton:SetPoint("TOPLEFT", InviteBox, "BOTTOMLEFT", 0, -50)
		DisbandButton:SetSize(200, 38)
		DisbandButton.TopText:Show()
		DisbandButton.TopText:SetText([[Can also use "/rtdis"]])
		DisbandButton.Button:SetText("Disband Raid")
		DisbandButton:SetScript("OnClick", function()
			_InviteTools:DisbandRaid()
		end)
		local DisbandButton2 = CreateFrame("Button", nil, mainContainer, "EchoRaidToolsConfig_Button")
		DisbandButton2:SetPoint("LEFT", DisbandButton, "RIGHT", 20, 0)
		DisbandButton2:SetSize(200, 38)
		DisbandButton2.TopText:Show()
		DisbandButton2.TopText:SetText([[Can also use "/rtdis guild"]])
		DisbandButton2.Button:SetText("Disband (keep Guild)")
		DisbandButton2:SetScript("OnClick", function()
			_InviteTools:DisbandRaid(true)
		end)

		mainContainer:SetHeight(350)
		return window
	end
	function _InviteTools:GetButtonInfo()
		return "Invite Tools",
			nil,
			function()
				return _InviteTools:GetConfig()
			end,
			_InviteTools:GetNavigationButtons()
	end

	_InviteTools.initialized = true
end
