{-# LANGUAGE OverloadedStrings #-}

module Cursor.Brick.Text where

import qualified Data.Text as T
import Data.Text (Text)

import Cursor.Text

import Brick.Types as Brick
import Brick.Widgets.Core as Brick

-- | Make a text cursor widget with a blink-y box.
--
-- This function does not wrap the given text.
--
-- Otherwise, because of the way indexes work, there would be rendering errors for text that crosses the side of the terminal.
selectedTextCursorWidget :: n -> TextCursor -> Widget n
selectedTextCursorWidget n tc =
  Brick.showCursor n (Brick.Location (textCursorIndex tc, 0)) $
  textCursorWidget tc

-- | Make a text cursor widget without a blink-y box.
--
-- This function does not wrap the given text.
textCursorWidget :: TextCursor -> Widget n
textCursorWidget tc =
  txt $
  let t = sanitiseText $ rebuildTextCursor tc
   in if T.null t
        then " "
        else t

-- | Draw an arbitrary Text, it will be sanitised.
textWidget :: Text -> Widget n
textWidget = txt . nonNullLinesText . sanitiseText

-- | Draw an arbitrary Text (with wrapping), it will be sanitised.
textWidgetWrap :: Text -> Widget n
textWidgetWrap = txtWrap . nonNullLinesText . sanitiseText

-- | Draw an arbitrary single-line Text, it will be sanitised.
textLineWidget :: Text -> Widget n
textLineWidget = txt . nonNullText . sanitiseText

-- | Draw an arbitrary single-line Text (with wrapping), it will be sanitised.
textLineWidgetWrap :: Text -> Widget n
textLineWidgetWrap = txtWrap . nonNullText . sanitiseText

-- | Makes every line of a Text non-empty using `nonNullText`
nonNullLinesText :: Text -> Text
nonNullLinesText = T.intercalate "\n" . map nonNullText . T.splitOn "\n"

-- | Makes a text non-empty.
--
-- This turns the empty text into " " and leaves other text as-is.
nonNullText :: Text -> Text
nonNullText "" = " "
nonNullText t = t

-- | Replace tabs by spaces so that brick doesn't render nonsense.
--
-- See https://hackage.haskell.org/package/brick/docs/Brick-Widgets-Core.html#v:txt
sanitiseText :: Text -> Text
sanitiseText =
  T.map $ \c ->
    case c of
      '\t' -> ' '
      _ -> c