    {-# LANGUAGE BangPatterns #-}
    -- | The 'Picture' data structure is representative of the final terminal view.
    --
    -- A 'Picture' is a background paired with a layer of 'Image's.
    module Graphics.Vty.Picture ( module Graphics.Vty.Picture
                                , module Graphics.Vty.Image
                                )
        where

    import Graphics.Vty.Image

    import Control.DeepSeq

    -- | The type of images to be displayed using 'update'.
    --
    -- Can be constructed directly or using `picForImage`. Which provides an initial instance with
    -- reasonable defaults for picCursor and picBackground.
    data Picture = Picture
        { picCursor :: Cursor
        , picLayers :: [Image]
        , picBackground :: Background
        }

    instance Show Picture where
        show (Picture _ layers _ ) = "Picture ?? " ++ show layers ++ " ??"

    instance NFData Picture where
        rnf (Picture c l b) = c `deepseq` l `deepseq` b `deepseq` ()

    -- | a picture with no cursor, background or image layers
    emptyPicture :: Picture
    emptyPicture = Picture NoCursor [] ClearBackground

    -- | The given 'Image' is added as the top layer of the 'Picture'
    addToTop :: Picture -> Image -> Picture
    addToTop p i = p {picLayers = i : picLayers p}

    -- | The given 'Image' is added as the bottom layer of the 'Picture'
    addToBottom :: Picture -> Image -> Picture
    addToBottom p i = p {picLayers = picLayers p ++ [i]}

    -- | Create a picture for display for the given image. The picture will not have a displayed cursor
    -- and no background pattern (ClearBackground) will be used.
    picForImage :: Image -> Picture
    picForImage i = Picture
        { picCursor = NoCursor
        , picLayers = [i]
        , picBackground = ClearBackground
        }

    -- | Create a picture for display with the given layers. Ordered top to bottom.
    --
    -- The picture will not have a displayed cursor and no background apttern (ClearBackgroun) will be
    -- used.
    --
    -- The first 'Image' is the top layer.
    picForLayers :: [Image] -> Picture
    picForLayers is = Picture
        { picCursor = NoCursor
        , picLayers = is
        , picBackground = ClearBackground
        }

    -- | A picture can be configured either to not show the cursor or show the cursor at the specified
    -- character position.
    --
    -- There is not a 1 to 1 map from character positions to a row and column on the screen due to
    -- characters that take more than 1 column.
    --
    -- todo: The Cursor can be given a (character,row) offset outside of the visible bounds of the
    -- output region. In this case the cursor will not be shown.
    data Cursor =
          NoCursor
        | Cursor Int Int

    instance NFData Cursor where
        rnf NoCursor = ()
        rnf (Cursor w h) = w `seq` h `seq` ()

    -- | A 'Picture' has a background pattern. The background is either ClearBackground. Which shows the
    -- layer below or is blank if the bottom layer. Or the background pattern is a character and a
    -- display attribute. If the display attribute used previously should be used for a background fill
    -- then use `currentAttr` for the background attribute.
    --
    -- \todo The current attribute is always set to the default attributes at the start of updating the
    -- screen to a picture.
    data Background
        = Background
        { backgroundChar :: Char
        , backgroundAttr :: Attr
        }
         -- | A ClearBackground is:
         --
         -- * the space character if there are remaining non-skip ops
         --
         -- * End of line if there are no remaining non-skip ops.
        | ClearBackground

    instance NFData Background where
        rnf (Background c a) = c `seq` a `seq` ()
        rnf ClearBackground = ()

    -- | Compatibility with applications that do not use more than a single layer.
    picImage :: Picture -> Image
    picImage = head . picLayers