-- $LastChangedDate: 2010-04-21 10:19:47 -0500 (Wed, 21 Apr 2010) $
-- Updates HUD every tick.
-- See module.txt for documentation and pitfalls.

---------------------
-- Hud (singleton) --
---------------------

Hud = {
    statusText = "",
    enableInfoText = true,  -- enable the info text in top-left corner of window (disabled to show OSG stats)
}

-- Initialize HUD.
function Hud:Init()
    -- Register timer-tick handler.
    -- Don't update HUD too fast.  Give time for the user to read it.
    Timer:Register( self, defs.HUD_TICK_FREQ )

    -- HUD is composed of lines of HudText objects defined by HudText::Args.
    local hudTextArgs = {
        text = "",
        orientation = "BOTTOM_LEFT",
        fontSize = 28.0,
        x = 16,
        y = 16,
    }

    local alpha = 1.0
    local yi = 32

    self.hudText1 = sim.HudText:New( hudTextArgs )
    hudTextArgs.y = hudTextArgs.y + yi

    self.hudText2 = sim.HudText:New( hudTextArgs )
    hudTextArgs.y = hudTextArgs.y + yi

    self.hudText3 = sim.HudText:New( hudTextArgs )
    hudTextArgs.y = hudTextArgs.y + yi

    self.hudText4 = sim.HudText:New( hudTextArgs )
    hudTextArgs.y = hudTextArgs.y + yi

    self.hudText5 = sim.HudText:New( hudTextArgs )
    self.hudText5:SetColor( 1.0, 1.0, 0.0, alpha )  -- yellow
    hudTextArgs.y = hudTextArgs.y + yi

    self.hudText6 = sim.HudText:New( hudTextArgs )
    hudTextArgs.y = hudTextArgs.y + yi

    if ( sim.Base:IfDebug() ) then
        self.hudTextDebug = sim.HudText:New( hudTextArgs )
        hudTextArgs.y = hudTextArgs.y + yi
    end

    self.hudTextOver = sim.HudText:New( { text="", orientation="TOP_LEFT", x=0, y=yi, fontSize = 34.0, } )
    self.hudTextOver:SetColor( 1.0, 0.6, 0.6, 1.0 )

    self.hudTextInfo = sim.HudText:New( { text="", orientation="TOP_LEFT" } )
    self.hudTextInfo:SetColor( 1.0, 1.0, 0.6, 1.0 )
end

-- Set/unset status text.
function Hud:AddStatusText( text )
    -- Already added?
    if ( not string.find( self.statusText, text ) ) then
        self.statusText = lib.CatWords( self.statusText, text )
    end
end

function Hud:RemoveStatusText( text )
    self.statusText = string.gsub( self.statusText, text, "" )
end

function Hud:ClearStatusText()
    self.statusText = ""
end

-- Update HUD.
function Hud:Tick()
    local temp = ""
    local current = PlayerActor:GetAircraft()  -- 3D Object
    local playerDestroyed = PlayerActor:IfDestroyed()
    local physics = current:GetPhysics()
    local posSph = sim.World:WorldVertex2SphereVertex( current:GetPosition() )

    -- Line 1.
    if ( playerDestroyed ) then
        temp = ""
    else
        local speedKPH = sim.Physics:Speed2KPH( physics:ComputeSpeed() )
        local throttle = current:GetThrottle()
        local paused = ""
        if ( sim.Program:IfPaused() ) then paused = "[PAUSED]" end
        temp = string.format( "KPH: %3d THROT: %3d%% FPS: %u  [%dX] %s",
                              speedKPH,
                              throttle * 100.0,
                              sim.Window:GetFPS(),
                              sim.Base:GetSimulationSpeed(),
                              paused )
    end
    self.hudText1:SetText( temp )

    -- Line 2.
    if ( playerDestroyed ) then
        temp = ""
    else
        local belowRadar = nil
        if ( posSph[ALT] < defs.SAM_RADAR_MIN_ALT_METERS ) then
            belowRadar = "BELOW RADAR"
        else
            belowRadar = ""
        end
        temp = string.format( "LAT,LON,ALT: %.2f %.2f %.2f %s",
                              posSph[LAT],
                              posSph[LON],
                              posSph[ALT],
                              belowRadar )
    end
    self.hudText2:SetText( temp )

    -- Line 3.
    if ( playerDestroyed ) then
        temp = ""
    else
        local coturn = ""
        if ( current:IfCoordinatedTurnExecuting() ) then coturn = "  COTURN  " end
        temp = string.format( "DRAG  : %8.2fN WEIGHT: %8.2fN  AoA: %2d %s",
                              Distance3(physics:ComputeDragForce()),
                              Distance3(physics:ComputeWeightForce()),
                              physics:ComputeAngleOfAttack(),
                              coturn )
    end
    self.hudText3:SetText( temp )

    -- Line 4.
    if ( playerDestroyed ) then
        temp = ""
    else
        temp = string.format( "THRUST: %8.2fN LIFT  : %8.2fN",
                              Distance3(physics:ComputeThrustForce()),
                              Distance3(physics:ComputeLiftForce()) )
    end
    self.hudText4:SetText( temp )

    -- Line 5.
    if ( playerDestroyed ) then
        temp = ""
    else
        temp = ""

        if ( current:IfWheelBrakes() ) then
            temp = "WHEEL BRAKES"
        elseif ( current:IfBrakes() ) then
            temp = "AIR BRAKES" 
        end

        if ( physics:IfStall() ) then
            temp = lib.CatWords( temp, "STALL" )
        end

        local replay = PlayerActor:GetReplay()
        if ( replay:IfPlaying() ) then
            temp = lib.CatWords( temp, "REPLAY" )
        elseif ( replay:IfRecording() ) then
            temp = lib.CatWords( temp, "RECORDING REPLAY" )
        end

        -- And show any status text.
        temp = lib.CatWords( temp, self.statusText )
    end
    self.hudText5:SetText( temp )

    -- Line 6.
    if ( sim.argvMap["-jp"] ) then
        -- C++ can compute a string for joystick state faster than Lua.
        temp = string.format( "JOY " .. sim.Joystick:GetStateAsString() )
        self.hudText6:SetText( temp )
    end

    -- Line DEBUG.
    if ( self.hudTextDebug ) then
        local megabytes = sim.Base:GetMemoryUsed() / 1048576
        temp = string.format( "DBG: OBJS=%d MEM=%dMB",
                              sim.Object:GetObjectCount(),
                              sim.Math:TruncInt( megabytes ) )
        self.hudTextDebug:SetText( temp )
    end

    -- "GAME OVER".
    temp = ""
    if ( playerDestroyed ) then
        temp = lib.CatWords( temp, "** GAME OVER ** [INSERT QUARTER] PRESS BACKSPACE" )
    end
    self.hudTextOver:SetText( temp )
end

-- Reset the HUD.
function Hud:Reset()
    self:EnableInfoText( true )
    self:ClearStatusText()
end

-- Enable/disable the top-left info line.
function Hud:EnableInfoText( enable )
    self.enableInfoText = enable

    -- Clear info text if disabled.
    if ( not enable ) then
        self.hudTextInfo:SetText( "" )
    end
end

-- Set text in the top-left info line.
function Hud:SetInfoText( infoText )
    if ( self.enableInfoText ) then
        self.hudTextInfo:SetText( infoText )
    end
end

Events:RegisterReset( function() Hud:Reset() end )  -- need anon func

-- Start HUD.
Hud:Init()
