
NextTimeCanChat = 0;
NextTimeCanChatOOC = 0;

function msgSetNextChatTime( msg )

	NextTimeCanChat = CurTime() + msg:ReadFloat();

end
usermessage.Hook( "SNCT", msgSetNextChatTime );


function msgSetNextChatTimeOOC( msg )

	NextTimeCanChatOOC = CurTime() + msg:ReadFloat();

end
usermessage.Hook( "SNCTOOC", msgSetNextChatTimeOOC );

surface.CreateFont( "akbar", 16, 800, true, false, "NewChatFont" );
surface.CreateFont( "akbar", 13, 800, true, false, "ChatFontSub" );
surface.CreateFont( "akbar", 8, 800, true, false, "SecretMsgFont" );
surface.CreateFont( "akbar", 20, 1600, true, false, "BigChatFont" );
surface.CreateFont( "akbar", 32, 1600, true, false, "GiantChatFont" );
surface.CreateFont( "akbar", 11, 400, true, false, "SmallChatFont" );

if( ChatBox ) then

	ChatBox:Remove();
	ChatBox = nil;

end

if( InnerChatBox ) then

	for k, v in pairs( InnerChatBox ) do
	
		v:Remove();
		InnerChatBox[k] = nil;
		
	end

end

ChatTabs = { }
InnerChatBox = { }

CurrentChatTab = 1;

ChatBoxVisible = false;

function OpenChatBox()

	if( ChatBoxVisible ) then return; end

	ChatBox:SetVisible( true );
	InnerChatBox[CurrentChatTab]:SetVisible( true );
	ChatBoxVisible = true;
	
	gui.EnableScreenClicker( true );
	
	FindVisibleChat( CurrentChatTab );
	
	InnerChatBox[CurrentChatTab].Paint = InnerChatBox[CurrentChatTab].OriginalPaint;
	
	if( InnerChatBox[CurrentChatTab].ScrollUpButton ) then
		InnerChatBox[CurrentChatTab].ScrollUpButton:SetVisible( true );
	end
	
	if( InnerChatBox[CurrentChatTab].ScrollDownButton ) then
		InnerChatBox[CurrentChatTab].ScrollDownButton:SetVisible( true );
	end

	if( InnerChatBox[CurrentChatTab].VScrollBar ) then
		InnerChatBox[CurrentChatTab].VScrollBar:SetVisible( true );
	end
	
	
end

function CloseChatBox()

	if( not ChatBoxVisible ) then return; end
	
	RunConsoleCommand( "eng_isnottyping", "" );
	
	FindVisibleChat( CurrentChatTab );

	ChatBox:SetVisible( false );
	ChatBoxVisible = false;
	
	InnerChatBox[CurrentChatTab].Paint = InnerChatBox[CurrentChatTab].PaintHook;
	
	if( InnerChatBox[CurrentChatTab].ScrollUpButton ) then
		InnerChatBox[CurrentChatTab].ScrollUpButton:SetVisible( false );
	end
	
	if( InnerChatBox[CurrentChatTab].ScrollDownButton ) then
		InnerChatBox[CurrentChatTab].ScrollDownButton:SetVisible( false );
	end

	if( InnerChatBox[CurrentChatTab].VScrollBar ) then
		InnerChatBox[CurrentChatTab].VScrollBar:SetVisible( false );
	end

end

function ToggleChatBox()

	ChatBoxVisible = !ChatBoxVisible;
	
	if( ChatBoxVisible ) then
	
		OpenChatBox();
	
	else
	
		CloseChatBox();
	
	end

end

function PrintGreenPrivateMessage( msg )

	local text = msg:ReadString();

	AddChat( { 1, 5 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 160, 255, 160, 255 ) );
	

end
usermessage.Hook( "PrivateMessage", PrintGreenPrivateMessage );

OIFY_COLOURS = {
Vector(0, 191, 255, 255),
Vector(124, 252, 0, 255),
Vector(255, 255, 0, 255),
Vector(255, 0, 0, 255),
Vector(255, 20, 147, 255)
}

function PrintOIFYMessage( msg )

	local text = msg:ReadString();

	AddChat( { 8 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), OIFY_COLOURS[math.random(1, #OIFY_COLOURS)] );
	

end
usermessage.Hook( "OIFYMessage", PrintOIFYMessage );

function PrintPinkAdminMessage( msg )

	local text = msg:ReadString();

	AddChat( { 1, 4 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 255, 105, 180, 255 ) );

end
usermessage.Hook( "AdminMessage", PrintPinkAdminMessage );

function PrintICGlobalMessage( msg )

	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 255, 255, 255, 255 ) );

end
usermessage.Hook( "ICGlobalMessage", PrintICGlobalMessage );

function PrintBroadCast( msg )

	local name = msg:ReadString()
	local text = msg:ReadString();
	

	AddChat( { 1, 3 }, name, text, "BigChatFont", Color( 200, 200, 200, 255 ), Color( 255, 255, 255, 255 ) );

end
usermessage.Hook( "msgBroadcast", PrintICGlobalMessage );

function ChVortigese( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();
	
	AddChat( { 1, 3 }, name, text, "NewChatFont", Color( 89, 1, 1, 255 ), Color( 89, 1, 1, 255 ) );

end
usermessage.Hook( "ChVortigese", ChVortigese );	

function PrintDispatch( msg )

	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", text, "BigChatFont", Color( 1, 121, 111, 255 ), Color( 1, 121, 111, 255 ) );

end
usermessage.Hook( "msgDispatch", PrintDispatch );

function PrintEvent( msg )

	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", text, "BigChatFont", Color( 255, 102, 0, 255 ), Color( 255, 102, 0, 255 ) );

end
usermessage.Hook( "msgEv", PrintEvent );

function PrintAdv( msg )

	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", text, "BigChatFont", Color( 200, 200, 200, 255 ), Color( 255, 255, 255, 255 ) );

end
usermessage.Hook( "msgAdv", PrintAdv );

function PrintRadioMessage( msg )

	local text = msg:ReadString();

	AddChat( { 6 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 200, 200, 200, 255 ) );

end
usermessage.Hook( "RadioMessage", PrintRadioMessage );

function PrintBlueMessage( msg )

	local text = msg:ReadString();

	AddChat( { 1, 2, 7 }, "", text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 200, 200, 200, 255 ) );

end
usermessage.Hook( "PrintBlueMessage", PrintBlueMessage );

function SayLocalOOCChat( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();

	AddChat( { 1, 3 }, name, text, "NewChatFont", Color( 200, 200, 200, 255 ), Color( 200, 200, 200, 255 ) );

end
usermessage.Hook( "LocalOOCChat", SayLocalOOCChat );

function SayICAction( msg )

	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", text, "NewChatFont", Color( 131, 206, 251, 255 ), Color( 131, 196, 251, 255 ) );
	

end
usermessage.Hook( "SayICAction", SayICAction );

function DoICAction( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();

	AddChat( { 1, 3 }, "", name .. text, "NewChatFont", Color( 131, 196, 251, 255 ), Color( 131, 196, 251, 255 ) );
	

end
usermessage.Hook( "ICAction", DoICAction );

function SayOOCChat( msg )

	local name = msg:ReadString();
	local color = team.GetColor( msg:ReadShort() );
	local text = msg:ReadString();

	AddChat( { 1, 2 }, name, text, "NewChatFont", color, Color( 200, 200, 200, 255 ) );


end
usermessage.Hook( "OOCChat", SayOOCChat );

function SayICChat( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();

	AddChat( { 1, 3 }, name, text, "NewChatFont", Color( 91, 166, 221, 255 ), Color( 91, 166, 221, 255 ) );

end
usermessage.Hook( "ICChat", SayICChat );

function YellICChat( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();

	AddChat( { 1, 3 }, name, "[Y]" .. text, "BigChatFont", Color( 91, 166, 221, 255 ), Color( 91, 166, 221, 255 ) );

end
usermessage.Hook( "YellICChat", YellICChat );

function WhisperICChat( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();

	AddChat( { 1, 3 }, name, "[w]" .. text, "SmallChatFont", Color( 91, 166, 221, 255 ), Color( 91, 166, 221, 255 ) );

end
usermessage.Hook( "WhisperICChat", WhisperICChat );

function ConsoleChat( msg )

	local text = msg:ReadString();

	AddChat( { 1, 4 }, "Console", text, "NewChatFont", Color( 232, 20, 225, 255 ), Color( 200, 200, 200, 255 ) );

end
usermessage.Hook( "ConsoleChat", ConsoleChat );

function PlyCon( msg )

	local name = msg:ReadString();
	
	AddChat( { 7 }, "", name .. " has connected", "NewChatFont", Color( 232, 20, 225, 255 ), Color( 255, 255, 149, 255 ) );
	

end
usermessage.Hook( "PlyCon", PlyCon );

function MiscCon( msg )

	local text = msg:ReadString();
	
	AddChat( { 1, 7 }, "", text, "NewChatFont", Color( 232, 20, 225, 255 ), Color( 255, 255, 149, 255 ) );
		

end
usermessage.Hook( "MiscCon", MiscCon );

function AYell( msg )

	local name = msg:ReadString();
	local text = msg:ReadString();
	
	AddChat( { 1, 4 }, name, text, "GiantChatFont", Color( 255, 255, 255, 255 ), Color( 232, 20, 20, 255 ) );
		

end
usermessage.Hook( "Ayell", AYell );

function PlyDisc( msg )

	local rpname = msg:ReadString();
	local name = msg:ReadString();
	local steamid = msg:ReadString();
	
	AddChat( { 7 }, "", rpname .. " (SF: " .. name .. " ID: " .. steamid .. ") has left the server", "NewChatFont", Color( 232, 20, 225, 255 ), Color( 255, 255, 149, 255 ) );
	

end
usermessage.Hook( "PlyDisc", PlyDisc );

function OOCDelayChange( msg )

	local name = msg:ReadString();
	local delay = msg:ReadFloat();
	
	AddChat( { 1, 7 }, "", name .. " has set the OOC delay to " .. delay, "NewChatFont", Color( 232, 20, 225, 255 ), Color( 255, 255, 149, 255 ) );
		
end
usermessage.Hook( "ODC", OOCDelayChange );

--Tabs, for reference
--1 - Global
--2 - OOC
--3 - IC
--4 - Admin
--5 - PM
--6 - Radio
--7 - Console log
--8 - OIFY :d

function AddChat( rec, name, text, font, namecolor, textcolor )

	if( not ChatBox or not InnerChatBox ) then return; end

	local origname = name;

	for k, v in pairs( rec ) do
	
		if( not ChatTabs[v] ) then
		
			ChatTabs[v] = { }
			ChatTabs[v].ChatLines = { }
			ChatTabs[v].CurrentY = 195;
			ChatTabs[v].Shift = 0;
			
		end
	
		local newline = { }
		
		surface.SetFont( font );
		
		
		
		--Figure out how tall this piece of name/text is
		local _, textheight = surface.GetTextSize( text );
		local _, nameheight = surface.GetTextSize( name );
		
		if( name ~= nil and name ~= "" ) then
			name = name .. ": ";
		end
		
		newline.Name = name;
		newline.NameColor = namecolor;
		newline.TextColor = textcolor;
		newline.Font = font;
		
		local spacesize = surface.GetTextSize( " " );
		
		--We indent the text so that it doesn't overlap the name, 
		--because the name and text are two different strings
		local namewidth = surface.GetTextSize( name );
		local numspaces = math.ceil( namewidth / spacesize );
		
		newline.Text = "";
		
		for n = 1, numspaces do
		
			newline.Text = newline.Text .. " ";
		
		end
		
		newline.Text = newline.Text .. text;
		
		newline.Text = FormatLine( newline.Text, font, 385 );
		_, textheight = surface.GetTextSize( newline.Text );
		
		--Position the text
		newline.X = 2;
		newline.Y = ChatTabs[v].CurrentY;
		
		newline.Time = CurTime();
		newline.Alpha = 255;
		
		local numlines = 1;
		
		--Which one takes up more space, the name or the text?  
		--We need to know this so we know how far down to place the next chat line
		if( textheight < nameheight ) then
		
			newline.Height = nameheight;
			numlines = math.ceil( newline.Height / nameheight );
			ChatTabs[v].CurrentY = ChatTabs[v].CurrentY + nameheight;
		
		else
		
			newline.Height = textheight;
			numlines = math.ceil( newline.Height / textheight );
			ChatTabs[v].CurrentY = ChatTabs[v].CurrentY + textheight;			
		
		end
		
		--ChatTabs[v].Shift = ChatTabs[v].Shift - newline.Height;

		
		--The code here at the bottom deals with the scroll bar in the
		local movebar = false;
		
		local olddist = InnerChatBox[v].VScrollDistance;

		InnerChatBox[v].VScrollDistance = InnerChatBox[v].VScrollDistance + newline.Height;
		
		
		if( InnerChatBox[v].VScrollBar ) then
		
			local _, y = InnerChatBox[v].VScrollBar:GetPos();
			local ymax = y + InnerChatBox[v].VScrollBar:GetTall();
			local _, y2 = InnerChatBox[v].ScrollDownButton:GetPos();
			
			--If the scrollbar is at the bottom, then we move it down when
			--more chat comes in
			if( ymax - y2 == 0 ) then
			
				movebar = true;
			
			end
			
		end
		
		InnerChatBox[v]:CalculateScrollBar();
		
		if( olddist == 0 and InnerChatBox[v].VScrollDistance > 0 ) then
		
			movebar = true;
		
		end
		
		if( movebar ) then
		
			local x, y = InnerChatBox[v].VScrollBar:GetPos();
			local _, y2 = InnerChatBox[v].ScrollDownButton:GetPos();
			y2 = y2 - InnerChatBox[v].VScrollBar:GetTall();
		
			InnerChatBox[v].VScrollBar:SetPos( x, y2 );	
			InnerChatBox[v].VScrollBar:CalculateScrollAmount();

			
		end

		table.insert( ChatTabs[v].ChatLines, newline );
		
		name = origname;
		
		if( not ChatBoxVisible ) then
		
			if( InnerChatBox[CurrentChatTab].ScrollUpButton ) then
				InnerChatBox[CurrentChatTab].ScrollUpButton:SetVisible( false );
			end
			
			if( InnerChatBox[CurrentChatTab].ScrollDownButton ) then
				InnerChatBox[CurrentChatTab].ScrollDownButton:SetVisible( false );
			end
		
			if( InnerChatBox[CurrentChatTab].VScrollBar ) then
				InnerChatBox[CurrentChatTab].VScrollBar:SetVisible( false );
			end
		
		end
		
		if( v ~= CurrentChatTab and ChatBox.Button[v] ) then
			
			ChatBox.Button[v].HighlightRed = true;
			ChatBox.Button[v].AlwaysHighlight = true;
		
		end
		
	end
	
	--Finally we decide which piece of the chat we want to render into the chatbox
	--To do this we have to make a table of what chat to display by looping through
	--all current chat lines and determining which is visible
	FindVisibleChat( CurrentChatTab );
		

end

VisibleChatLines = { }

function FindVisibleChat( num )

	if( not ChatTabs[num] or not ChatTabs[num].ChatLines ) then return; end

	VisibleChatLines = { }

	for k, v in pairs( ChatTabs[num].ChatLines ) do

		local y = v.Y - InnerChatBox[num].VScrollAmount + ChatTabs[num].Shift;
		local ymax = y + v.Height;
		
		if( ( y >= -5 or ymax >= -5 ) and y <= InnerChatBox[num]:GetTall() ) then
			
			--This text is visible
			table.insert( VisibleChatLines, k );
		
		end
	
	end

end

function CreateChatBox()

	ChatBox = CreateBPanel( nil, 5, ScrH() - 400, 400, 250 );
	ChatBox.RequiresMouse = false;
	
	for n = 1, 7 do
	
		InnerChatBox[n] = CreateBPanel( nil, 10, ScrH() - 400 + 29, 390, 198 );
		--InnerChatBox[n]:SetParent( ChatBox );
		InnerChatBox[n]:SetBodyColor( Color( 0, 0, 0, 100 ) );
		InnerChatBox[n]:EnableScrolling( true );
		InnerChatBox[n]:SetVisible( false );
		InnerChatBox[n].RequiresMouse = false;
		InnerChatBox[n].OnScrollBarUpdate = function()
	
			FindVisibleChat( n );
		
		end
		
		InnerChatBox[n].PaintHook = function( self )
		
			if( not ChatBox:IsVisible() and PlayerMenuVisible ) then
			
				return;
			
			end
		
			for k, v in pairs( VisibleChatLines ) do
			
				if( ChatTabs and ChatTabs[n] and ChatTabs[n].ChatLines and ChatTabs[n].ChatLines[v] ) then

					local line = ChatTabs[n].ChatLines[v];
	
					if( ChatBoxVisible ) then
	
						draw.SimpleTextOutlined( line.Name, line.Font, line.X, line.Y - InnerChatBox[n].VScrollAmount + ChatTabs[n].Shift, line.NameColor, 0, 0, 1, Color( 30, 30, 30, 255 ) );
						draw.DrawTextOutlined( line.Text, line.Font, line.X, line.Y - InnerChatBox[n].VScrollAmount + ChatTabs[n].Shift, Color( line.TextColor.r, line.TextColor.g, line.TextColor.b, line.TextColor.a ), 0, 0, 1, Color( 30, 30, 30, 255 ) );

					else
					
						draw.SimpleTextOutlined( line.Name, line.Font, line.X, line.Y - InnerChatBox[n].VScrollAmount + ChatTabs[n].Shift, Color( line.NameColor.r, line.NameColor.g, line.NameColor.b, line.Alpha ), 0, 0, 1, Color( 30, 30, 30, line.Alpha ) );
						draw.DrawTextOutlined( line.Text, line.Font, line.X, line.Y - InnerChatBox[n].VScrollAmount + ChatTabs[n].Shift, Color( line.TextColor.r, line.TextColor.g, line.TextColor.b, line.Alpha ), 0, 0, 1, Color( 30, 30, 30, line.Alpha ) );

						if( line.Time + 5 < CurTime() ) then
						
							line.Alpha = math.Clamp( line.Alpha - 200 * FrameTime(), 0, 255 );
						
						end 

					end
						
				end
					
			end
			
		
		end
		
		InnerChatBox[n].OriginalPaint = InnerChatBox[n].Paint;
		InnerChatBox[n].Paint = InnerChatBox[n].PaintHook;
		
		ChatBox.TextEntry = vgui.Create( "DTextEntry", ChatBox );
		ChatBox.TextEntry:SetPos( 10, ScrH() - 400 + 250 );
		ChatBox.TextEntry:SetSize( 390, 16 );
		ChatBox.TextEntry:SetMouseInputEnabled( true );
		ChatBox.TextEntry:SetKeyboardInputEnabled( true );
		ChatBox.TextEntry:SetFGColor( 0, 0, 0, 255 );
		ChatBox.TextEntry:MakePopup();
		
		ChatBox.TextEntry.OnKeyCodeTyped = function( self, key )
			
			if( key == 70 ) then
			
				CloseChatBox();
				RunConsoleCommand( "cancelselect", "" );
				
				HideMouse();
				
				return;
			
			end
			
			if( key == KEY_ENTER ) then
			
				CloseChatBox();
			
				if( string.gsub( ChatBox.TextEntry:GetValue(), " ", "" ) ~= "" ) then
					
					RunConsoleCommand( "say", ChatBox.TextEntry:GetValue() );
					
				end

				ChatBox.TextEntry:SetText( "" );
				HideMouse();
				
				return;
			
			end
		
		end
		
	end
	
	InnerChatBox[1]:SetVisible( true );
	
	ChatBox.Button = { }
	
	ChatBox.Button[1] = ChatBox:AddButton( "Global", 5, 5 );
	ChatBox.Button[1].Outline = 1;
	
	local function SetToChatBox( n )
	
		if( CurrentChatTab == n ) then return; end

		ChatBox.Button[CurrentChatTab].AlwaysHighlight = false;
		ChatBox.Button[n].AlwaysHighlight = true;
		ChatBox.Button[n].HighlightRed = false;
		InnerChatBox[CurrentChatTab]:SetVisible( false );
		InnerChatBox[n]:SetVisible( true );
		InnerChatBox[n].Paint = InnerChatBox[n].OriginalPaint;
		
		CurrentChatTab = n;
		
		FindVisibleChat( n );		
	
	end
	
	ChatBox.Button[1].Action = function()
	
		SetToChatBox( 1 );
	
	end
	ChatBox.Button[1].Action();
	
	ChatBox.Button[1].AlwaysHighlight = true;
	
	ChatBox.Button[2] = ChatBox:AddButton( "OOC", 60, 5 );
	ChatBox.Button[2].Outline = 1;
	
	ChatBox.Button[2].Action = function()
	
		SetToChatBox( 2 );
	
	end
	
	ChatBox.Button[3] = ChatBox:AddButton( "IC", 105, 5 );
	ChatBox.Button[3].Outline = 1;
	
	ChatBox.Button[3].Action = function()
	
		SetToChatBox( 3 );
	
	end
	
	ChatBox.Button[4] = ChatBox:AddButton( "Admin", 133, 5 );
	ChatBox.Button[4].Outline = 1;
	
	ChatBox.Button[4].Action = function()
	
		SetToChatBox( 4 );
	
	end
	
	ChatBox.Button[5] = ChatBox:AddButton( "PM", 187, 5 );
	ChatBox.Button[5].Outline = 1;
	
	ChatBox.Button[5].Action = function()
	
		SetToChatBox( 5 );
	
	end
	
	local but = ChatBox:AddButton( "Radio", 220, 5 );
	but.Outline = 1;	
	
	ChatBox.Button[7] = ChatBox:AddButton( "Console", 270, 5 );
	ChatBox.Button[7].Outline = 1;
	
	ChatBox.Button[7].Action = function()
	
		SetToChatBox( 7 );
	
	end

end

CreateChatBox();
ChatBox:SetVisible( false );

