module UI.BrickHelpers where
import Text.Wrap
import Brick
import Brick.Widgets.Border
import Brick.Widgets.Center
import Data.Text (pack)
import Graphics.Vty (imageWidth, imageHeight, charFill)
import Lens.Micro
import UI.Attributes

hCenteredStrWrap :: String -> Widget n
hCenteredStrWrap = hCenteredStrWrapWithAttr id

hCenteredStrWrapWithAttr :: (Widget n -> Widget n) -> String -> Widget n
hCenteredStrWrapWithAttr attr p = Widget Greedy Fixed $ do
  c <- getContext
  let w = c^.availWidthL
  let result = vBox $ map (hCenter . attr . txt) $ wrapTextToLines (WrapSettings {preserveIndentation=False, breakLongWords=True}) w (pack p)
  render result

-- Somewhat inefficient because rendering is done just to
-- determine the width and height. So don't use this if the
-- rendering is expensive.
centerPopup :: Widget n -> Widget n
centerPopup widget = Widget Fixed Fixed $ do
  c <- getContext
  result <- render widget
  let w = result^.imageL.to imageWidth
      h = result^.imageL.to imageHeight
      x = (c^.availWidthL - w) `div` 2
      y = (c^.availHeightL - h) `div` 2
  render $ translateBy (Location (x, y)) widget

drawException :: Maybe String -> Widget n
drawException Nothing = emptyWidget
drawException (Just e) =
        centerPopup $
        borderWithLabel (str "Error") $
        withAttr exceptionAttr $ str e

-- | Fill all available space with the specified character. Grows only
-- horizontally.
hFill :: Char -> Widget n
hFill ch =
    Widget Greedy Fixed $ do
      c <- getContext
      return $ emptyResult & imageL .~ charFill (c^.attrL) ch (c^.availWidthL) 1

-- | Fill all available space with the specified character. Grows only
-- vertically.
vFill :: Char -> Widget n
vFill ch =
    Widget Fixed Greedy $ do
      c <- getContext
      return $ emptyResult & imageL .~ charFill (c^.attrL) ch 1 (c^.availHeightL)

-- | Make widget at least some amount of rows high.
atLeastV :: Int -> Widget n -> Widget n
atLeastV n widget = Widget Fixed Fixed $ do
  c <- getContext
  result <- render widget
  let h  = result^.imageL.to imageHeight
      dh = n - h
  if dh > 0 then render $ vLimit n (widget <=> vFill ' ') else render widget