content: {-
  pandoc-crossref is a pandoc filter for numbering figures,
  equations, tables and cross-references to them.
  Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  -}
  
  {- |
     Module      : Text.Pandoc.CrossRef
     Copyright   : Copyright (C) 2015 Nikolay Yakimov
     License     : GNU GPL, version 2 or above
  
     Maintainer  : Nikolay Yakimov <root@livid.pp.ru>
     Stability   : alpha
     Portability : portable
  
  Public interface to pandoc-crossref library
  
  Example of use:
  
  > import Text.Pandoc
  > import Text.Pandoc.JSON
  >
  > import Text.Pandoc.CrossRef
  >
  > main :: IO ()
  > main = toJSONFilter go
  >   where
  >     go fmt p@(Pandoc meta _) = runCrossRefIO meta fmt action p
  >       where
  >         action (Pandoc _ bs) = do
  >           bs' <- crossRefBlocks bs
  >           meta' <- crossRefMeta
  >           return $ Pandoc meta' bs'
  
  This module also exports utility functions for setting up meta-settings for
  pandoc-crossref. Refer to documentation for a complete list of metadata field
  names. All functions accept a single argument of type, returned by
  "Text.Pandoc.Builder" functions, and return 'Meta'.
  
  Example:
  
  > runCrossRefIO meta fmt crossRefBlocks blocks
  >   where
  >     meta =
  >          figureTitle (str "Figura")
  >       <> tableTitle (str "Tabla")
  >       <> figPrefix (str "fig.")
  >       <> eqnPrefix (str "ec.")
  >       <> tblPrefix (str "tbl.")
  >       <> loftitle (header 1 $ text "Lista de figuras")
  >       <> lotTitle (header 1 $ text "Lista de tablas")
  >       <> chaptersDepth (MetaString "2")
  
  -}
  
  module Text.Pandoc.CrossRef (
      crossRefBlocks
    , crossRefMeta
    , defaultCrossRefAction
    , runCrossRef
    , runCrossRefIO
    , module SG
    , defaultMeta
    , CrossRefM
    , CrossRefEnv(..)
    ) where
  
  import Lens.Micro.Mtl
  import Control.Monad.Reader
  import Text.Pandoc
  
  import Text.Pandoc.CrossRef.References
  import Text.Pandoc.CrossRef.References.Monad
  import Text.Pandoc.CrossRef.Util.ModifyMeta
  import Text.Pandoc.CrossRef.Util.Settings
  import Text.Pandoc.CrossRef.Util.Settings.Gen as SG
  
  import Text.Pandoc.CrossRef.Internal
  
  {- | Walk over blocks, while inserting cross-references, list-of, etc.
  
  Works in 'CrossRefM' monad. -}
  crossRefBlocks :: [Block] -> CrossRefM [Block]
  crossRefBlocks = CrossRefM . lift . replaceAll
  
  {- | Modifies metadata, adding header-includes instructions to setup custom and
  builtin environments, plus list-of-x metadata fields if
  'Text.Pandoc.CrossRef.Util.Settings.Gen.listOfMetadata' is enabled.
  
  Works in 'CrossRefM' monad. -}
  crossRefMeta :: CrossRefM Meta
  crossRefMeta = CrossRefM do
    settings <- ask
    lift do
      opts <- use wsOptions
      liftF $ modifyMeta opts settings
  
  {- | Combines 'crossRefMeta' and 'crossRefBlocks'
  
  Works in 'CrossRefM' monad. -}
  defaultCrossRefAction :: Pandoc -> CrossRefM Pandoc
  defaultCrossRefAction (Pandoc _ bs) = Pandoc <$> crossRefMeta <*> crossRefBlocks bs
  
  {- | Run an action in 'CrossRefM' monad with argument, and return pure result.
  
  This is the primary function to work with 'CrossRefM' -}
  runCrossRef :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
  runCrossRef meta fmt action arg = runCrossRefInternal env $ action arg
    where
      settings = defaultMeta <> meta
      env = CrossRefEnv {
              creSettings = settings
            , creOptions = getOptions settings fmt
            , creReferences = def
           }
  
  {- | Run an action in 'CrossRefM' monad with argument, and return 'IO' result.
  
  This function will attempt to read pandoc-crossref settings from settings
  file specified by crossrefYaml metadata field. -}
  runCrossRefIO :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
  runCrossRefIO meta fmt action arg = do
    settings <- getSettings fmt meta
    let
      env = CrossRefEnv {
              creSettings = settings
            , creOptions = getOptions settings fmt
            , creReferences = def
           }
    pure $ runCrossRefInternal env $ action arg
  
  runCrossRefInternal :: CrossRefEnv -> CrossRefM b -> b
  runCrossRefInternal CrossRefEnv { creOptions, creReferences, creSettings } (CrossRefM action) =
    fst $ runWS (WState creOptions creReferences) (runReaderT action creSettings)
  