{- | The single-line status bar pinned at the bottom of the editor
("Termtab.UI".@drawUI@): file\/modified state, tempo and time signature,
cursor position and zoom, playback state, and any transient status
message — or, while typing a command, the command line itself in place
of all of that.
-}
module Termtab.UI.Widgets.StatusBar (renderStatusBar, statusBarAttr, commandModeAttr) where

import Brick
import System.FilePath (takeFileName)

import Termtab.Audio.Types (PlaybackStatus (..))
import Termtab.Types
import Termtab.UI.Types

{- | Attribute name for the normal status-bar styling (see "Termtab.UI"'s
@theAttrMap@ for the actual Vty style).
-}
statusBarAttr :: AttrName
statusBarAttr :: AttrName
statusBarAttr = [Char] -> AttrName
attrName [Char]
"statusBar"

{- | Attribute name for the @:@-prefixed command line shown while
'CommandMode' is active.
-}
commandModeAttr :: AttrName
commandModeAttr :: AttrName
commandModeAttr = [Char] -> AttrName
attrName [Char]
"commandMode"

{- | Render the status bar for the current 'AppState'. Shows the raw
command buffer (prefixed with @:@) when 'asInputMode' is 'CommandMode';
otherwise shows the usual file\/tempo\/position\/playback summary, with
any 'asMessage' appended at the end.
-}
renderStatusBar :: AppState -> Widget ResourceName
renderStatusBar :: AppState -> Widget ResourceName
renderStatusBar AppState
st = case AppState -> InputMode
asInputMode AppState
st of
    CommandMode [Char]
buf ->
        AttrName -> Widget ResourceName -> Widget ResourceName
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
commandModeAttr (Widget ResourceName -> Widget ResourceName)
-> Widget ResourceName -> Widget ResourceName
forall a b. (a -> b) -> a -> b
$
            [Char] -> Widget ResourceName
forall n. [Char] -> Widget n
str ([Char]
":" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
buf)
    InputMode
_ ->
        AttrName -> Widget ResourceName -> Widget ResourceName
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
statusBarAttr (Widget ResourceName -> Widget ResourceName)
-> Widget ResourceName -> Widget ResourceName
forall a b. (a -> b) -> a -> b
$
            [Widget ResourceName] -> Widget ResourceName
forall n. [Widget n] -> Widget n
hBox
                [ Widget ResourceName
forall {n}. Widget n
fileInfo
                , Char -> Widget ResourceName
forall n. Char -> Widget n
fill Char
' '
                , Widget ResourceName
forall {n}. Widget n
tempoInfo
                , Char -> Widget ResourceName
forall n. Char -> Widget n
fill Char
' '
                , Widget ResourceName
forall {n}. Widget n
positionInfo
                , Widget ResourceName
forall {n}. Widget n
playbackInfo
                , case AppState -> Maybe [Char]
asMessage AppState
st of
                    Just [Char]
msg -> [Char] -> Widget ResourceName
forall n. [Char] -> Widget n
str ([Char]
"  " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
msg)
                    Maybe [Char]
Nothing -> Widget ResourceName
forall {n}. Widget n
emptyWidget
                ]
  where
    fileInfo :: Widget n
fileInfo =
        let modified :: [Char]
modified = if [Song] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (AppState -> [Song]
asUndoStack AppState
st) then [Char]
"" else [Char]
" [modified]"
         in [Char] -> Widget n
forall n. [Char] -> Widget n
str ([Char] -> Widget n) -> [Char] -> Widget n
forall a b. (a -> b) -> a -> b
$ case AppState -> Maybe [Char]
asFilePath AppState
st of
                Just [Char]
fp -> [Char]
"File: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
takeFileName [Char]
fp [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
modified
                Maybe [Char]
Nothing -> [Char]
"[scratch]" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
modified

    tempoInfo :: Widget n
tempoInfo =
        let Tempo Int
bpm = Song -> Tempo
songTempo (AppState -> Song
asSong AppState
st)
            timeSig :: [Char]
timeSig = case AppState -> Maybe Measure
currentMeasure AppState
st of
                Just Measure
m ->
                    let TimeSignature Int
num Int
den = Measure -> TimeSignature
timeSignature Measure
m
                     in Int -> [Char]
forall a. Show a => a -> [Char]
show Int
num [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
den
                Maybe Measure
Nothing -> [Char]
"4/4"
         in [Char] -> Widget n
forall n. [Char] -> Widget n
str ([Char]
"Tempo: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
bpm [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" BPM  " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
timeSig)

    positionInfo :: Widget n
positionInfo =
        let MeasureIndex Int
m = AppState -> MeasureIndex
asCurrentMeasure AppState
st
            total :: Int
total = AppState -> Int
measureCount AppState
st
         in [Char] -> Widget n
forall n. [Char] -> Widget n
str ([Char]
"Bar: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
total [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"  [zoom: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (AppState -> Int
asZoom AppState
st) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]")

    playbackInfo :: Widget n
playbackInfo = case AppState -> PlaybackStatus
asPlaybackStatus AppState
st of
        PlaybackStatus
Playing -> [Char] -> Widget n
forall n. [Char] -> Widget n
str [Char]
" [PLAYING]"
        PlaybackStatus
Paused -> [Char] -> Widget n
forall n. [Char] -> Widget n
str [Char]
" [PAUSED]"
        PlaybackStatus
Stopped -> Widget n
forall {n}. Widget n
emptyWidget