local gsub = string.gsub

function string.Interp(str, tbl)
   return gsub(str, '{(%w+)}', tbl)
end

if ( SERVER ) then
	AddCSLuaFile()
else

	-- Fonts
	surface.CreateFont("TraitorState", {font = "Trebuchet24",
										size = 28,
										weight = 1000})
	surface.CreateFont("TimeLeft",     {font = "Trebuchet24",
										size = 24,
										weight = 800})
	surface.CreateFont("HealthAmmo",   {font = "Trebuchet24",
										size = 24,
										weight = 750})
	surface.CreateFont("Sleek_RoleFont", {font = "Bebas Neue",
										size = 72,
										weight = 0})
	surface.CreateFont("Sleek_NameFont", {font = "Bebas Neue",
										size = 38,
										weight = 0})
	surface.CreateFont("Sleek_TimeFont", {font = "Bebas Neue",
										size = 20,
										weight = 0})
	surface.CreateFont("Sleek_HealthFont", {font = "Bebas Neue",
										size = 20,
										weight = 0})
	surface.CreateFont("Sleek_SpecFont", {font = "Bebas Neue",
										size = 38,
										weight = 0})
	surface.CreateFont("Sleek_AmmoFont", {font = "Bebas Neue",
										size = 22,
										weight = 0})

	local function SleekOverride()
		if ( GAMEMODE.Name ~= "Trouble in Terrorist Town" ) then
			hook.Remove( "Initialize", "SleekTTTHUD" )
			return
		end
		
		local key_params = { usekey = Key("+use", "USE") }
		
		local GetTranslation = LANG.GetTranslation
		local GetPTranslation = LANG.GetParamTranslation
		local GetLang = LANG.GetUnsafeLanguageTable
		local interp = string.Interp
		
		local roundStates = {}
		roundStates[ ROUND_WAIT ]	= "round_wait"
		roundStates[ ROUND_PREP ]	= "round_prep"
		roundStates[ ROUND_ACTIVE ] = "round_active"
		roundStates[ ROUND_POST ]	= "round_post"
		
		local bg_colors = {
	   background_main = Color(0, 0, 10, 200),

	   noround = Color(100,100,100,200),
	   traitor = Color(200, 25, 25, 200),
	   innocent = Color(25, 200, 25, 200),
	   detective = Color(25, 25, 200, 200)
	};

	local health_colors = {
	   border = COLOR_WHITE,
	   background = Color(100, 25, 25, 222),
	   fill = Color(200, 50, 50, 250)
	};

	local ammo_colors = {
	   border = COLOR_WHITE,
	   background = Color(20, 20, 5, 222),
	   fill = Color(205, 155, 0, 255)
	};

	local margin = 10
	
	local Tex_Corner8 = surface.GetTextureID( "gui/corner8" )
	local function RoundedMeter( bs, x, y, w, h, color)
	   surface.SetDrawColor(clr(color))

	   surface.DrawRect( x+bs, y, w-bs*2, h )
	   surface.DrawRect( x, y+bs, bs, h-bs*2 )

	   surface.SetTexture( Tex_Corner8 )
	   surface.DrawTexturedRectRotated( x + bs/2 , y + bs/2, bs, bs, 0 )
	   surface.DrawTexturedRectRotated( x + bs/2 , y + h -bs/2, bs, bs, 90 )

	   if w > 14 then
		  surface.DrawRect( x+w-bs, y+bs, bs, h-bs*2 )
		  surface.DrawTexturedRectRotated( x + w - bs/2 , y + bs/2, bs, bs, 270 )
		  surface.DrawTexturedRectRotated( x + w - bs/2 , y + h - bs/2, bs, bs, 180 )
	   else
		  surface.DrawRect( x + math.max(w-bs, bs), y, bs/2, h )
	   end

	end
	
	local function GetAmmo(ply)
	   local weap = ply:GetActiveWeapon()
	   if not weap or not ply:Alive() then return -1 end

	   local ammo_inv = weap:Ammo1() or 0
	   local ammo_clip = weap:Clip1() or 0
	   local ammo_max = weap.Primary.ClipSize or 0

	   return ammo_clip, ammo_max, ammo_inv
	end

	local dr = draw

	local function ShadowedText(text, font, x, y, color, xalign, yalign)

	   dr.SimpleText(text, font, x+2, y+2, COLOR_BLACK, xalign, yalign)

	   dr.SimpleText(text, font, x, y, color, xalign, yalign)
	end
		
		local function PaintBar(x, y, w, h, colors, value)
		   -- Background
		   -- slightly enlarged to make a subtle border
		   draw.RoundedBox(8, x-1, y-1, w+2, h+2, colors.background)

		   -- Fill
		   local width = w * math.Clamp(value, 0, 1)

		   if width > 0 then
			  RoundedMeter(8, x, y, width, h, colors.fill)
		   end
		end
		
		local function PunchPaint(client)
		   local L = GetLang()
		   local punch = client:GetNWFloat("specpunches", 0)

		   local width, height = 200, 25
		   local x = ScrW() / 2 - width/2
		   local y = margin/2 + height

		   PaintBar(x, y, width, height, ammo_colors, punch)

		   local color = bg_colors.background_main

		   dr.SimpleText(L.punch_title, "HealthAmmo", ScrW() / 2, y, color, TEXT_ALIGN_CENTER)

		   dr.SimpleText(L.punch_help, "TabLarge", ScrW() / 2, margin, COLOR_WHITE, TEXT_ALIGN_CENTER)

		   local bonus = client:GetNWInt("bonuspunches", 0)
		   if bonus != 0 then
			  local text
			  if bonus < 0 then
				 text = interp(L.punch_bonus, {num = bonus})
			  else
				 text = interp(L.punch_malus, {num = bonus})
			  end

			  dr.SimpleText(text, "TabLarge", ScrW() / 2, y * 2, COLOR_WHITE, TEXT_ALIGN_CENTER)
		   end
		end

		local function SpecHUDPaint(client)
		   local L = GetLang() -- for fast direct table lookups

		   -- Draw round state
		   local x       = margin
		   local height  = 32
		   local width   = 250
		   local round_y = ScrH() - height - margin

		   -- move up a little on low resolutions to allow space for spectator hints
		   if ScrW() < 1000 then round_y = round_y - 15 end

		   local time_x = x + 170
		   local time_y = round_y + 4

			draw.RoundedBox( 8, 10, ScrH() - 110 + 50, 360 - 100, 50, Color( 44, 59, 75 ) )
			draw.RoundedBox( 8, 11, ScrH() - 109 + 50, 358 - 100, 20, Color( 134, 143, 152 ) )
			draw.RoundedBox( 8, 11, ScrH() - 108+ 50, 358 - 100, 49, Color( 44, 62, 80 ) )
			draw.RoundedBoxEx( 8, 11, ScrH() - 108+ 50, 358 - 100, 24, Color( 52, 73, 94 ), true, true, false, false )

		   local text = L[ roundStates[GAMEMODE.round_state] ]
		   ShadowedText(text, "Sleek_SpecFont", x + margin + 6, round_y - 8, COLOR_WHITE)
		   --draw.SimpleText( text, "Sleek_SpecFont", x + margin )

		   -- Draw round/prep/post time remaining
		   local text = util.SimpleTime(math.max(0, GetGlobalFloat("ttt_round_end", 0) - CurTime()), "%02i:%02i")
		   ShadowedText(text, "Sleek_SpecFont", time_x + margin, time_y - 12, COLOR_WHITE)
		   
		   if av and av:IsValid() then
				av:Remove()
			end

		   local tgt = client:GetObserverTarget()
		   if IsValid(tgt) and tgt:IsPlayer() then
			  ShadowedText(tgt:Nick(), "TimeLeft", ScrW() / 2, margin, COLOR_WHITE, TEXT_ALIGN_CENTER)

		   elseif IsValid(tgt) and tgt:GetNWEntity("spec_owner", nil) == client then
			  PunchPaint(client)
		   else
			  ShadowedText(interp(L.spec_help, key_params), "TabLarge", ScrW() / 2, margin, COLOR_WHITE, TEXT_ALIGN_CENTER)
		   end
		end

		local function DrawAbsHUD( client )
			local L = GetLang() 
			local is_traitor = client:IsActiveTraitor()
			
			local width = 250
		   local height = 90
			
			local y = ScrH() - margin - height
			
			local traitor_y = y - 30
			local text = nil
			
			local x       = margin
			local height  = 32
			local width   = 250
			local round_y = ScrH() - height - margin

		   -- move up a little on low resolutions to allow space for spectator hints
			   if ScrW() < 1000 then round_y = round_y - 15 end

			   local time_x = x + 170
			   local time_y = round_y + 4
			
			local roleText
			local roleString
			local round_state = GAMEMODE.round_state
			
			local bgCol = {}
			bgCol["traitor"] = { fCol = Color( 192, 57, 43 ), sCol = Color( 231, 76, 60 ) }
			bgCol["detective"] = { fCol = Color( 41, 128, 185 ), sCol = Color( 52, 152, 219 ) }
			bgCol["innocent"] = { fCol = Color( 39, 174, 96 ), sCol = Color( 46, 204, 113 ) }
			
			local is_haste = HasteMode() and round_state == ROUND_ACTIVE
		   local is_traitor = client:IsActiveTraitor()

		   local endtime = GetGlobalFloat("ttt_round_end", 0) - CurTime()

		   local text
		   local font = "TimeLeft"
		   local color = COLOR_WHITE
		   local rx = x + margin + 170
		   local ry = traitor_y + 3

		   -- Time displays differently depending on whether haste mode is on,
		   -- whether the player is traitor or not, and whether it is overtime.
		   if is_haste then
			  local hastetime = GetGlobalFloat("ttt_haste_end", 0) - CurTime()
			  if hastetime < 0 then
				 if (not is_traitor) or (math.ceil(CurTime()) % 7 <= 2) then
					-- innocent or blinking "overtime"
					text = L.overtime
					font = "Trebuchet18"

					-- need to hack the position a little because of the font switch
					ry = ry + 5
					rx = rx - 3
				 else
					-- traitor and not blinking "overtime" right now, so standard endtime display
					text  = util.SimpleTime(math.max(0, endtime), "%02i:%02i")
					color = COLOR_RED
				 end
			  else
				 -- still in starting period
				 local t = hastetime
				 if is_traitor and math.ceil(CurTime()) % 6 < 2 then
					t = endtime
					color = COLOR_RED
				 end
				 text = util.SimpleTime(math.max(0, t), "%02i:%02i")
			  end
		   else
			  -- bog standard time when haste mode is off (or round not active)
			  text = util.SimpleTime(math.max(0, endtime), "%02i:%02i")
		   end
			
			local hCol
			
			if round_state == ROUND_PREP then
			
				draw.RoundedBox( 8, 10, ScrH() - 110 + 50, 360 - 100, 50, Color( 44, 59, 75 ) )
				draw.RoundedBox( 8, 11, ScrH() - 109 + 50, 358 - 100, 20, Color( 134, 143, 152 ) )
				draw.RoundedBox( 8, 11, ScrH() - 108+ 50, 358 - 100, 49, Color( 44, 62, 80 ) )
				draw.RoundedBoxEx( 8, 11, ScrH() - 108+ 50, 358 - 100, 24, Color( 52, 73, 94 ), true, true, false, false )

			   local text = L[ roundstate_string[GAMEMODE.round_state] ]
			   ShadowedText(text, "Sleek_SpecFont", x + margin + 6, round_y - 8, COLOR_WHITE)
			   --draw.SimpleText( text, "Sleek_SpecFont", x + margin )

			   -- Draw round/prep/post time remaining
			   local text = util.SimpleTime(math.max(0, GetGlobalFloat("ttt_round_end", 0) - CurTime()), "%02i:%02i")
			   ShadowedText(text, "Sleek_SpecFont", time_x + margin, time_y - 12, COLOR_WHITE)
			   
			   hCol = bgCol["innocent"]
			   
			elseif round_state == ROUND_ACTIVE then
				
				draw.RoundedBox( 8, 10, ScrH() - 110, 360, 100, Color( 44, 59, 75 ) )
				draw.RoundedBox( 8, 11, ScrH() - 109, 358, 50, Color( 134, 143, 152 ) )
				draw.RoundedBox( 8, 11, ScrH() - 108, 358, 97, Color( 44, 62, 80 ) )
				draw.RoundedBoxEx( 8, 11, ScrH() - 108, 358, 50, Color( 52, 73, 94 ), true, true, false, false )
				
				if is_traitor then
					draw.RoundedBoxEx( 8, 11, ScrH() - 109, 58, 50, Color( 254, 243, 223 ), true, false, false, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 97, Color( 192, 57, 43 ), true, false, true, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 50, Color( 231, 76, 60 ), true, false, false, false )
					roleText = "T"
					roleString = "Traitor"
					hCol = bgCol["traitor"]
				elseif LocalPlayer():GetRole() == ROLE_DETECTIVE then
					draw.RoundedBoxEx( 8, 11, ScrH() - 109, 58, 50, Color( 254, 243, 223 ), true, false, false, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 97, Color( 41, 128, 185 ), true, false, true, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 50, Color( 52, 152, 219 ), true, false, false, false )
					roleText = "D"
					roleString = "Detective"
					hCol = bgCol["detective"]
				else
					draw.RoundedBoxEx( 8, 11, ScrH() - 109, 58, 50, Color( 254, 243, 223 ), true, false, false, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 97, Color( 39, 174, 96 ), true, false, true, false )
					draw.RoundedBoxEx( 8, 11, ScrH() - 108, 58, 50, Color( 46, 204, 113 ), true, false, false, false )
					roleText = "I"
					roleString = "Innocent"
					hCol = bgCol["innocent"]
				end
				
				draw.SimpleText( roleString, "Sleek_NameFont", 91 - 10, ScrH() - 99, Color( 0, 0, 0, 255 ), TEXT_ALIGN_LEFT )
				draw.SimpleText( roleString, "Sleek_NameFont", 90 - 10, ScrH() - 100, Color( 255, 255, 255 ), TEXT_ALIGN_LEFT )
				
				draw.SimpleText( "Time remaining: "..text, "Sleek_TimeFont", 355, ScrH() - 99, Color( 0, 0, 0, 255 ), TEXT_ALIGN_RIGHT )
				draw.SimpleText( "Time remaining: "..text, "Sleek_TimeFont", 354, ScrH() - 100, Color( 255, 255, 255 ), TEXT_ALIGN_RIGHT )
				
				if is_haste then
					draw.SimpleText( L.hastemode, "Sleek_TimeFont", 355, ScrH() - 85, Color( 0, 0, 0, 255 ), TEXT_ALIGN_RIGHT )
					draw.SimpleText( L.hastemode, "Sleek_TimeFont", 354, ScrH() - 86, Color( 255, 255, 255 ), TEXT_ALIGN_RIGHT )
				end
				
				local health = LocalPlayer():Health()
				
				draw.RoundedBox( 4, 11 + 62 + 6, ScrH() - 46, 280 , 27, Color( 0, 0, 0, 255 ) )
				draw.RoundedBox( 4, 12 + 62 + 6, ScrH() - 45, 278 * (health/100), 24, hCol.sCol )
				draw.RoundedBox( 4, 12 + 62 + 6, ScrH() - 44, 278 * (health/100), 24, hCol.fCol )
				
				draw.SimpleText( "Health: "..LocalPlayer():Health(), "Sleek_HealthFont", 91, ScrH() - 41, Color( 0, 0, 0, 255 ), TEXT_ALIGN_LEFT )
				draw.SimpleText( "Health: "..LocalPlayer():Health(), "Sleek_HealthFont", 90, ScrH() - 42, Color( 255, 255, 255 ), TEXT_ALIGN_LEFT )
				
				local width = 250
			   local height = 90

			   local x = margin
			   local y = ScrH() - margin - height

			   --DrawBg(x, y, width, height, client)

			   local bar_height = 25
			   local bar_width = width - (margin*2)

				
				local health = math.max(0, client:Health())
				local health_y = y + margin
				
				local SWEP = LocalPlayer():GetActiveWeapon()
				local swepname
				
				if SWEP:IsValid() then
					
					swepname = SWEP:GetPrintName() or ""
				
					if SWEP:GetClass() == "weapon_zm_improvised" then 
						swepname = "Crowbar" end
					if SWEP:GetClass() == "weapon_zm_carry" then 
						swepname = "Magneto-Stick" end
					if SWEP:GetClass() == "weapon_ttt_unarmed" then 
						swepname = "Holster" end
					if SWEP:GetClass() == "weapon_ttt_ak47" then 
						swepname = "AK-47" end
					if SWEP:GetClass() == "weapon_ttt_aug" then 
						swepname = "AUG" end
					if SWEP:GetClass() == "weapon_zm_mac10" then 
						swepname = "Mac10" end
					if SWEP:GetClass() == "weapon_ttt_44mag" then 
						swepname = ".44 Magnum" end
					if SWEP:GetClass() == "weapon_ttt_beacon" then 
						swepname = "Beacon" end
					if SWEP:GetClass() == "weapon_zm_revolver" then 
						swepname = "Deagle" end
					if SWEP:GetClass() == "weapon_ttt_l96aw" then 
						swepname = "L96A1" end
					if SWEP:GetClass() == "weapon_ttt_m16" then 
						swepname = "M16" end
					if SWEP:GetClass() == "weapon_ttt_g3sg1" then 
						swepname = "G3SG1" end
					if SWEP:GetClass() == "weapon_ttt_ump" then 
						swepname = "UMP" end
					if SWEP:GetClass() == "weapon_zm_rifle" then 
						swepname = "Rifle" end
					if SWEP:GetClass() == "weapon_ttt_870" then 
						swepname = "Remington 870" end
					if SWEP:GetClass() == "weapon_ttt_p90" then 
						swepname = "P90" end
					if SWEP:GetClass() == "weapon_zm_sledge" then 
						swepname = "HUGE-249" end
					if SWEP:GetClass() == "weapon_ttt_mp5" then 
						swepname = "MP5" end
					if SWEP:GetClass() == "weapon_ttt_galil" then 
						swepname = "Galil" end
					if SWEP:GetClass() == "weapon_ttt_sg550" then 
						swepname = "SG550" end
					if SWEP:GetClass() == "weapon_zm_shotgun" then 
						swepname = "Shotgun" end
					if SWEP:GetClass() == "weapon_zm_pistol" then 
						swepname = "Pistol" end	
					if SWEP:GetClass() == "weapon_ttt_glock" then 
						swepname = "Glock" end
					if SWEP:GetClass() == "weapon_ttt_smokegrenade" then 
						swepname = "Smoke Grenade" end
					if SWEP:GetClass() == "weapon_zm_molotov" then 
						swepname = "Incendiary Grenade"  end
					if SWEP:GetClass() == "weapon_ttt_confgrenade" then 
						swepname = "Discombobulator" end
					if SWEP:GetClass() == "weapon_ttt_sipistol" then
						swepname = "Silenced Pistol" end
					if SWEP:GetClass() == "weapon_ttt_knife" then
						swepname = "Knife" end
					if SWEP:GetClass() == "weapon_ttt_binoculars" then
						swepname = "Binoculars" end
					if SWEP:GetClass() == "weapon_ttt_beacon" then
						swepname = "Beacon" end
					if SWEP:GetClass() == "weapon_ttt_c4" then
						swepname = "C4" end
					if SWEP:GetClass() == "weapon_ttt_teleport" then
						swepname = "Teleporter" end
				end
				
				if client:GetActiveWeapon().Primary then
				  local ammo_clip, ammo_max, ammo_inv = GetAmmo(client)
				  if ammo_clip != -1 then
					 local ammo_y = health_y + bar_height + margin
					 --PaintBar(ScrW() - bar_width - 10, ammo_y + 20, bar_width, bar_height, ammo_colors, ammo_clip/ammo_max)
					--draw.RoundedBox( 8, ScrW() - 168, ScrH() - 110 + 70, 360 - 100 - 100, 30, Color( 44, 59, 75 ) )
					--draw.RoundedBox( 8, ScrW() - 167, ScrH() - 109 + 70, 358 - 100 - 100, 14, Color( 134, 143, 152 ) )
					--draw.RoundedBox( 8, ScrW() - 167, ScrH() - 108+ 70, 358 - 100 - 100, 14, Color( 44, 62, 80 ) )
					--draw.RoundedBoxEx( 8, ScrW() - 167, ScrH() - 108+ 70, 358 - 100 - 100, 14, Color( 52, 73, 94 ), true, true, false, false )
					local text = string.format("%i + %02i", ammo_clip, ammo_inv)

					--ShadowedText(client:GetActiveWeapon():GetPrintName().." - "..text, "Sleek_AmmoFont", ScrW() - bar_width + 200, ammo_y + 21, COLOR_WHITE, TEXT_ALIGN_RIGHT, TEXT_ALIGN_RIGHT)
					draw.SimpleText( swepname.." - "..text, "Sleek_HealthFont", 346, ScrH() - 41, Color( 0, 0, 0, 255 ), TEXT_ALIGN_RIGHT )
					draw.SimpleText( swepname.." - "..text, "Sleek_HealthFont", 346, ScrH() - 42, Color( 255, 255, 255 ), TEXT_ALIGN_RIGHT )
				  end
			   end
			end
		end

		function GAMEMODE:HUDPaint()
			if ( not GetConVar( "cl_drawhud" ):GetBool() ) then
				return
			end

			GAMEMODE:HUDDrawTargetID()

			local player = LocalPlayer()
			MSTACK:Draw( player )

			--drawTime()

			if ( not player:Alive() or player:Team() == TEAM_SPEC ) then
				SpecHUDPaint(LocalPlayer())
				return
			end

			RADAR:Draw( player )
			TBHUD:Draw( player )
			WSWITCH:Draw( player )

			VOICE.Draw( player )
			DISGUISE.Draw( player )

			GAMEMODE:HUDDrawPickupHistory()

			--drawHealth()
			--drawAmmo()
			if ( GAMEMODE.round_state == ROUND_ACTIVE ) then
				DrawAbsHUD( LocalPlayer() )
			else
				SpecHUDPaint(LocalPlayer())
			end
		end
	end
	hook.Add( "Initialize", "SleekTTTHUD", SleekOverride )

	if GAMEMODE then
		SleekOverride()
	end
end
