-- Map storing Player -> Blocked user Ids.
local BlockedUserIdsMap = {}

PlayersService.PlayerAdded:connect(function(newPlayer)
	for player, blockedUsers in pairs(BlockedUserIdsMap) do
		local speaker = ChatService:GetSpeaker(player.Name)
		if speaker then
			for i = 1, #blockedUsers do
				local blockedUserId = blockedUsers[i]
				if blockedUserId == newPlayer.UserId then
					speaker:AddMutedSpeaker(newPlayer.Name)
				end
			end
		end
	end
end)

PlayersService.PlayerRemoving:connect(function(removingPlayer)
	BlockedUserIdsMap[removingPlayer] = nil
end)

EventFolder.SetBlockedUserIdsRequest.OnServerEvent:connect(function(player, blockedUserIdsList)
	BlockedUserIdsMap[player] = blockedUserIdsList
	local speaker = ChatService:GetSpeaker(player.Name)
	if speaker then
		for i = 1, #blockedUserIdsList do
			local blockedPlayer = PlayersService:GetPlayerByUserId(blockedUserIdsList[i])
			if blockedPlayer then
				speaker:AddMutedSpeaker(blockedPlayer.Name)
			end
		end
	end
end)

EventFolder.GetInitDataRequest.OnServerInvoke = (function(playerObj)
	local speaker = ChatService:GetSpeaker(playerObj.Name)
	if not (speaker and speaker:GetPlayer()) then
		CreatePlayerSpeakerObject(playerObj)
		speaker = ChatService:GetSpeaker(playerObj.Name)
	end

	local data = {}
	data.Channels = {}
	data.SpeakerExtraData = {}

	for i, channelName in pairs(speaker:GetChannelList()) do
		local channelObj = ChatService:GetChannel(channelName)
		if (channelObj) then
			local channelData =
			{
				channelName,
				channelObj:GetWelcomeMessageForSpeaker(speaker),
				channelObj:GetHistoryLogForSpeaker(speaker),
				channelObj.ChannelNameColor,
			}

			table.insert(data.Channels, channelData)
		end
	end

	for i, oSpeakerName in pairs(ChatService:GetSpeakerList()) do
		local oSpeaker = ChatService:GetSpeaker(oSpeakerName)
		data.SpeakerExtraData[oSpeakerName] = oSpeaker.ExtraData
	end

	return data
end)

local function DoJoinCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (channel) then
			if (channel.Joinable) then
				if (not speaker:IsInChannel(channel.Name)) then
					speaker:JoinChannel(channel.Name)
				else
					speaker:SetMainChannel(channel.Name)
					speaker:SendSystemMessage(
						string.gsub(
							ChatLocalization:Get(
								"GameChat_SwitchChannel_NowInChannel",
								string.format("You are now chatting in channel: '%s'", channel.Name)
							),
						"{RBX_NAME}",channel.Name),
						channel.Name
					)
				end
			else
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatServiceRunner_YouCannotJoinChannel",
							("You cannot join channel '" .. channelName .. "'.")
						),
					"{RBX_NAME}",channelName),
					fromChannelName
				)
			end
		else
			speaker:SendSystemMessage(
				string.gsub(
					ChatLocalization:Get(
						"GameChat_ChatServiceRunner_ChannelDoesNotExist",
						("Channel '" .. channelName .. "' does not exist.")
					),
				"{RBX_NAME}",channelName),
				fromChannelName
			)
		end
	end
end

local function DoLeaveCommand(speakerName, channelName, fromChannelName)
	local speaker = ChatService:GetSpeaker(speakerName)
	local channel = ChatService:GetChannel(channelName)

	if (speaker) then
		if (speaker:IsInChannel(channelName)) then
			if (channel.Leavable) then
				speaker:LeaveChannel(channel.Name)
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatService_YouHaveLeftChannel",
							string.format("You have left channel '%s'", channelName)
						),
					"{RBX_NAME}",channel.Name),
					"System"
				)
			else
				speaker:SendSystemMessage(
					string.gsub(
						ChatLocalization:Get(
							"GameChat_ChatServiceRunner_YouCannotLeaveChannel",
							("You cannot leave channel '" .. channelName .. "'.")
						),
					"{RBX_NAME}",channelName),
					fromChannelName
				)
			end
		else
			speaker:SendSystemMessage(
				string.gsub(
					ChatLocalization:Get(
						"GameChat_ChatServiceRunner_YouAreNotInChannel",
						("You are not in channel '" .. channelName .. "'.")
					),
				"{RBX_NAME}",channelName),
				fromChannelName
			)
		end
	end
end

ChatService:RegisterProcessCommandsFunction("default_commands", function(fromSpeaker, message, channel)
	if (string.sub(message, 1, 6):lower() == "/join ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 7), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/j ") then
		DoJoinCommand(fromSpeaker, string.sub(message, 4), channel)
		return true

	elseif (string.sub(message, 1, 7):lower() == "/leave ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 8), channel)
		return true
	elseif (string.sub(message, 1, 3):lower() == "/l ") then
		DoLeaveCommand(fromSpeaker, string.sub(message, 4), channel)
		return true

	elseif (string.sub(message, 1, 3) == "/e " or string.sub(message, 1, 7) == "/emote ") then
		-- Just don't show these in the chatlog. The animation script listens on these.
		return true

	end

	return false
end)

if ChatSettings.GeneralChannelName and ChatSettings.GeneralChannelName ~= "" then
	local allChannel = ChatService:AddChannel(ChatSettings.GeneralChannelName)

	allChannel.Leavable = false
	allChannel.AutoJoin = true

	allChannel:RegisterGetWelcomeMessageFunction(function(speaker)