local F={}F.__index=F function getClassicChatEnabled()if ChatSettings.ClassicChatEnabled~=nil then return ChatSettings.ClassicChatEnabled end return Players.ClassicChat end function getBubbleChatEnabled()if ChatSettings.BubbleChatEnabled~=nil then return ChatSettings.BubbleChatEnabled end return Players.BubbleChat end function bubbleChatOnly()return not getClassicChatEnabled()and getBubbleChatEnabled()end function F.CreateGuiObjects(B,F)local N=Instance.new("\070\114\097\109\101")N.BackgroundTransparency=1 N.Active=ChatSettings.WindowDraggable N.Parent=F if(game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")).MouseEnabled then N.AnchorPoint=ChatSettings.DefaultPCWindowAnchorPoint else N.AnchorPoint=ChatSettings.DefaultMobileWindowAnchorPoint end local j=Instance.new("\070\114\097\109\101")j.Selectable=false j.Name="\067\104\097\116\066\097\114\080\097\114\101\110\116\070\114\097\109\101"j.BackgroundTransparency=1 j.Parent=N local x=Instance.new("\070\114\097\109\101")x.Selectable=false x.Name="\067\104\097\110\110\101\108\115\066\097\114\080\097\114\101\110\116\070\114\097\109\101"x.BackgroundTransparency=1 x.Position=UDim2.new(0,0,0,0)x.Parent=N local p=Instance.new("\070\114\097\109\101")p.Selectable=false p.Name="\067\104\097\116\067\104\097\110\110\101\108\080\097\114\101\110\116\070\114\097\109\101"p.BackgroundTransparency=1 p.BackgroundColor3=ChatSettings.BackGroundColor p.BackgroundTransparency=.6 p.BorderSizePixel=0 p.Parent=N local b=Instance.new("\073\109\097\103\101\066\117\116\116\111\110")b.Selectable=false b.Image=""b.BackgroundTransparency=.6 b.BorderSizePixel=0 b.Visible=false b.BackgroundColor3=ChatSettings.BackGroundColor b.Active=true if bubbleChatOnly()then else b.Position=UDim2.new(1,-b.AbsoluteSize.X,1,-b.AbsoluteSize.Y)end local Z=Instance.new("\073\109\097\103\101\076\097\098\101\108")Z.Selectable=false Z.Size=UDim2.new(.8,0,.8,0)Z.Position=UDim2.new(.2,0,.2,0)Z.BackgroundTransparency=1 Z.Image="\114\098\120\097\115\115\101\116\105\100\058\047\047\050\054\049\056\056\048\055\052\051"Z.Parent=b local function h()local F=N while F and not F:IsA("\083\099\114\101\101\110\071\117\105")do F=F.Parent end return F end local k=DEVICE_DESKTOP local q=h()if q.AbsoluteSize.X<=PHONE_SCREEN_WIDTH then k=DEVICE_PHONE elseif q.AbsoluteSize.X<=TABLET_SCREEN_WIDTH then k=DEVICE_TABLET end local g=false local function f()if g then return end g=true if not N:IsDescendantOf(PlayerGui)then return end local F=h()local B=ChatSettings.MinimumWindowSize local p=ChatSettings.MaximumWindowSize local b=x.AbsoluteSize.Y+j.AbsoluteSize.Y local Z=B.X.Scale*F.AbsoluteSize.X+B.X.Offset local k=math.max(B.Y.Scale*F.AbsoluteSize.Y+B.Y.Offset,b)local q=p.X.Scale*F.AbsoluteSize.X+p.X.Offset local f=p.Y.Scale*F.AbsoluteSize.Y+p.Y.Offset local L=N.AbsoluteSize.X local Y=N.AbsoluteSize.Y if L<Z then local F=UDim2.new(0,Z-L,0,0)N.Size=N.Size+F elseif L>q then local F=UDim2.new(0,q-L,0,0)N.Size=N.Size+F end if Y<k then local F=UDim2.new(0,0,0,k-Y)N.Size=N.Size+F elseif Y>f then local F=UDim2.new(0,0,0,f-Y)N.Size=N.Size+F end local n=N.AbsoluteSize.X/F.AbsoluteSize.X local D=N.AbsoluteSize.Y/F.AbsoluteSize.Y N.Size=UDim2.new(n,0,D,0)g=false end N.Changed:connect(function(F)if F=="\065\098\115\111\108\117\116\101\083\105\122\101"then f()end end)b.DragBegin:connect(function(F)N.Draggable=false end)local function L(F)if ChatSettings.WindowDraggable==false and ChatSettings.WindowResizable==false then return end local B=(F-N.AbsolutePosition)+b.AbsoluteSize N.Size=UDim2.new(0,B.X,0,B.Y)if bubbleChatOnly()then b.Position=UDim2.new(1,-b.AbsoluteSize.X,0,0)else b.Position=UDim2.new(1,-b.AbsoluteSize.X,1,-b.AbsoluteSize.Y)end end b.DragStopped:connect(function(F,B)N.Draggable=ChatSettings.WindowDraggable end)local Y=false b.Changed:connect(function(F)if F=="\065\098\115\111\108\117\116\101\080\111\115\105\116\105\111\110"and not N.Draggable then if Y then return end Y=true L(b.AbsolutePosition)Y=false end end)local function n(F)if k==DEVICE_PHONE then F=F or ChatSettings.ChatChannelsTabTextSizePhone else F=F or ChatSettings.ChatChannelsTabTextSize end local B=F local N=math.max(32,B+8)+2 return N end local function D(F)if k==DEVICE_PHONE then F=F or ChatSettings.ChatBarTextSizePhone else F=F or ChatSettings.ChatBarTextSize end local B=F local N=(B+14)+10 return N end if bubbleChatOnly()then j.Position=UDim2.new(0,0,0,0)x.Visible=false x.Active=false p.Visible=false p.Active=false local F=0 local B=0 local b=h()if k==DEVICE_PHONE then F=ChatSettings.DefaultWindowSizePhone.X.Scale B=ChatSettings.DefaultWindowSizePhone.X.Offset elseif k==DEVICE_TABLET then F=ChatSettings.DefaultWindowSizeTablet.X.Scale B=ChatSettings.DefaultWindowSizeTablet.X.Offset else F=ChatSettings.DefaultWindowSizeTablet.X.Scale B=ChatSettings.DefaultWindowSizeTablet.X.Offset end local Z=D()N.Size=UDim2.new(F,B,0,Z)N.Position=ChatSettings.DefaultWindowPosition else local F=h()if k==DEVICE_PHONE then N.Size=ChatSettings.DefaultWindowSizePhone elseif k==DEVICE_TABLET then N.Size=ChatSettings.DefaultWindowSizeTablet else N.Size=ChatSettings.DefaultWindowSizeDesktop end if(game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")).MouseEnabled then N.Position=ChatSettings.DefaultPCWindowPosition elseif(game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")).TouchEnabled then N.Position=ChatSettings.DefaultMobileWindowPosition end end if k==DEVICE_PHONE then ChatSettings.ChatWindowTextSize=ChatSettings.ChatWindowTextSizePhone ChatSettings.ChatChannelsTabTextSize=ChatSettings.ChatChannelsTabTextSizePhone ChatSettings.ChatBarTextSize=ChatSettings.ChatBarTextSizePhone end local function U(F)N.Active=F N.Draggable=F end local function W(F)b.Visible=F b.Draggable=F local B=j.Size.Y.Offset if F then j.Size=UDim2.new(1,-B-2,0,B)if not bubbleChatOnly()then j.Position=UDim2.new(0,0,1,-B)end else j.Size=UDim2.new(1,0,0,B)if not bubbleChatOnly()then j.Position=UDim2.new(0,0,1,-B)end end end local function e()local F=n()local B=D()if ChatSettings.ShowChannelsBar then p.Size=UDim2.new(1,0,1,-(((F+B)+2)+2))p.Position=UDim2.new(0,0,0,F+2)else p.Size=UDim2.new(1,0,1,-((B+2)+2))p.Position=UDim2.new(0,0,0,2)end end local function R(F)local B=n(F)x.Size=UDim2.new(1,0,0,B)e()end local function d(F)local B=D(F)j.Size=UDim2.new(1,0,0,B)if not bubbleChatOnly()then j.Position=UDim2.new(0,0,1,-B)end b.Size=UDim2.new(0,B,0,B)b.Position=UDim2.new(1,-B,1,-B)e()W(ChatSettings.WindowResizable)end local function v(F)x.Visible=F e()end R(ChatSettings.ChatChannelsTabTextSize)d(ChatSettings.ChatBarTextSize)U(ChatSettings.WindowDraggable)W(ChatSettings.WindowResizable)v(ChatSettings.ShowChannelsBar)ChatSettings.SettingsChanged:connect(function(F,B)if F=="\087\105\110\100\111\119\068\114\097\103\103\097\098\108\101"then U(B)elseif F=="\087\105\110\100\111\119\082\101\115\105\122\097\098\108\101"then W(B)elseif F=="\067\104\097\116\067\104\097\110\110\101\108\115\084\097\098\084\101\120\116\083\105\122\101"then R(B)elseif F=="\067\104\097\116\066\097\114\084\101\120\116\083\105\122\101"then d(B)elseif F=="\083\104\111\119\067\104\097\110\110\101\108\115\066\097\114"then v(B)end end)B.GuiObject=N B.GuiObjects.BaseFrame=N B.GuiObjects.ChatBarParentFrame=j B.GuiObjects.ChannelsBarParentFrame=x B.GuiObjects.ChatChannelParentFrame=p B.GuiObjects.ChatResizerFrame=b B.GuiObjects.ResizeIcon=Z B:AnimGuiObjects()end function F.GetChatBar(F)return F.ChatBar end function F.RegisterChatBar(B,F)B.ChatBar=F B.ChatBar:CreateGuiObjects(B.GuiObjects.ChatBarParentFrame)end function F.RegisterChannelsBar(B,F)B.ChannelsBar=F B.ChannelsBar:CreateGuiObjects(B.GuiObjects.ChannelsBarParentFrame)end function F.RegisterMessageLogDisplay(B,F)B.MessageLogDisplay=F B.MessageLogDisplay.GuiObject.Parent=B.GuiObjects.ChatChannelParentFrame end function F.AddChannel(B,F)if B:GetChannel(F)then error("\067\104\097\110\110\101\108 \'"..(F.."\' \097\108\114\101\097\100\121 \101\120\105\115\116\115\033"))return end local N=moduleChatChannel.new(F,B.MessageLogDisplay)B.Channels[F:lower()]=N N:SetActive(false)local j=B.ChannelsBar:AddChannelTab(F)j.NameTag.MouseButton1Click:connect(function()B:SwitchCurrentChannel(F)end)N:RegisterChannelTab(j)return N end function F.GetFirstChannel(F)for F,B in pairs(F.Channels)do return B end return nil end function F.RemoveChannel(B,F)if not B:GetChannel(F)then error("\067\104\097\110\110\101\108 \'"..(F.."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\033"))end local N=F:lower()local j=false if B.Channels[N]==B:GetCurrentChannel()then j=true B:SwitchCurrentChannel(nil)end B.Channels[N]:Destroy()B.Channels[N]=nil B.ChannelsBar:RemoveChannelTab(F)if j then local F=B:GetChannel(ChatSettings.GeneralChannelName)~=nil local j=N==ChatSettings.GeneralChannelName:lower()local x=nil if F and not j then x=ChatSettings.GeneralChannelName else local F=B:GetFirstChannel()x=F and F.Name or nil end B:SwitchCurrentChannel(x)end if not ChatSettings.ShowChannelsBar then if B.ChatBar.TargetChannel==F then B.ChatBar:SetChannelTarget(ChatSettings.GeneralChannelName)end end end function F.GetChannel(B,F)return F and B.Channels[F:lower()]or nil end function F.GetTargetMessageChannel(F)if not ChatSettings.ShowChannelsBar then return F.ChatBar.TargetChannel else local B=F:GetCurrentChannel()return B and B.Name end end function F.GetCurrentChannel(F)return F.CurrentChannel end function F.SwitchCurrentChannel(B,F)if not ChatSettings.ShowChannelsBar then local N=B:GetChannel(F)if N then B.ChatBar:SetChannelTarget(N.Name)end F=ChatSettings.GeneralChannelName end local N=B:GetCurrentChannel()local j=B:GetChannel(F)if j==nil then error(string.format("\067\104\097\110\110\101\108 \'\037\115\' \100\111\101\115 \110\111\116 \101\120\105\115\116\046",F))end if j~=N then if N then N:SetActive(false)local F=B.ChannelsBar:GetChannelTab(N.Name)F:SetActive(false)end if j then j:SetActive(true)local F=B.ChannelsBar:GetChannelTab(j.Name)F:SetActive(true)end B.CurrentChannel=j end end function F.UpdateFrameVisibility(F)F.GuiObject.Visible=F.Visible and F.CoreGuiEnabled end function F.GetVisible(F)return F.Visible end function F.SetVisible(B,F)B.Visible=F B:UpdateFrameVisibility()end function F.GetCoreGuiEnabled(F)return F.CoreGuiEnabled end function F.SetCoreGuiEnabled(B,F)B.CoreGuiEnabled=F B:UpdateFrameVisibility()end function F.EnableResizable(F)F.GuiObjects.ChatResizerFrame.Active=true end function F.DisableResizable(F)F.GuiObjects.ChatResizerFrame.Active=false end function F.FadeOutBackground(B,F)B.ChannelsBar:FadeOutBackground(F)B.MessageLogDisplay:FadeOutBackground(F)B.ChatBar:FadeOutBackground(F)B.AnimParams.Background_TargetTransparency=1 B.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(F)end function F.FadeInBackground(B,F)B.ChannelsBar:FadeInBackground(F)B.MessageLogDisplay:FadeInBackground(F)B.ChatBar:FadeInBackground(F)B.AnimParams.Background_TargetTransparency=.6 B.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(F)end function F.FadeOutText(B,F)B.MessageLogDisplay:FadeOutText(F)B.ChannelsBar:FadeOutText(F)end function F.FadeInText(B,F)B.MessageLogDisplay:FadeInText(F)B.ChannelsBar:FadeInText(F)end function F.AnimGuiObjects(F)F.GuiObjects.ChatChannelParentFrame.BackgroundTransparency=F.AnimParams.Background_CurrentTransparency F.GuiObjects.ChatResizerFrame.BackgroundTransparency=F.AnimParams.Background_CurrentTransparency F.GuiObjects.ResizeIcon.ImageTransparency=F.AnimParams.Background_CurrentTransparency end function F.InitializeAnimParams(F)F.AnimParams.Background_TargetTransparency=.6 F.AnimParams.Background_CurrentTransparency=.6 F.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(0)end function F.Update(B,F)B.ChatBar:Update(F)B.ChannelsBar:Update(F)B.MessageLogDisplay:Update(F)B.AnimParams.Background_CurrentTransparency=CurveUtil:Expt(B.AnimParams.Background_CurrentTransparency,B.AnimParams.Background_TargetTransparency,B.AnimParams.Background_NormalizedExptValue,F)B:AnimGuiObjects()end

local methods = {}
methods.__index = methods

function getClassicChatEnabled()
	if ChatSettings.ClassicChatEnabled ~= nil then
		return ChatSettings.ClassicChatEnabled
	end
	return Players.ClassicChat
end

function getBubbleChatEnabled()
	if ChatSettings.BubbleChatEnabled ~= nil then
		return ChatSettings.BubbleChatEnabled
	end
	return Players.BubbleChat
end

function bubbleChatOnly()
 	return not getClassicChatEnabled() and getBubbleChatEnabled()
end

function methods:CreateGuiObjects(targetParent)
	local BaseFrame = Instance.new("Frame")
	BaseFrame.BackgroundTransparency = 1
	BaseFrame.Active = ChatSettings.WindowDraggable
	BaseFrame.Parent = targetParent
	if game:GetService("UserInputService").MouseEnabled then
		BaseFrame.AnchorPoint = ChatSettings.DefaultPCWindowAnchorPoint
	else
		BaseFrame.AnchorPoint = ChatSettings.DefaultMobileWindowAnchorPoint
	end
	

	local ChatBarParentFrame = Instance.new("Frame")
	ChatBarParentFrame.Selectable = false
	ChatBarParentFrame.Name = "ChatBarParentFrame"
	ChatBarParentFrame.BackgroundTransparency = 1
	ChatBarParentFrame.Parent = BaseFrame

	local ChannelsBarParentFrame = Instance.new("Frame")
	ChannelsBarParentFrame.Selectable = false
	ChannelsBarParentFrame.Name = "ChannelsBarParentFrame"
	ChannelsBarParentFrame.BackgroundTransparency = 1
	ChannelsBarParentFrame.Position = UDim2.new(0, 0, 0, 0)
	ChannelsBarParentFrame.Parent = BaseFrame

	local ChatChannelParentFrame = Instance.new("Frame")
	ChatChannelParentFrame.Selectable = false
	ChatChannelParentFrame.Name = "ChatChannelParentFrame"
	ChatChannelParentFrame.BackgroundTransparency = 1
	ChatChannelParentFrame.BackgroundColor3 = ChatSettings.BackGroundColor
	ChatChannelParentFrame.BackgroundTransparency = 0.6
	ChatChannelParentFrame.BorderSizePixel = 0
	ChatChannelParentFrame.Parent = BaseFrame

	local ChatResizerFrame = Instance.new("ImageButton")
	ChatResizerFrame.Selectable = false
	ChatResizerFrame.Image = ""
	ChatResizerFrame.BackgroundTransparency = 0.6
	ChatResizerFrame.BorderSizePixel = 0
	ChatResizerFrame.Visible = false
	ChatResizerFrame.BackgroundColor3 = ChatSettings.BackGroundColor
	ChatResizerFrame.Active = true
	if bubbleChatOnly() then
	-- 	ChatResizerFrame.Position = UDim2.new(1, -ChatResizerFrame.AbsoluteSize.X, 0, 0)
	else
		ChatResizerFrame.Position = UDim2.new(1, -ChatResizerFrame.AbsoluteSize.X, 1, -ChatResizerFrame.AbsoluteSize.Y)
	end
	-- ChatResizerFrame.Parent = BaseFrame

	local ResizeIcon = Instance.new("ImageLabel")
	ResizeIcon.Selectable = false
	ResizeIcon.Size = UDim2.new(0.8, 0, 0.8, 0)
	ResizeIcon.Position = UDim2.new(0.2, 0, 0.2, 0)
	ResizeIcon.BackgroundTransparency = 1
	ResizeIcon.Image = "rbxassetid://261880743"
	ResizeIcon.Parent = ChatResizerFrame

	local function GetScreenGuiParent()
		--// Travel up parent list until you find the ScreenGui that the chat window is parented to
		local screenGuiParent = BaseFrame
		while (screenGuiParent and not screenGuiParent:IsA("ScreenGui")) do
			screenGuiParent = screenGuiParent.Parent
		end

		return screenGuiParent
	end


	local deviceType = DEVICE_DESKTOP

	local screenGuiParent = GetScreenGuiParent()
	if (screenGuiParent.AbsoluteSize.X <= PHONE_SCREEN_WIDTH) then
		deviceType = DEVICE_PHONE

	elseif (screenGuiParent.AbsoluteSize.X <= TABLET_SCREEN_WIDTH) then
		deviceType = DEVICE_TABLET

	end

	local checkSizeLock = false
	local function doCheckSizeBounds()
		if (checkSizeLock) then return end
		checkSizeLock = true

		if (not BaseFrame:IsDescendantOf(PlayerGui)) then return end

		local screenGuiParent = GetScreenGuiParent()

		local minWinSize = ChatSettings.MinimumWindowSize
		local maxWinSize = ChatSettings.MaximumWindowSize

		local forceMinY = ChannelsBarParentFrame.AbsoluteSize.Y + ChatBarParentFrame.AbsoluteSize.Y

		local minSizePixelX = (minWinSize.X.Scale * screenGuiParent.AbsoluteSize.X) + minWinSize.X.Offset
		local minSizePixelY = math.max((minWinSize.Y.Scale * screenGuiParent.AbsoluteSize.Y) + minWinSize.Y.Offset, forceMinY)

		local maxSizePixelX = (maxWinSize.X.Scale * screenGuiParent.AbsoluteSize.X) + maxWinSize.X.Offset
		local maxSizePixelY = (maxWinSize.Y.Scale * screenGuiParent.AbsoluteSize.Y) + maxWinSize.Y.Offset

		local absSizeX = BaseFrame.AbsoluteSize.X
		local absSizeY = BaseFrame.AbsoluteSize.Y

		if (absSizeX < minSizePixelX) then
			local offset = UDim2.new(0, minSizePixelX - absSizeX, 0, 0)
			BaseFrame.Size = BaseFrame.Size + offset

		elseif (absSizeX > maxSizePixelX) then
			local offset = UDim2.new(0, maxSizePixelX - absSizeX, 0, 0)
			BaseFrame.Size = BaseFrame.Size + offset

		end

		if (absSizeY < minSizePixelY) then
			local offset = UDim2.new(0, 0, 0, minSizePixelY - absSizeY)
			BaseFrame.Size = BaseFrame.Size + offset

		elseif (absSizeY > maxSizePixelY) then
			local offset = UDim2.new(0, 0, 0, maxSizePixelY - absSizeY)
			BaseFrame.Size = BaseFrame.Size + offset

		end

		local xScale = BaseFrame.AbsoluteSize.X / screenGuiParent.AbsoluteSize.X
		local yScale = BaseFrame.AbsoluteSize.Y / screenGuiParent.AbsoluteSize.Y
		BaseFrame.Size = UDim2.new(xScale, 0, yScale, 0)

		checkSizeLock = false
	end


	BaseFrame.Changed:connect(function(prop)
		if (prop == "AbsoluteSize") then
			doCheckSizeBounds()
		end
	end)



	ChatResizerFrame.DragBegin:connect(function(startUdim)
		BaseFrame.Draggable = false
	end)

	local function UpdatePositionFromDrag(atPos)
		if ChatSettings.WindowDraggable == false and ChatSettings.WindowResizable == false then
			return
		end
		local newSize = atPos - BaseFrame.AbsolutePosition + ChatResizerFrame.AbsoluteSize
		BaseFrame.Size = UDim2.new(0, newSize.X, 0, newSize.Y)
		if bubbleChatOnly() then
			ChatResizerFrame.Position = UDim2.new(1, -ChatResizerFrame.AbsoluteSize.X, 0, 0)
		else
			ChatResizerFrame.Position = UDim2.new(1, -ChatResizerFrame.AbsoluteSize.X, 1, -ChatResizerFrame.AbsoluteSize.Y)
		end
	end

	ChatResizerFrame.DragStopped:connect(function(endX, endY)
		BaseFrame.Draggable = ChatSettings.WindowDraggable
		--UpdatePositionFromDrag(Vector2.new(endX, endY))
	end)

	local resizeLock = false
	ChatResizerFrame.Changed:connect(function(prop)
		if (prop == "AbsolutePosition" and not BaseFrame.Draggable) then
			if (resizeLock) then return end
			resizeLock = true

			UpdatePositionFromDrag(ChatResizerFrame.AbsolutePosition)

			resizeLock = false
		end
	end)

	local function CalculateChannelsBarPixelSize(textSize)
		if (deviceType == DEVICE_PHONE) then
			textSize = textSize or ChatSettings.ChatChannelsTabTextSizePhone
		else
			textSize = textSize or ChatSettings.ChatChannelsTabTextSize
		end

		local channelsBarTextYSize = textSize
		local chatChannelYSize = math.max(32, channelsBarTextYSize + 8) + 2

		return chatChannelYSize
	end

	local function CalculateChatBarPixelSize(textSize)
		if (deviceType == DEVICE_PHONE) then
			textSize = textSize or ChatSettings.ChatBarTextSizePhone
		else
			textSize = textSize or ChatSettings.ChatBarTextSize
		end

		local chatBarTextSizeY = textSize
		local chatBarYSize = chatBarTextSizeY + (7 * 2) + (5 * 2)

		return chatBarYSize
	end

	if bubbleChatOnly() then
		ChatBarParentFrame.Position = UDim2.new(0, 0, 0, 0)
		ChannelsBarParentFrame.Visible = false
		ChannelsBarParentFrame.Active = false
		ChatChannelParentFrame.Visible = false
		ChatChannelParentFrame.Active = false

		local useXScale = 0
		local useXOffset = 0

		local screenGuiParent = GetScreenGuiParent()

		if (deviceType == DEVICE_PHONE) then
			useXScale = ChatSettings.DefaultWindowSizePhone.X.Scale
			useXOffset = ChatSettings.DefaultWindowSizePhone.X.Offset

		elseif (deviceType == DEVICE_TABLET) then
			useXScale = ChatSettings.DefaultWindowSizeTablet.X.Scale
			useXOffset = ChatSettings.DefaultWindowSizeTablet.X.Offset

		else
			useXScale = ChatSettings.DefaultWindowSizeTablet.X.Scale
			useXOffset = ChatSettings.DefaultWindowSizeTablet.X.Offset

		end

		local chatBarYSize = CalculateChatBarPixelSize()

		BaseFrame.Size = UDim2.new(useXScale, useXOffset, 0, chatBarYSize)
		BaseFrame.Position = ChatSettings.DefaultWindowPosition

	else

		local screenGuiParent = GetScreenGuiParent()

		if (deviceType == DEVICE_PHONE) then
			BaseFrame.Size = ChatSettings.DefaultWindowSizePhone

		elseif (deviceType == DEVICE_TABLET) then
			BaseFrame.Size = ChatSettings.DefaultWindowSizeTablet

		else
			BaseFrame.Size = ChatSettings.DefaultWindowSizeDesktop

		end
		if game:GetService("UserInputService").MouseEnabled then
		BaseFrame.Position = ChatSettings.DefaultPCWindowPosition
		elseif game:GetService("UserInputService").TouchEnabled then
		BaseFrame.Position = ChatSettings.DefaultMobileWindowPosition
		end

	end

	if (deviceType == DEVICE_PHONE) then
		ChatSettings.ChatWindowTextSize = ChatSettings.ChatWindowTextSizePhone
		ChatSettings.ChatChannelsTabTextSize = ChatSettings.ChatChannelsTabTextSizePhone
		ChatSettings.ChatBarTextSize = ChatSettings.ChatBarTextSizePhone
	end

	local function UpdateDraggable(enabled)
		BaseFrame.Active = enabled
		BaseFrame.Draggable = enabled
	end

	local function UpdateResizable(enabled)
		ChatResizerFrame.Visible = enabled
		ChatResizerFrame.Draggable = enabled

		local frameSizeY = ChatBarParentFrame.Size.Y.Offset

		if (enabled) then
			ChatBarParentFrame.Size = UDim2.new(1, -frameSizeY - 2, 0, frameSizeY)
			if not bubbleChatOnly() then
				ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -frameSizeY)
			end
		else
			ChatBarParentFrame.Size = UDim2.new(1, 0, 0, frameSizeY)
			if not bubbleChatOnly() then
				ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -frameSizeY)
			end
		end
	end

	local function UpdateChatChannelParentFrameSize()
		local channelsBarSize = CalculateChannelsBarPixelSize()
		local chatBarSize = CalculateChatBarPixelSize()

		if (ChatSettings.ShowChannelsBar) then
			ChatChannelParentFrame.Size = UDim2.new(1, 0, 1, -(channelsBarSize + chatBarSize + 2 + 2))
			ChatChannelParentFrame.Position = UDim2.new(0, 0, 0, channelsBarSize + 2)

		else
			ChatChannelParentFrame.Size = UDim2.new(1, 0, 1, -(chatBarSize + 2 + 2))
			ChatChannelParentFrame.Position = UDim2.new(0, 0, 0, 2)

		end
	end

	local function UpdateChatChannelsTabTextSize(size)
		local channelsBarSize = CalculateChannelsBarPixelSize(size)
		ChannelsBarParentFrame.Size = UDim2.new(1, 0, 0, channelsBarSize)

		UpdateChatChannelParentFrameSize()
	end

	local function UpdateChatBarTextSize(size)
		local chatBarSize = CalculateChatBarPixelSize(size)

		ChatBarParentFrame.Size = UDim2.new(1, 0, 0, chatBarSize)
		if not bubbleChatOnly() then
			ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -chatBarSize)
		end

		ChatResizerFrame.Size = UDim2.new(0, chatBarSize, 0, chatBarSize)
		ChatResizerFrame.Position = UDim2.new(1, -chatBarSize, 1, -chatBarSize)

		UpdateChatChannelParentFrameSize()
		UpdateResizable(ChatSettings.WindowResizable)
	end

	local function UpdateShowChannelsBar(enabled)
		ChannelsBarParentFrame.Visible = enabled
		UpdateChatChannelParentFrameSize()
	end

	UpdateChatChannelsTabTextSize(ChatSettings.ChatChannelsTabTextSize)
	UpdateChatBarTextSize(ChatSettings.ChatBarTextSize)
	UpdateDraggable(ChatSettings.WindowDraggable)
	UpdateResizable(ChatSettings.WindowResizable)
	UpdateShowChannelsBar(ChatSettings.ShowChannelsBar)

	ChatSettings.SettingsChanged:connect(function(setting, value)
		if (setting == "WindowDraggable") then
			UpdateDraggable(value)

		elseif (setting == "WindowResizable") then
			UpdateResizable(value)

		elseif (setting == "ChatChannelsTabTextSize") then
			UpdateChatChannelsTabTextSize(value)

		elseif (setting == "ChatBarTextSize") then
			UpdateChatBarTextSize(value)

		elseif (setting == "ShowChannelsBar") then
			UpdateShowChannelsBar(value)

		end
	end)

	self.GuiObject = BaseFrame

	self.GuiObjects.BaseFrame = BaseFrame
	self.GuiObjects.ChatBarParentFrame = ChatBarParentFrame
	self.GuiObjects.ChannelsBarParentFrame = ChannelsBarParentFrame
	self.GuiObjects.ChatChannelParentFrame = ChatChannelParentFrame
	self.GuiObjects.ChatResizerFrame = ChatResizerFrame
	self.GuiObjects.ResizeIcon = ResizeIcon
	self:AnimGuiObjects()
end

function methods:GetChatBar()
	return self.ChatBar
end

function methods:RegisterChatBar(ChatBar)
	self.ChatBar = ChatBar
	self.ChatBar:CreateGuiObjects(self.GuiObjects.ChatBarParentFrame)
end

function methods:RegisterChannelsBar(ChannelsBar)
	self.ChannelsBar = ChannelsBar
	self.ChannelsBar:CreateGuiObjects(self.GuiObjects.ChannelsBarParentFrame)
end

function methods:RegisterMessageLogDisplay(MessageLogDisplay)
	self.MessageLogDisplay = MessageLogDisplay
	self.MessageLogDisplay.GuiObject.Parent = self.GuiObjects.ChatChannelParentFrame
end

function methods:AddChannel(channelName)
	if (self:GetChannel(channelName)) then
		error("Channel '" .. channelName .. "' already exists!")
		return
	end

	local channel = moduleChatChannel.new(channelName, self.MessageLogDisplay)
	self.Channels[channelName:lower()] = channel

	channel:SetActive(false)

	local tab = self.ChannelsBar:AddChannelTab(channelName)
	tab.NameTag.MouseButton1Click:connect(function()
		self:SwitchCurrentChannel(channelName)
	end)

	channel:RegisterChannelTab(tab)

	return channel
end

function methods:GetFirstChannel()
	--// Channels are not indexed numerically, so this function is necessary.
	--// Grabs and returns the first channel it happens to, or nil if none exist.
	for i, v in pairs(self.Channels) do
		return v
	end
	return nil
end

function methods:RemoveChannel(channelName)
	if (not self:GetChannel(channelName)) then
		error("Channel '" .. channelName .. "' does not exist!")
	end

	local indexName = channelName:lower()

	local needsChannelSwitch = false
	if (self.Channels[indexName] == self:GetCurrentChannel()) then
		needsChannelSwitch = true

		self:SwitchCurrentChannel(nil)
	end

	self.Channels[indexName]:Destroy()
	self.Channels[indexName] = nil

	self.ChannelsBar:RemoveChannelTab(channelName)

	if (needsChannelSwitch) then
		local generalChannelExists = (self:GetChannel(ChatSettings.GeneralChannelName) ~= nil)
		local removingGeneralChannel = (indexName == ChatSettings.GeneralChannelName:lower())

		local targetSwitchChannel = nil

		if (generalChannelExists and not removingGeneralChannel) then
			targetSwitchChannel = ChatSettings.GeneralChannelName
		else
			local firstChannel = self:GetFirstChannel()
			targetSwitchChannel = (firstChannel and firstChannel.Name or nil)
		end

		self:SwitchCurrentChannel(targetSwitchChannel)
	end

	if not ChatSettings.ShowChannelsBar then
		if self.ChatBar.TargetChannel == channelName then
			self.ChatBar:SetChannelTarget(ChatSettings.GeneralChannelName)
		end
	end
end

function methods:GetChannel(channelName)
	return channelName and self.Channels[channelName:lower()] or nil
end

function methods:GetTargetMessageChannel()
	if (not ChatSettings.ShowChannelsBar) then
		return self.ChatBar.TargetChannel
	else
		local curChannel = self:GetCurrentChannel()
		return curChannel and curChannel.Name
	end
end

function methods:GetCurrentChannel()
	return self.CurrentChannel
end

function methods:SwitchCurrentChannel(channelName)
	if (not ChatSettings.ShowChannelsBar) then
		local targ = self:GetChannel(channelName)
		if (targ) then
			self.ChatBar:SetChannelTarget(targ.Name)
		end

		channelName = ChatSettings.GeneralChannelName
	end

	local cur = self:GetCurrentChannel()
	local new = self:GetChannel(channelName)
	if new == nil then
		error(string.format("Channel '%s' does not exist.", channelName))
	end

	if (new ~= cur) then
		if (cur) then
			cur:SetActive(false)
			local tab = self.ChannelsBar:GetChannelTab(cur.Name)
			tab:SetActive(false)
		end

		if (new) then
			new:SetActive(true)
			local tab = self.ChannelsBar:GetChannelTab(new.Name)
			tab:SetActive(true)
		end

		self.CurrentChannel = new
	end

end

function methods:UpdateFrameVisibility()
	self.GuiObject.Visible = (self.Visible and self.CoreGuiEnabled)
end

function methods:GetVisible()
	return self.Visible
end

function methods:SetVisible(visible)
	self.Visible = visible
	self:UpdateFrameVisibility()
end

function methods:GetCoreGuiEnabled()
	return self.CoreGuiEnabled
end

function methods:SetCoreGuiEnabled(enabled)
	self.CoreGuiEnabled = enabled
	self:UpdateFrameVisibility()
end

function methods:EnableResizable()
	self.GuiObjects.ChatResizerFrame.Active = true
end

function methods:DisableResizable()
	self.GuiObjects.ChatResizerFrame.Active = false
end

function methods:FadeOutBackground(duration)
	self.ChannelsBar:FadeOutBackground(duration)
	self.MessageLogDisplay:FadeOutBackground(duration)
	self.ChatBar:FadeOutBackground(duration)

	self.AnimParams.Background_TargetTransparency = 1
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration)
end

function methods:FadeInBackground(duration)
	self.ChannelsBar:FadeInBackground(duration)
	self.MessageLogDisplay:FadeInBackground(duration)
	self.ChatBar:FadeInBackground(duration)

	self.AnimParams.Background_TargetTransparency = 0.6
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration)
end

function methods:FadeOutText(duration)
	self.MessageLogDisplay:FadeOutText(duration)
	self.ChannelsBar:FadeOutText(duration)
end

function methods:FadeInText(duration)
	self.MessageLogDisplay:FadeInText(duration)
	self.ChannelsBar:FadeInText(duration)
end

function methods:AnimGuiObjects()
	self.GuiObjects.ChatChannelParentFrame.BackgroundTransparency = self.AnimParams.Background_CurrentTransparency
	self.GuiObjects.ChatResizerFrame.BackgroundTransparency = self.AnimParams.Background_CurrentTransparency
	self.GuiObjects.ResizeIcon.ImageTransparency = self.AnimParams.Background_CurrentTransparency
end

function methods:InitializeAnimParams()
	self.AnimParams.Background_TargetTransparency = 0.6
	self.AnimParams.Background_CurrentTransparency = 0.6
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(0)
end

function methods:Update(dtScale)
	self.ChatBar:Update(dtScale)
	self.ChannelsBar:Update(dtScale)
	self.MessageLogDisplay:Update(dtScale)

	self.AnimParams.Background_CurrentTransparency = CurveUtil:Expt(
			self.AnimParams.Background_CurrentTransparency,
			self.AnimParams.Background_TargetTransparency,
			self.AnimParams.Background_NormalizedExptValue,
			dtScale
	)

	self:AnimGuiObjects()
end
