    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE CPP #-}
    -- | This module provides a progress bar widget.
    module Brick.Widgets.ProgressBar
      ( progressBar
      , customProgressBar
      -- * Attributes
      , progressCompleteAttr
      , progressIncompleteAttr
      )
    where

    import Lens.Micro ((^.))
    import Data.Maybe (fromMaybe)
    #if !(MIN_VERSION_base(4,11,0))
    import Data.Monoid
    #endif
    import Graphics.Vty (safeWcswidth)

    import Brick.Types
    import Brick.AttrMap
    import Brick.Widgets.Core

    -- | The attribute of the completed portion of the progress bar.
    progressCompleteAttr :: AttrName
    progressCompleteAttr :: AttrName
    progressCompleteAttr = String -> AttrName
    attrName String
    "progressComplete"

    -- | The attribute of the incomplete portion of the progress bar.
    progressIncompleteAttr :: AttrName
    progressIncompleteAttr :: AttrName
    progressIncompleteAttr = String -> AttrName
    attrName String
    "progressIncomplete"

    -- | Draw a progress bar with the specified (optional) label and
    -- progress value. This fills available horizontal space and is one row
    -- high.
    progressBar :: Maybe String
                -- ^ The label. If specified, this is shown in the center of
                -- the progress bar.
                -> Float
                -- ^ The progress value. Should be between 0 and 1 inclusive.
                -> Widget n
    progressBar :: forall n. Maybe String -> Float -> Widget n
    progressBar = Char -> Char -> Maybe String -> Float -> Widget n
    forall n. Char -> Char -> Maybe String -> Float -> Widget n
    customProgressBar Char
    ' ' Char
    ' '

    -- | Draw a progress bar with the specified (optional) label,
    -- progress value and custom characters to fill the progress.
    -- This fills available horizontal space and is one row high.
    -- Please be aware of using wide characters in Brick,
    -- see [Wide Character Support and the TextWidth class](https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst#wide-character-support-and-the-textwidth-class)
    customProgressBar :: Char
                      -- ^ Character to fill the completed part.
                      -> Char
                      -- ^ Character to fill the incomplete part.
                      -> Maybe String
                      -- ^ The label. If specified, this is shown in the center of
                      -- the progress bar.
                      -> Float
                      -- ^ The progress value. Should be between 0 and 1 inclusive.
                      -> Widget n
    customProgressBar :: forall n. Char -> Char -> Maybe String -> Float -> Widget n
    customProgressBar Char
    completeChar Char
    incompleteChar Maybe String
    mLabel Float
    progress =
        Size -> Size -> RenderM n (Result n) -> Widget n
    forall n. Size -> Size -> RenderM n (Result n) -> Widget n
    Widget Size
    Greedy Size
    Fixed (RenderM n (Result n) -> Widget n)
    -> RenderM n (Result n) -> Widget n
    forall a b. (a -> b) -> a -> b
    $ do
            c <- RenderM n (Context n)
    forall n. RenderM n (Context n)
    getContext
            let barWidth = Context n
    cContext n -> Getting Int (Context n) Int -> Int
    forall s a. s -> Getting a s a -> a
    ^.Getting Int (Context n) Int
    forall n (f :: * -> *).
    Functor f =>
    (Int -> f Int) -> Context n -> f (Context n)
    availWidthL
                label = String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    "" Maybe String
    mLabel
                labelWidth = String -> Int
    safeWcswidth String
    label
                spacesWidth = Int
    barWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    labelWidth
                leftWidth = Int
    spacesWidth Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    2
                rightWidth = Int
    barWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    labelWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    leftWidth
                completeWidth = Float -> Int
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Float -> Int) -> Float -> Int
    forall a b. (a -> b) -> a -> b
    $ Float
    progress Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Int -> Float
    forall a. Enum a => Int -> a
    toEnum Int
    barWidth

                leftCompleteWidth = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    leftWidth Int
    completeWidth
                leftIncompleteWidth = Int
    leftWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    leftCompleteWidth
                leftPart = Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate Int
    leftCompleteWidth Char
    completeChar String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate Int
    leftIncompleteWidth Char
    incompleteChar
                rightCompleteWidth = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    0 (Int
    completeWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    labelWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    leftWidth)
                rightIncompleteWidth = Int
    rightWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    rightCompleteWidth
                rightPart = Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate Int
    rightCompleteWidth Char
    completeChar String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate Int
    rightIncompleteWidth Char
    incompleteChar

                fullBar = String
    leftPart String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    label String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    rightPart
                adjustedCompleteWidth = if Int
    completeWidth Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == String -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    fullBar Bool -> Bool -> Bool
    && Float
    progress Float -> Float -> Bool
    forall a. Ord a => a -> a -> Bool
    < Float
    1.0
                                        then Int
    completeWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
                                        else if Int
    completeWidth Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0 Bool -> Bool -> Bool
    && Float
    progress Float -> Float -> Bool
    forall a. Ord a => a -> a -> Bool
    > Float
    0.0
                                             then Int
    1
                                             else Int
    completeWidth
                (completePart, incompletePart) = splitAt adjustedCompleteWidth fullBar
            render $ (withAttr progressCompleteAttr $ str completePart) <+>
                     (withAttr progressIncompleteAttr $ str incompletePart)