-- HUD HUD HUD



local table = table

local surface = surface

local draw = draw

local math = math

local string = string



local GetTranslation = LANG.GetTranslation

local GetPTranslation = LANG.GetParamTranslation

local GetLang = LANG.GetUnsafeLanguageTable

local interp = string.Interp



-- 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})

-- Color presets

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)

};





-- Modified RoundedBox

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



---- The bar painting is loosely based on:

---- http://wiki.garrysmod.com/?title=Creating_a_HUD



-- Paints a graphical meter bar

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 roundstate_string = {

   [ROUND_WAIT]   = "round_wait",

   [ROUND_PREP]   = "round_prep",

   [ROUND_ACTIVE] = "round_active",

   [ROUND_POST]   = "round_post"

};



-- Returns player's ammo information

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 function DrawBg(x, y, width, height, client)

   -- Traitor area sizes

   local th = 30

   local tw = 170



   -- Adjust for these

   y = y - th

   height = height + th



   -- main bg area, invariant

   -- encompasses entire area

   draw.RoundedBox(8, x, y, width, height, bg_colors.background_main)



   -- main border, traitor based

   local col = bg_colors.innocent

   if GAMEMODE.round_state != ROUND_ACTIVE then

      col = bg_colors.noround

   elseif client:GetTraitor() then

      col = bg_colors.traitor

   elseif client:GetDetective() then

      col = bg_colors.detective

   end



   draw.RoundedBox(8, x, y, tw, th, col)

end



local sf = surface

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 margin = 10



-- Paint punch-o-meter

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 key_params = { usekey = Key("+use", "USE") }



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, x, round_y, width, height, bg_colors.background_main)

   draw.RoundedBox(8, x, round_y, time_x - x, height, bg_colors.noround)



   local text = L[ roundstate_string[GAMEMODE.round_state] ]

   ShadowedText(text, "TraitorState", x + margin, round_y, COLOR_WHITE)



   -- Draw round/prep/post time remaining

   local text = util.SimpleTime(math.max(0, GetGlobalFloat("ttt_round_end", 0) - CurTime()), "%02i:%02i")

   ShadowedText(text, "TimeLeft", time_x + margin, time_y, COLOR_WHITE)



   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 ttt_health_label = CreateClientConVar("ttt_health_label", "0", true)



local function InfoPaint(client)

   local L = GetLang()



   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)



   -- Draw health

   local health = math.max(0, client:Health())

   local health_y = y + margin



   PaintBar(x + margin, health_y, bar_width, bar_height, health_colors, health/100)



   ShadowedText(tostring(health), "HealthAmmo", bar_width, health_y, COLOR_WHITE, TEXT_ALIGN_RIGHT, TEXT_ALIGN_RIGHT)



   if ttt_health_label:GetBool() then

      local health_status = util.HealthToString(health)

      draw.SimpleText(L[health_status], "TabLarge", x + margin*2, health_y + bar_height/2, COLOR_WHITE, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)

   end



   -- Draw ammo

   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(x+margin, ammo_y, bar_width, bar_height, ammo_colors, ammo_clip/ammo_max)

         local text = string.format("%i + %02i", ammo_clip, ammo_inv)



         ShadowedText(text, "HealthAmmo", bar_width, ammo_y, COLOR_WHITE, TEXT_ALIGN_RIGHT, TEXT_ALIGN_RIGHT)

      end

   end



   -- Draw traitor state

   local round_state = GAMEMODE.round_state



   local traitor_y = y - 30

   local text = nil

   if round_state == ROUND_ACTIVE then

      text = L[ client:GetRoleStringRaw() ]

   else

      text = L[ roundstate_string[round_state] ]

   end



   ShadowedText(text, "TraitorState", x + margin + 73, traitor_y, COLOR_WHITE, TEXT_ALIGN_CENTER)



   -- Draw round time

   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



   ShadowedText(text, font, rx, ry, color)



   if is_haste then

      dr.SimpleText(L.hastemode, "TabLarge", x + margin + 165, traitor_y - 8)

   end



end



-- Paints player status HUD element in the bottom left

function GM:HUDPaint()

   local client = LocalPlayer()



   hook.Call( "HUDDrawTargetID", GAMEMODE )



   MSTACK:Draw(client)



   if (not client:Alive()) or client:Team() == TEAM_SPEC then

      SpecHUDPaint(client)



      return

   end





   RADAR:Draw(client)

   TBHUD:Draw(client)

   WSWITCH:Draw(client)



   VOICE.Draw(client)

   DISGUISE.Draw(client)



   hook.Call( "HUDDrawPickupHistory", GAMEMODE )



   -- Draw bottom left info panel

   InfoPaint(client)

end



-- Hide the standard HUD stuff

local hud = {"CHudHealth", "CHudBattery", "CHudAmmo", "CHudSecondaryAmmo"}

function GM:HUDShouldDraw(name)

   for k, v in pairs(hud) do

      if name == v then return false end

   end



   return true

end



