{-|
Module      : Dep.Bricks.Negation
Description : A module to create images with /negations/ for the /gate/ and /wires/.
Maintainer  : hapytexeu+gh@gmail.com
Stability   : experimental
Portability : POSIX

A module to create images with negations for gates, wires, and other modules.
-}

module Dep.Bricks.Negation (
    -- * Negation for a single wire
    negation, negationH, negationV
    -- * Negation for a list of wires
  , negationList, negationHList, negationVList
  ) where

import Data.Bool(bool)

import Dep.Bricks.Box(negator, linev, lineh)

import Graphics.Vty.Attributes(Attr)
import Graphics.Vty.Image(Image, (<|>), (<->), char, emptyImage)

-- | Create an Image that contains a single character that is either the 'negator' or the given 'Char'.
negation
  :: Char  -- ^ The 'Char' to use in case we do not negate.
  -> Bool  -- ^ A 'Bool' that specifies if this is a negator.
  -> Attr  -- ^ The 'Attr' to use when rendering the image.
  -> Image  -- ^ The corresponding 'Image' for the given (optional) negator.
negation :: Char -> Bool -> Attr -> Image
negation Char
c = (Attr -> Char -> Image) -> Char -> Attr -> Image
forall a b c. (a -> b -> c) -> b -> a -> c
flip Attr -> Char -> Image
char (Char -> Attr -> Image) -> (Bool -> Char) -> Bool -> Attr -> Image
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Char -> Bool -> Char
forall a. a -> a -> Bool -> a
bool Char
c Char
negator

-- | Create an image for a negator on a /horizontal/ wire.
negationH
  :: Bool  -- ^ Specifies if this is a simple wire ('False'), or a negator ('True').
  -> Attr  -- ^ The 'Attr' to use when rendering the image.
  -> Image  -- ^ The corresponding 'Image' for the given (optional) negator.
negationH :: Bool -> Attr -> Image
negationH = Char -> Bool -> Attr -> Image
negation Char
linev

-- | Create an image for a negator on a /vertical/ wire.
negationV
  :: Bool  -- ^ Specifies if this is a simple wire ('False'), or a negator ('True').
  -> Attr  -- ^ The 'Attr' to use when rendering the image.
  -> Image  -- ^ The corresponding 'Image' for the given (optional) negator.
negationV :: Bool -> Attr -> Image
negationV = Char -> Bool -> Attr -> Image
negation Char
lineh

-- | Create a list of negators in one of the two directions. The 'Char' specifies
-- what to render in case it is not a negator.
negationList
  :: (Image -> Image -> Image)  -- ^ A function to merge two 'Image's together.
  -> Char  -- ^ A 'Char' that specifies what to render in case we do not render a negator.
  -> [Bool]  -- ^ The list of 'Bool's that specifies when a negator occurs.
  -> Attr  -- ^ The 'Attr' that specifies the style of the negators.
  -> Image  -- ^ The corresponding 'Image' that contains wires and negators.
negationList :: (Image -> Image -> Image) -> Char -> [Bool] -> Attr -> Image
negationList Image -> Image -> Image
mgr Char
lns [Bool]
bls Attr
attr = (Bool -> Image -> Image) -> Image -> [Bool] -> Image
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Image -> Image -> Image
mgr (Image -> Image -> Image)
-> (Bool -> Image) -> Bool -> Image -> Image
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Attr -> Image
`go` Attr
attr)) Image
emptyImage [Bool]
bls
  where go :: Bool -> Attr -> Image
go = Char -> Bool -> Attr -> Image
negation Char
lns

-- | Create an 'Image' of negators in the /horizontal/ direction. The wires here are in the /vertical/ direction.
negationHList
  :: [Bool]  -- ^ The list of 'Bool's that specifies when a negator occurs.
  -> Attr  -- ^ The 'Attr' that specifies the style of the negators.
  -> Image  -- ^ The corresponding 'Image' that contains wires and negators.
negationHList :: [Bool] -> Attr -> Image
negationHList = (Image -> Image -> Image) -> Char -> [Bool] -> Attr -> Image
negationList Image -> Image -> Image
(<|>) Char
linev

-- | Create an 'Image' of negators in the /vertical/ direction. The wires here are in the /horizontal/ direction.
negationVList
  :: [Bool]  -- ^ The list of 'Bool's that specifies when a negator occurs.
  -> Attr  -- ^ The 'Attr' that specifies the style of the negators.
  -> Image  -- ^ The corresponding 'Image' that contains wires and negators.
negationVList :: [Bool] -> Attr -> Image
negationVList = (Image -> Image -> Image) -> Char -> [Bool] -> Attr -> Image
negationList Image -> Image -> Image
(<->) Char
lineh