content: -- A 'Picture' is a background paired with a set of 'Image' layers. The
  -- 'Picture' data structure is representative of the final terminal
  -- view.
  module Graphics.Vty.Picture
    ( Picture(..)
    , Cursor(..)
    , Background(..)
    , emptyPicture
    , addToTop
    , addToBottom
    , picForImage
    , picForLayers
    , picImage
    )
  where
  
  import Graphics.Vty.Image
  import Graphics.Vty.Attributes
  
  import Control.DeepSeq
  
  -- | A Vty picture.
  --
  -- These can be constructed directly or using `picForImage`.
  data Picture = Picture
      { picCursor :: Cursor
      -- ^ The picture's cursor.
      , picLayers :: [Image]
      -- ^ The picture's image layers (top-most first).
      , picBackground :: Background
      -- ^ The picture's background to be displayed in locations with no
      -- Image data.
      } deriving (Eq, Show)
  
  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
  
  -- | Add an 'Image' as the top-most layer of a 'Picture'.
  addToTop :: Picture -> Image -> Picture
  addToTop p i = p {picLayers = i : picLayers p}
  
  -- | Add an 'Image' as the bottom-most layer of a 'Picture'.
  addToBottom :: Picture -> Image -> Picture
  addToBottom p i = p {picLayers = picLayers p ++ [i]}
  
  -- | Create a picture from 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 with the given layers, top-most first.
  --
  -- The picture will not have a displayed cursor and no background
  -- pattern (ClearBackgroun) will be used.
  picForLayers :: [Image] -> Picture
  picForLayers is = Picture
      { picCursor = NoCursor
      , picLayers = is
      , picBackground = ClearBackground
      }
  
  -- | A picture can be configured to hide the cursor or to show the
  -- cursor at the specified character position.
  --
  -- There is not a 1:1 map from character positions to a row and column
  -- on the screen due to characters that take more than 1 column.
  data Cursor =
      -- | Hide the cursor
      NoCursor
      -- | Set the terminal's cursor position without displaying a cursor
      -- character. This is important for accessibility with screen
      -- readers where a cursor position needs to be reported but we may
      -- not want to show a block cursor in that location for cosmetic
      -- reasons. The boolean argument indicates whether the positioning
      -- should be absolute as with 'AbsoluteCursor' ('True') or logical
      -- as with 'Cursor' ('False').
      | PositionOnly !Bool !Int !Int
      -- | Show the cursor at the given logical column accounting for
      -- character width in the presence of multi-column characters.
      | Cursor !Int !Int
      -- | Show the cursor at the given absolute terminal column and row
      | AbsoluteCursor !Int !Int
      deriving (Eq, Show)
  
  instance NFData Cursor where
      rnf c = c `seq` ()
  
  -- | A 'Picture' has a background pattern. The background is either:
  --
  -- * ClearBackground, which shows the layer below or is blank if the
  --   bottom layer
  -- * 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.
  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
      deriving (Eq, Show)
  
  instance NFData Background where
      rnf (Background c a) = c `seq` a `seq` ()
      rnf ClearBackground = ()
  
  -- | Return the top-most 'Image' layer for a picture. This is unsafe for
  -- 'Picture's without at least one layer.
  --
  -- This is provided for compatibility with applications that do not use
  -- more than a single layer.
  picImage :: Picture -> Image
  picImage = head . picLayers
  