{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}

-- | Provides the GlobalState and everything to mutate it.
module Language.Ltml.ToLaTeX.GlobalState
    ( GlobalState (..)
    , DocType (..)
    {- functions to mutate counters -}
    , nextSupersection
    , nextSection
    , nextInsertedSection
    , nextParagraph
    , nextSentence
    , nextFootnote
    , nextAppendix
    , resetCountersHard
    , resetCountersSoft
    {- other helper functions to mutate the globalstate -}
    , insertRefLabel
    , nextEnumPosition
    , descendEnumTree
    , addTOCEntry
    , addAppendixHeaderEntry
    , addHeaderFooter
    {- lenses -}
    , counterState
    , flagState
    , formatState
    , supersectionCTR
    , sectionCTR
    , insertedSectionCTR
    , paragraphCTR
    , sentenceCTR
    , footnoteCTR
    , appendixCTR
    , tocLabelCTR
    , enumPosition
    , enumIdentifierFormat
    , appendixFormat
    , docHeadingFormat
    , sectionFormat
    , onlyOneParagraph
    , flaggedParent
    , flaggedChildren
    , docType
    , labelToRef
    , labelToFootNote
    , toc
    , appendixHeaders
    , preDocument
    {- initial states -}
    , initialGlobalState
    , initialCounterState
    , initialFlagState
    ) where

import Control.Lens (makeLenses, use, (%=), (.=), (<+=))
import Control.Monad (forM_)
import Control.Monad.State (State)

import qualified Data.DList as DList
import Data.Map (Map, insert)
import qualified Data.Text as T
import Language.Lsd.AST.Format (IdentifierFormat, KeyFormat, MainHeadingFormat)
import Language.Lsd.AST.Type.AppendixSection (AppendixElementFormat)
import Language.Lsd.AST.Type.DocumentContainer
    ( HeaderFooterFormat (HeaderFooterFormat)
    )
import Language.Lsd.AST.Type.Section (SectionFormat)
import Language.Ltml.AST.Footnote (Footnote)
import Language.Ltml.AST.Label (Label (Label))
import Language.Ltml.ToLaTeX.Format
    ( emptyAppendixFormat
    , emptyHeadingFormat
    , emptyIdentifierFormat
    , emptySectionFormat
    , formatHeaderFooterItem
    , formatKey
    , getIdentifier
    , staticDocumentFormat
    )
import Language.Ltml.ToLaTeX.PreLaTeXType
    ( PreLaTeX (ISequence, IText)
    , fancyfoot
    , fancyhead
    , hyperlink
    , hypertarget
    , linebreak
    )

-- | State for generating and keeping track of context
data GlobalState = GlobalState
    { GlobalState -> CounterState
_counterState :: CounterState
    -- ^ Counters to keep track of the position in the document
    , GlobalState -> FlagState
_flagState :: FlagState
    -- ^ Flags for special cases
    , GlobalState -> FormatState
_formatState :: FormatState
    , GlobalState -> [Int]
_enumPosition :: [Int]
    -- ^ Path for current enum position
    , -- \| Maps for labels
      GlobalState -> Map Label Text
_labelToRef :: Map Label T.Text
    -- ^ since the style of the identifier is defined globally for an
    --          enumeration or appendix we need to pass it to the kids
    , GlobalState -> Map Label Footnote
_labelToFootNote :: Map Label Footnote
    , GlobalState -> DList PreLaTeX
_toc :: DList.DList PreLaTeX
    -- ^ functional list that builds the table of contents
    , GlobalState -> DList PreLaTeX
_appendixHeaders :: DList.DList PreLaTeX
    , GlobalState -> PreLaTeX
_preDocument :: PreLaTeX
    -- ^ pre-document is used to store the header and footer of the document
    }
    deriving (Int -> GlobalState -> ShowS
[GlobalState] -> ShowS
GlobalState -> [Char]
(Int -> GlobalState -> ShowS)
-> (GlobalState -> [Char])
-> ([GlobalState] -> ShowS)
-> Show GlobalState
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> GlobalState -> ShowS
showsPrec :: Int -> GlobalState -> ShowS
$cshow :: GlobalState -> [Char]
show :: GlobalState -> [Char]
$cshowList :: [GlobalState] -> ShowS
showList :: [GlobalState] -> ShowS
Show)

data CounterState = CounterState
    { CounterState -> Int
_supersectionCTR :: Int
    , CounterState -> Int
_sectionCTR :: Int
    , CounterState -> Int
_insertedSectionCTR :: Int
    , CounterState -> Int
_paragraphCTR :: Int
    , CounterState -> Int
_sentenceCTR :: Int
    , CounterState -> Int
_footnoteCTR :: Int
    , CounterState -> Int
_appendixCTR :: Int
    , CounterState -> Int
_tocLabelCTR :: Int
    }
    deriving (Int -> CounterState -> ShowS
[CounterState] -> ShowS
CounterState -> [Char]
(Int -> CounterState -> ShowS)
-> (CounterState -> [Char])
-> ([CounterState] -> ShowS)
-> Show CounterState
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterState -> ShowS
showsPrec :: Int -> CounterState -> ShowS
$cshow :: CounterState -> [Char]
show :: CounterState -> [Char]
$cshowList :: [CounterState] -> ShowS
showList :: [CounterState] -> ShowS
Show)

data FlagState = FlagState
    { FlagState -> Bool
_onlyOneParagraph :: Bool
    , FlagState -> Bool
_flaggedParent :: Bool
    -- ^ needed for sections with only one paragraph
    , FlagState -> Bool
_flaggedChildren :: Bool
    , FlagState -> DocType
_docType :: DocType
    }
    -- \| needed to distinguish between main document and appendix

    deriving (Int -> FlagState -> ShowS
[FlagState] -> ShowS
FlagState -> [Char]
(Int -> FlagState -> ShowS)
-> (FlagState -> [Char])
-> ([FlagState] -> ShowS)
-> Show FlagState
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FlagState -> ShowS
showsPrec :: Int -> FlagState -> ShowS
$cshow :: FlagState -> [Char]
show :: FlagState -> [Char]
$cshowList :: [FlagState] -> ShowS
showList :: [FlagState] -> ShowS
Show)

-- | introduced a datatype instead of using bool to make it easily extensible
data DocType = Main | Appendix
    deriving (Int -> DocType -> ShowS
[DocType] -> ShowS
DocType -> [Char]
(Int -> DocType -> ShowS)
-> (DocType -> [Char]) -> ([DocType] -> ShowS) -> Show DocType
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DocType -> ShowS
showsPrec :: Int -> DocType -> ShowS
$cshow :: DocType -> [Char]
show :: DocType -> [Char]
$cshowList :: [DocType] -> ShowS
showList :: [DocType] -> ShowS
Show, DocType -> DocType -> Bool
(DocType -> DocType -> Bool)
-> (DocType -> DocType -> Bool) -> Eq DocType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DocType -> DocType -> Bool
== :: DocType -> DocType -> Bool
$c/= :: DocType -> DocType -> Bool
/= :: DocType -> DocType -> Bool
Eq)

data FormatState = FormatState
    { FormatState -> MainHeadingFormat
_docHeadingFormat :: MainHeadingFormat
    , FormatState -> AppendixElementFormat
_appendixFormat :: AppendixElementFormat
    , FormatState -> IdentifierFormat
_enumIdentifierFormat :: IdentifierFormat
    , FormatState -> SectionFormat
_sectionFormat :: SectionFormat
    }
    deriving (Int -> FormatState -> ShowS
[FormatState] -> ShowS
FormatState -> [Char]
(Int -> FormatState -> ShowS)
-> (FormatState -> [Char])
-> ([FormatState] -> ShowS)
-> Show FormatState
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FormatState -> ShowS
showsPrec :: Int -> FormatState -> ShowS
$cshow :: FormatState -> [Char]
show :: FormatState -> [Char]
$cshowList :: [FormatState] -> ShowS
showList :: [FormatState] -> ShowS
Show)

makeLenses ''GlobalState
makeLenses ''CounterState
makeLenses ''FlagState
makeLenses ''FormatState

nextSupersection :: State GlobalState Int
nextSupersection :: State GlobalState Int
nextSupersection = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
insertedSectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
supersectionCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextSection :: State GlobalState Int
nextSection :: State GlobalState Int
nextSection = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
paragraphCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
sectionCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextInsertedSection :: State GlobalState Int
nextInsertedSection :: State GlobalState Int
nextInsertedSection = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
paragraphCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
insertedSectionCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextParagraph :: State GlobalState Int
nextParagraph :: State GlobalState Int
nextParagraph = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
sentenceCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
paragraphCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextSentence :: State GlobalState Int
nextSentence :: State GlobalState Int
nextSentence = do
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
sentenceCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextFootnote :: State GlobalState Int
nextFootnote :: State GlobalState Int
nextFootnote = do
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
footnoteCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextAppendix :: State GlobalState Int
nextAppendix :: State GlobalState Int
nextAppendix = do
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
appendixCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

nextTOCLabel :: State GlobalState Int
nextTOCLabel :: State GlobalState Int
nextTOCLabel = do
    (CounterState -> (Int, CounterState))
-> GlobalState -> (Int, GlobalState)
Lens' GlobalState CounterState
counterState ((CounterState -> (Int, CounterState))
 -> GlobalState -> (Int, GlobalState))
-> ((Int -> (Int, Int)) -> CounterState -> (Int, CounterState))
-> (Int -> (Int, Int))
-> GlobalState
-> (Int, GlobalState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> CounterState -> (Int, CounterState)
Lens' CounterState Int
tocLabelCTR ((Int -> (Int, Int)) -> GlobalState -> (Int, GlobalState))
-> Int -> State GlobalState Int
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
LensLike' ((,) a) s a -> a -> m a
<+= Int
1

resetCountersHard :: State GlobalState ()
resetCountersHard :: StateT GlobalState Identity ()
resetCountersHard = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
supersectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
sectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
insertedSectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
paragraphCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
footnoteCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
appendixCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0

resetCountersSoft :: State GlobalState ()
resetCountersSoft :: StateT GlobalState Identity ()
resetCountersSoft = do
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
supersectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
sectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
insertedSectionCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
paragraphCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0
    (CounterState -> Identity CounterState)
-> GlobalState -> Identity GlobalState
Lens' GlobalState CounterState
counterState ((CounterState -> Identity CounterState)
 -> GlobalState -> Identity GlobalState)
-> ((Int -> Identity Int) -> CounterState -> Identity CounterState)
-> (Int -> Identity Int)
-> GlobalState
-> Identity GlobalState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Identity Int) -> CounterState -> Identity CounterState
Lens' CounterState Int
footnoteCTR ((Int -> Identity Int) -> GlobalState -> Identity GlobalState)
-> Int -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
0

-- | Get the path to the current level
nextEnumPosition :: State GlobalState [Int]
nextEnumPosition :: State GlobalState [Int]
nextEnumPosition = do
    [Int]
prefix <- Getting [Int] GlobalState [Int] -> State GlobalState [Int]
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting [Int] GlobalState [Int]
Lens' GlobalState [Int]
enumPosition
    let depth :: Int
depth = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
prefix
        newPrefix :: [Int]
newPrefix = [Int] -> [Int]
forall a. HasCallStack => [a] -> [a]
init [Int]
prefix [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [[Int]
prefix [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1]
    ([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState
Lens' GlobalState [Int]
enumPosition (([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState)
-> [Int] -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Int]
newPrefix
    [Int] -> State GlobalState [Int]
forall a. a -> StateT GlobalState Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Int]
newPrefix

-- | Go one enum level deeper for the required action
descendEnumTree :: State GlobalState a -> State GlobalState a
descendEnumTree :: forall a. State GlobalState a -> State GlobalState a
descendEnumTree State GlobalState a
action = do
    [Int]
oldPath <- Getting [Int] GlobalState [Int] -> State GlobalState [Int]
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting [Int] GlobalState [Int]
Lens' GlobalState [Int]
enumPosition
    ([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState
Lens' GlobalState [Int]
enumPosition (([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState)
-> [Int] -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Int]
oldPath [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
0]
    a
result <- State GlobalState a
action
    ([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState
Lens' GlobalState [Int]
enumPosition (([Int] -> Identity [Int]) -> GlobalState -> Identity GlobalState)
-> [Int] -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Int]
oldPath
    a -> State GlobalState a
forall a. a -> StateT GlobalState Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
result

insertRefLabel :: Maybe Label -> T.Text -> State GlobalState ()
insertRefLabel :: Maybe Label -> Text -> StateT GlobalState Identity ()
insertRefLabel Maybe Label
mLabel Text
ident =
    Maybe Label
-> (Label -> StateT GlobalState Identity ())
-> StateT GlobalState Identity ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe Label
mLabel ((Label -> StateT GlobalState Identity ())
 -> StateT GlobalState Identity ())
-> (Label -> StateT GlobalState Identity ())
-> StateT GlobalState Identity ()
forall a b. (a -> b) -> a -> b
$ \Label
l -> (Map Label Text -> Identity (Map Label Text))
-> GlobalState -> Identity GlobalState
Lens' GlobalState (Map Label Text)
labelToRef ((Map Label Text -> Identity (Map Label Text))
 -> GlobalState -> Identity GlobalState)
-> (Map Label Text -> Map Label Text)
-> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Label -> Text -> Map Label Text -> Map Label Text
forall k a. Ord k => k -> a -> Map k a -> Map k a
insert Label
l Text
ident

-- | the state uses a dlist to keep track of the toc. so we render the (mostly) heading,
--   wrap it in a hyperlink, to make the final pdf interactive. returns the corresponding
--   hypertarget.
addTOCEntry
    :: Int
    -> Int
    -> KeyFormat
    -> IdentifierFormat
    -> PreLaTeX
    -> State GlobalState PreLaTeX
addTOCEntry :: Int
-> Int
-> KeyFormat
-> IdentifierFormat
-> PreLaTeX
-> State GlobalState PreLaTeX
addTOCEntry Int
n Int
ni KeyFormat
keyident IdentifierFormat
ident PreLaTeX
headingText = do
    Int
m <- State GlobalState Int
nextTOCLabel
    let tocLabel :: Label
tocLabel = Text -> Label
Label (Text -> Label) -> Text -> Label
forall a b. (a -> b) -> a -> b
$ [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
m [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/"
    (DList PreLaTeX -> Identity (DList PreLaTeX))
-> GlobalState -> Identity GlobalState
Lens' GlobalState (DList PreLaTeX)
toc
        ((DList PreLaTeX -> Identity (DList PreLaTeX))
 -> GlobalState -> Identity GlobalState)
-> (DList PreLaTeX -> DList PreLaTeX)
-> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= ( DList PreLaTeX -> DList PreLaTeX -> DList PreLaTeX
forall a. Semigroup a => a -> a -> a
<>
                [PreLaTeX] -> DList PreLaTeX
forall a. [a] -> DList a
DList.fromList
                    [ Label -> PreLaTeX -> PreLaTeX
hyperlink
                        Label
tocLabel
                        ( [PreLaTeX] -> PreLaTeX
ISequence
                            [ KeyFormat -> PreLaTeX -> PreLaTeX
formatKey KeyFormat
keyident (Text -> PreLaTeX
IText (Text -> PreLaTeX) -> Text -> PreLaTeX
forall a b. (a -> b) -> a -> b
$ IdentifierFormat -> Int -> Int -> Text
getIdentifier IdentifierFormat
ident Int
n Int
ni)
                            , Text -> PreLaTeX
IText Text
" "
                            , PreLaTeX
headingText
                            ]
                        )
                    , PreLaTeX
linebreak
                    ]
           )
    PreLaTeX -> State GlobalState PreLaTeX
forall a. a -> StateT GlobalState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (PreLaTeX -> State GlobalState PreLaTeX)
-> PreLaTeX -> State GlobalState PreLaTeX
forall a b. (a -> b) -> a -> b
$ Label -> PreLaTeX -> PreLaTeX
hypertarget Label
tocLabel PreLaTeX
forall a. Monoid a => a
mempty

-- | since the toc is emptied for each document, but we need the headings of the appendices
--   in the main document, we collect it with this function as well
addAppendixHeaderEntry
    :: Int -> KeyFormat -> IdentifierFormat -> PreLaTeX -> State GlobalState ()
addAppendixHeaderEntry :: Int
-> KeyFormat
-> IdentifierFormat
-> PreLaTeX
-> StateT GlobalState Identity ()
addAppendixHeaderEntry Int
n KeyFormat
keyident IdentifierFormat
ident PreLaTeX
headingText =
    (DList PreLaTeX -> Identity (DList PreLaTeX))
-> GlobalState -> Identity GlobalState
Lens' GlobalState (DList PreLaTeX)
appendixHeaders
        ((DList PreLaTeX -> Identity (DList PreLaTeX))
 -> GlobalState -> Identity GlobalState)
-> (DList PreLaTeX -> DList PreLaTeX)
-> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= ( DList PreLaTeX -> DList PreLaTeX -> DList PreLaTeX
forall a. Semigroup a => a -> a -> a
<>
                [PreLaTeX] -> DList PreLaTeX
forall a. [a] -> DList a
DList.fromList
                    [ KeyFormat -> PreLaTeX -> PreLaTeX
formatKey KeyFormat
keyident (Text -> PreLaTeX
IText (Text -> PreLaTeX) -> Text -> PreLaTeX
forall a b. (a -> b) -> a -> b
$ IdentifierFormat -> Int -> Int -> Text
getIdentifier IdentifierFormat
ident Int
n Int
0)
                    , Text -> PreLaTeX
IText Text
" "
                    , PreLaTeX
headingText
                    , PreLaTeX
linebreak
                    ]
           )

-- | function to fill the header and footer with the required content
addHeaderFooter
    :: HeaderFooterFormat
    -> HeaderFooterFormat
    -> T.Text
    -> T.Text
    -> T.Text
    -> State GlobalState ()
addHeaderFooter :: HeaderFooterFormat
-> HeaderFooterFormat
-> Text
-> Text
-> Text
-> StateT GlobalState Identity ()
addHeaderFooter
    (HeaderFooterFormat [HeaderFooterItemFormat]
topLeft [HeaderFooterItemFormat]
topCenter [HeaderFooterItemFormat]
topRight)
    (HeaderFooterFormat [HeaderFooterItemFormat]
botLeft [HeaderFooterItemFormat]
botCenter [HeaderFooterItemFormat]
botRight)
    Text
superTitle
    Text
title
    Text
date = do
        let superTitle' :: PreLaTeX
superTitle' = Text -> PreLaTeX
IText Text
superTitle
            title' :: PreLaTeX
title' = Text -> PreLaTeX
IText Text
title
            date' :: PreLaTeX
date' = Text -> PreLaTeX
IText Text
date
            assemble :: [HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
items = [PreLaTeX] -> PreLaTeX
ISequence ([PreLaTeX] -> PreLaTeX) -> [PreLaTeX] -> PreLaTeX
forall a b. (a -> b) -> a -> b
$ (HeaderFooterItemFormat -> PreLaTeX)
-> [HeaderFooterItemFormat] -> [PreLaTeX]
forall a b. (a -> b) -> [a] -> [b]
map (PreLaTeX
-> PreLaTeX -> PreLaTeX -> HeaderFooterItemFormat -> PreLaTeX
formatHeaderFooterItem PreLaTeX
superTitle' PreLaTeX
title' PreLaTeX
date') [HeaderFooterItemFormat]
items
        (PreLaTeX -> Identity PreLaTeX)
-> GlobalState -> Identity GlobalState
Lens' GlobalState PreLaTeX
preDocument
            ((PreLaTeX -> Identity PreLaTeX)
 -> GlobalState -> Identity GlobalState)
-> (PreLaTeX -> PreLaTeX) -> StateT GlobalState Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= ( PreLaTeX -> PreLaTeX -> PreLaTeX
forall a. Semigroup a => a -> a -> a
<>
                    [PreLaTeX] -> PreLaTeX
ISequence
                        [ [Text] -> PreLaTeX -> PreLaTeX
fancyhead [Text
"l"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
topLeft)
                        , [Text] -> PreLaTeX -> PreLaTeX
fancyhead [Text
"c"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
topCenter)
                        , [Text] -> PreLaTeX -> PreLaTeX
fancyhead [Text
"r"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
topRight)
                        , [Text] -> PreLaTeX -> PreLaTeX
fancyfoot [Text
"l"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
botLeft)
                        , [Text] -> PreLaTeX -> PreLaTeX
fancyfoot [Text
"c"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
botCenter)
                        , [Text] -> PreLaTeX -> PreLaTeX
fancyfoot [Text
"r"] ([HeaderFooterItemFormat] -> PreLaTeX
assemble [HeaderFooterItemFormat]
botRight)
                        ]
               )

-- | state with everything set to 0 or mempty. only the
--   staticDocumentFormat (which is used to build the final pdf)
--   is preset in Format.hs
initialGlobalState :: GlobalState
initialGlobalState :: GlobalState
initialGlobalState =
    CounterState
-> FlagState
-> FormatState
-> [Int]
-> Map Label Text
-> Map Label Footnote
-> DList PreLaTeX
-> DList PreLaTeX
-> PreLaTeX
-> GlobalState
GlobalState
        CounterState
initialCounterState
        FlagState
initialFlagState
        FormatState
initialFormatState
        [Int
0]
        Map Label Text
forall a. Monoid a => a
mempty
        Map Label Footnote
forall a. Monoid a => a
mempty
        DList PreLaTeX
forall a. Monoid a => a
mempty
        DList PreLaTeX
forall a. Monoid a => a
mempty
        PreLaTeX
staticDocumentFormat

initialCounterState :: CounterState
initialCounterState :: CounterState
initialCounterState =
    Int
-> Int -> Int -> Int -> Int -> Int -> Int -> Int -> CounterState
CounterState
        Int
0
        Int
0
        Int
0
        Int
0
        Int
0
        Int
0
        Int
0
        Int
0

initialFlagState :: FlagState
initialFlagState :: FlagState
initialFlagState =
    Bool -> Bool -> Bool -> DocType -> FlagState
FlagState
        Bool
False -- onlyOneParagraph
        Bool
False -- isSupersection
        Bool
False
        DocType
Main -- isAppendix

initialFormatState :: FormatState
initialFormatState :: FormatState
initialFormatState =
    MainHeadingFormat
-> AppendixElementFormat
-> IdentifierFormat
-> SectionFormat
-> FormatState
FormatState
        MainHeadingFormat
forall (b :: Bool). HeadingFormat b
emptyHeadingFormat
        AppendixElementFormat
emptyAppendixFormat
        IdentifierFormat
emptyIdentifierFormat
        SectionFormat
emptySectionFormat