local function z(z)local y={}for z,H in pairs(z)do y[z]=H end return y end local y={}y.__index=y function y.SayMessage(d,z,y,H)if d.ChatService:InternalDoProcessCommands(d.Name,z,y)then return end if not y then return end local m=d.Channels[y:lower()]if not m then error("\083\112\101\097\107\101\114 \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \""..(y.."\""))end local X=m:InternalPostMessage(d,z,H)if X then local z,H=pcall(function()d.eSaidMessage:Fire(X,y)end)if not z and H then print("\069\114\114\111\114 \115\097\121\105\110\103 \109\101\115\115\097\103\101\058 "..H)end end return X end function y.JoinChannel(y,z)if y.Channels[z: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 \""..(z.."\""))return end local H=y.ChatService:GetChannel(z)if not H then error("\067\104\097\110\110\101\108 \""..(z.."\" \100\111\101\115 \110\111\116 \101\120\105\115\116\033"))end y.Channels[z:lower()]=H H:InternalAddSpeaker(y)local d,m=pcall(function()y.eChannelJoined:Fire(H.Name,H:GetWelcomeMessageForSpeaker(y))end)if not d and m then print("\069\114\114\111\114 \106\111\105\110\105\110\103 \099\104\097\110\110\101\108\058 "..m)end end function y.LeaveChannel(y,z)if not y.Channels[z:lower()]then warn("\083\112\101\097\107\101\114 \105\115 \110\111\116 \105\110 \099\104\097\110\110\101\108 \""..(z.."\""))return end local H=y.Channels[z:lower()]y.Channels[z:lower()]=nil H:InternalRemoveSpeaker(y)local d,m=pcall(function()y.eChannelLeft:Fire(H.Name)end)if not d and m then print("\069\114\114\111\114 \108\101\097\118\105\110\103 \099\104\097\110\110\101\108\058 "..m)end end function y.IsInChannel(y,z)return y.Channels[z:lower()]~=nil end function y.GetChannelList(z)local y={}for z,H in pairs(z.Channels)do table.insert(y,H.Name)end return y end function y.SendMessage(m,z,y,H,d)local X=m.Channels[y:lower()]if X then X:SendMessageToSpeaker(z,m.Name,H,d)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",m.Name,y))end end function y.SendSystemMessage(d,z,y,H)local m=d.Channels[y:lower()]if m then m:SendSystemMessageToSpeaker(z,d.Name,H)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",d.Name,y))end end function y.GetPlayer(z)return z.PlayerObj end function y.SetExtraData(H,z,y)H.ExtraData[z]=y H.eExtraDataUpdated:Fire(z,y)end function y.GetExtraData(y,z)return y.ExtraData[z]end function y.SetMainChannel(y,z)local H,d=pcall(function()y.eMainChannelSet:Fire(z)end)if not H and d 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 "..d)end end

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
