module Test.Sandwich.Formatters.TerminalUI.Draw.RunTimes (getRunTimes) where

import Brick
import Data.Maybe
import Data.String.Interpolate
import Data.Time.Clock
import qualified Graphics.Vty as V
import Lens.Micro
import Test.Sandwich.Formatters.Common.Util
import Test.Sandwich.Formatters.TerminalUI.AttrMap
import Test.Sandwich.Formatters.TerminalUI.Types


Int
minGray :: Int = Int
50
Int
maxGray :: Int = Int
255

getRunTimes :: AppState
-> UTCTime
-> UTCTime
-> Maybe NominalDiffTime
-> Maybe NominalDiffTime
-> Bool
-> Widget n
getRunTimes AppState
app UTCTime
startTime UTCTime
endTime Maybe NominalDiffTime
statusSetupTime Maybe NominalDiffTime
statusTeardownTime Bool
showEllipses = Image -> Widget n
forall n. Image -> Widget n
raw Image
setupWork Widget n -> Widget n -> Widget n
forall n. Widget n -> Widget n -> Widget n
<+> Image -> Widget n
forall n. Image -> Widget n
raw Image
actualWork Widget n -> Widget n -> Widget n
forall n. Widget n -> Widget n -> Widget n
<+> Image -> Widget n
forall n. Image -> Widget n
raw Image
teardownWork
  where
    totalElapsed :: NominalDiffTime
totalElapsed = UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime (AppState
app AppState -> Getting UTCTime AppState UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime AppState UTCTime
Lens' AppState UTCTime
appCurrentTime) (AppState
app AppState -> Getting UTCTime AppState UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime AppState UTCTime
Lens' AppState UTCTime
appStartTime)

    actualWorkTime :: NominalDiffTime
actualWorkTime = (UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime UTCTime
endTime UTCTime
startTime) NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
- (NominalDiffTime -> Maybe NominalDiffTime -> NominalDiffTime
forall a. a -> Maybe a -> a
fromMaybe NominalDiffTime
0 Maybe NominalDiffTime
statusSetupTime) NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
- (NominalDiffTime -> Maybe NominalDiffTime -> NominalDiffTime
forall a. a -> Maybe a -> a
fromMaybe NominalDiffTime
0 Maybe NominalDiffTime
statusTeardownTime)

    setupWork :: Image
setupWork = Image
-> (NominalDiffTime -> Image) -> Maybe NominalDiffTime -> Image
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Image
forall a. Monoid a => a
mempty (\NominalDiffTime
dt -> Attr -> String -> Image
V.string (NominalDiffTime -> NominalDiffTime -> Attr
getAttr NominalDiffTime
totalElapsed NominalDiffTime
dt) [i|(#{formatNominalDiffTime dt}) + |]) Maybe NominalDiffTime
statusSetupTime
    actualWork :: Image
actualWork = Attr -> String -> Image
V.string (NominalDiffTime -> NominalDiffTime -> Attr
getAttr NominalDiffTime
totalElapsed NominalDiffTime
actualWorkTime) (NominalDiffTime -> String
formatNominalDiffTime NominalDiffTime
actualWorkTime String -> String -> String
forall a. Semigroup a => a -> a -> a
<> (if Bool
showEllipses then String
"..." else String
""))
    teardownWork :: Image
teardownWork = Image
-> (NominalDiffTime -> Image) -> Maybe NominalDiffTime -> Image
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Image
forall a. Monoid a => a
mempty (\NominalDiffTime
dt -> Attr -> String -> Image
V.string (NominalDiffTime -> NominalDiffTime -> Attr
getAttr NominalDiffTime
totalElapsed NominalDiffTime
dt) [i| + (#{formatNominalDiffTime dt})|]) Maybe NominalDiffTime
statusTeardownTime

getAttr :: NominalDiffTime -> NominalDiffTime -> V.Attr
getAttr :: NominalDiffTime -> NominalDiffTime -> Attr
getAttr NominalDiffTime
totalElapsed NominalDiffTime
dt = V.Attr {
  attrStyle :: MaybeDefault Style
V.attrStyle = MaybeDefault Style
forall v. MaybeDefault v
V.Default
  , attrForeColor :: MaybeDefault Color
V.attrForeColor = Color -> MaybeDefault Color
forall v. v -> MaybeDefault v
V.SetTo (Color -> MaybeDefault Color) -> Color -> MaybeDefault Color
forall a b. (a -> b) -> a -> b
$ Int -> Color
forall {i}. Integral i => i -> Color
grayAt (Int -> Color) -> Int -> Color
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Int
getLevel (NominalDiffTime -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac NominalDiffTime
totalElapsed) (NominalDiffTime -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac NominalDiffTime
dt)
  , attrBackColor :: MaybeDefault Color
V.attrBackColor = MaybeDefault Color
forall v. MaybeDefault v
V.Default
  , attrURL :: MaybeDefault Text
V.attrURL = MaybeDefault Text
forall v. MaybeDefault v
V.Default
  }

getLevel :: Double -> Double -> Int
getLevel :: Double -> Double -> Int
getLevel Double
totalElapsed Double
duration = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
maxGray (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
minGray (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
minGray Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
intensity Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
maxGray Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
minGray))))
  where
    Double
intensity :: Double = Double -> Double -> Double
forall a. Floating a => a -> a -> a
logBase (Double
totalElapsed Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1) (Double
duration Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1)