local function y(y)local k={}for y,S in pairs(y)do k[y]=S end return k end local k={}k.__index=k function k.SayMessage(x,y,k,S)if x.ChatService:InternalDoProcessCommands(x.Name,y,k)then return end if not k then return end local T=x.Channels[k:lower()]if not T then error("\083\112\101\097\107\101\114 \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \""..(k.."\""))end local M=T:InternalPostMessage(x,y,S)if M then local y,S=pcall(function()x.eSaidMessage:Fire(M,k)end)if not y and S then print("\069\114\114\111\114 \115\097\121\105\110\103 \109\101\115\115\097\103\101\058 "..S)end end return M end function k.JoinChannel(k,y)if k.Channels[y:lower()]then warn("\083\112\101\097\107\101\114 \105\115 \097\108\114\101\097\100\121 \105\110 \099\104\097\110\110\101\108 \""..(y.."\""))return end local S=k.ChatService:GetChannel(y)if not S then error("\067\104\097\110\110\101\108 \""..(y.."\" \100\111\101\115 \110\111\116 \101\120\105\115\116\033"))end k.Channels[y:lower()]=S S:InternalAddSpeaker(k)local x,T=pcall(function()k.eChannelJoined:Fire(S.Name,S:GetWelcomeMessageForSpeaker(k))end)if not x and T then print("\069\114\114\111\114 \106\111\105\110\105\110\103 \099\104\097\110\110\101\108\058 "..T)end end function k.LeaveChannel(k,y)if not k.Channels[y:lower()]then warn("\083\112\101\097\107\101\114 \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \""..(y.."\""))return end local S=k.Channels[y:lower()]k.Channels[y:lower()]=nil S:InternalRemoveSpeaker(k)local x,T=pcall(function()k.eChannelLeft:Fire(S.Name)end)if not x and T then print("\069\114\114\111\114 \108\101\097\118\105\110\103 \099\104\097\110\110\101\108\058 "..T)end end function k.IsInChannel(k,y)return k.Channels[y:lower()]~=nil end function k.GetChannelList(y)local k={}for y,S in pairs(y.Channels)do table.insert(k,S.Name)end return k end function k.SendMessage(T,y,k,S,x)local M=T.Channels[k:lower()]if M then M:SendMessageToSpeaker(y,T.Name,S,x)else warn(string.format("\083\112\101\097\107\101\114 \'\037\115\' \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \'\037\115\' \097\110\100 \099\097\110\110\111\116 \114\101\099\101\105\118\101 \097 \109\101\115\115\097\103\101 \105\110 \105\116\046",T.Name,k))end end function k.SendSystemMessage(x,y,k,S)local T=x.Channels[k:lower()]if T then T:SendSystemMessageToSpeaker(y,x.Name,S)else warn(string.format("\083\112\101\097\107\101\114 \'\037\115\' \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \'\037\115\' \097\110\100 \099\097\110\110\111\116 \114\101\099\101\105\118\101 \097 \115\121\115\116\101\109 \109\101\115\115\097\103\101 \105\110 \105\116\046",x.Name,k))end end function k.GetPlayer(y)return y.PlayerObj end function k.SetExtraData(S,y,k)S.ExtraData[y]=k S.eExtraDataUpdated:Fire(y,k)end function k.GetExtraData(k,y)return k.ExtraData[y]end function k.SetMainChannel(k,y)local S,x=pcall(function()k.eMainChannelSet:Fire(y)end)if not S and x then print("\069\114\114\111\114 \115\101\116\116\105\110\103 \109\097\105\110 \099\104\097\110\110\101\108\058 "..x)end end
--////////////////////////////// Methods
--//////////////////////////////////////
local function ShallowCopy(table)
	local copy = {}
	for i, v in pairs(table) do
		copy[i] = v
	end
	return copy
end

local methods = {}
methods.__index = methods

function methods:SayMessage(message, channelName, extraData)
	if self.ChatService:InternalDoProcessCommands(self.Name, message, channelName) then
		return
	end
	if not channelName then
		return
	end

	local channel = self.Channels[channelName:lower()]
	if not channel then
		error('Speaker is not in channel "' .. channelName .. '"')
	end

	local messageObj = channel:InternalPostMessage(self, message, extraData)
	if messageObj then
		local success, err = pcall(function()
			self.eSaidMessage:Fire(messageObj, channelName)
		end)
		if not success and err then
			print("Error saying message: " .. err)
		end
	end

	return messageObj
end

function methods:JoinChannel(channelName)
	if self.Channels[channelName:lower()] then
		warn('Speaker is already in channel "' .. channelName .. '"')
		return
	end

	local channel = self.ChatService:GetChannel(channelName)
	if not channel then
		error('Channel "' .. channelName .. '" does not exist!')
	end

	self.Channels[channelName:lower()] = channel
	channel:InternalAddSpeaker(self)
	local success, err = pcall(function()
		self.eChannelJoined:Fire(channel.Name, channel:GetWelcomeMessageForSpeaker(self))
	end)
	if not success and err then
		print("Error joining channel: " .. err)
	end
end

function methods:LeaveChannel(channelName)
	if not self.Channels[channelName:lower()] then
		warn('Speaker is not in channel "' .. channelName .. '"')
		return
	end

	local channel = self.Channels[channelName:lower()]

	self.Channels[channelName:lower()] = nil
	channel:InternalRemoveSpeaker(self)
	local success, err = pcall(function()
		self.eChannelLeft:Fire(channel.Name)
	end)
	if not success and err then
		print("Error leaving channel: " .. err)
	end
end

function methods:IsInChannel(channelName)
	return (self.Channels[channelName:lower()] ~= nil)
end

function methods:GetChannelList()
	local list = {}
	for i, channel in pairs(self.Channels) do
		table.insert(list, channel.Name)
	end
	return list
end

function methods:SendMessage(message, channelName, fromSpeaker, extraData)
	local channel = self.Channels[channelName:lower()]
	if channel then
		channel:SendMessageToSpeaker(message, self.Name, fromSpeaker, extraData)
	else
		warn(
			string.format(
				"Speaker '%s' is not in channel '%s' and cannot receive a message in it.",
				self.Name,
				channelName
			)
		)
	end
end

function methods:SendSystemMessage(message, channelName, extraData)
	local channel = self.Channels[channelName:lower()]
	if channel then
		channel:SendSystemMessageToSpeaker(message, self.Name, extraData)
	else
		warn(
			string.format(
				"Speaker '%s' is not in channel '%s' and cannot receive a system message in it.",
				self.Name,
				channelName
			)
		)
	end
end

function methods:GetPlayer()
	return self.PlayerObj
end

function methods:SetExtraData(key, value)
	self.ExtraData[key] = value
	self.eExtraDataUpdated:Fire(key, value)
end

function methods:GetExtraData(key)
	return self.ExtraData[key]
end

function methods:SetMainChannel(channelName)
	local success, err = pcall(function()
		self.eMainChannelSet:Fire(channelName)
	end)
	if not success and err then
		print("Error setting main channel: " .. err)
	end
end
