    {-# LANGUAGE FlexibleContexts     #-}
    {-# LANGUAGE OverloadedStrings    #-}
    {- |
    Copyright   : © 2021-2026 Albert Krewinkel
    License     : MIT
    Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>

    Shared functions used in multiple types.
    -}
    module Text.Pandoc.Lua.Marshal.Shared
      ( -- * Walking
        walkBlocksAndInlines
      ) where

    import Prelude hiding (lookup)
    import Control.Monad ((>=>))
    import HsLua
    import {-# SOURCE #-} Text.Pandoc.Lua.Marshal.Block
    import {-# SOURCE #-} Text.Pandoc.Lua.Marshal.Inline
    import Text.Pandoc.Lua.Marshal.Filter
    import Text.Pandoc.Definition
    import Text.Pandoc.Lua.Topdown
    import Text.Pandoc.Lua.Walk
    import Text.Pandoc.Walk

    -- | Walk blocks and inlines.
    walkBlocksAndInlines :: (LuaError e,
                             Walkable (SpliceList Block) a,
                             Walkable (SpliceList Inline) a,
                             Walkable [Block] a,
                             Walkable [Inline] a,
                             Walkable Topdown a)
                         => Filter
                         -> a -> LuaE e a
    walkBlocksAndInlines :: forall e a.
    (LuaError e, Walkable (SpliceList Block) a,
     Walkable (SpliceList Inline) a, Walkable [Block] a,
     Walkable [Inline] a, Walkable Topdown a) =>
    Filter -> a -> LuaE e a
    walkBlocksAndInlines Filter
    filter' =
      case Filter -> WalkingOrder
    filterWalkingOrder Filter
    filter' of
        WalkingOrder
    WalkTopdown     -> (Topdown -> LuaE e Topdown) -> a -> LuaE e a
    forall a b (m :: * -> *).
    (Walkable a b, Monad m, Applicative m, Functor m) =>
    (a -> m a) -> b -> m b
    forall (m :: * -> *).
    (Monad m, Applicative m, Functor m) =>
    (Topdown -> m Topdown) -> a -> m a
    walkM (Filter -> Topdown -> LuaE e Topdown
    forall e. LuaError e => Filter -> Topdown -> LuaE e Topdown
    applyFilterTopdown Filter
    filter')
        WalkingOrder
    WalkForEachType -> Filter -> a -> LuaE e a
    forall e a.
    (LuaError e, Walkable (SpliceList Inline) a) =>
    Filter -> a -> LuaE e a
    walkInlineSplicing Filter
    filter'
                       (a -> LuaE e a) -> (a -> LuaE e a) -> a -> LuaE e a
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Filter -> a -> LuaE e a
    forall e a.
    (LuaError e, Walkable [Inline] a) =>
    Filter -> a -> LuaE e a
    walkInlinesStraight Filter
    filter'
                       (a -> LuaE e a) -> (a -> LuaE e a) -> a -> LuaE e a
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Filter -> a -> LuaE e a
    forall e a.
    (LuaError e, Walkable (SpliceList Block) a) =>
    Filter -> a -> LuaE e a
    walkBlockSplicing Filter
    filter'
                       (a -> LuaE e a) -> (a -> LuaE e a) -> a -> LuaE e a
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Filter -> a -> LuaE e a
    forall e a.
    (LuaError e, Walkable [Block] a) =>
    Filter -> a -> LuaE e a
    walkBlocksStraight Filter
    filter'

    -- | Applies a filter by processing the root node(s) first and descending
    -- towards the leaves depth-first.
    applyFilterTopdown :: LuaError e
                       => Filter
                       -> Topdown -> LuaE e Topdown
    applyFilterTopdown :: forall e. LuaError e => Filter -> Topdown -> LuaE e Topdown
    applyFilterTopdown Filter
    filter' topdown :: Topdown
    topdown@(Topdown TraversalControl
    _ TraversalNode
    node) =
      case TraversalNode
    node of
        TBlock Block
    x ->
          case Filter
    filter' Filter -> Block -> Maybe FilterFunction
    forall a. Data a => Filter -> a -> Maybe FilterFunction
    `getFunctionFor` Block
    x of
            Maybe FilterFunction
    Nothing ->
              Topdown -> LuaE e Topdown
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Topdown
    topdown
            Just FilterFunction
    fn -> do
              (blocks, ctrl) <-
                FilterFunction
    -> Pusher e Block
    -> Peeker e [Block]
    -> Block
    -> LuaE e ([Block], TraversalControl)
    forall e a.
    LuaError e =>
    FilterFunction
    -> Pusher e a
    -> Peeker e [a]
    -> a
    -> LuaE e ([a], TraversalControl)
    applySplicingFunction FilterFunction
    fn Pusher e Block
    forall e. LuaError e => Pusher e Block
    pushBlock Peeker e [Block]
    forall e. LuaError e => Peeker e [Block]
    peekBlocksFuzzy Block
    x
              pure $ Topdown ctrl $ TBlocks blocks

        TBlocks [Block]
    xs ->
          case Name
    "Blocks" Name -> Filter -> Maybe FilterFunction
    `lookup` Filter
    filter' of
            Maybe FilterFunction
    Nothing ->
              Topdown -> LuaE e Topdown
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Topdown
    topdown
            Just FilterFunction
    fn -> do
              (blocks, ctrl) <-
                FilterFunction
    -> Pusher e [Block]
    -> Peeker e [Block]
    -> [Block]
    -> LuaE e ([Block], TraversalControl)
    forall e a.
    LuaError e =>
    FilterFunction
    -> Pusher e a -> Peeker e a -> a -> LuaE e (a, TraversalControl)
    applyStraightFunction FilterFunction
    fn Pusher e [Block]
    forall e. LuaError e => Pusher e [Block]
    pushBlocks Peeker e [Block]
    forall e. LuaError e => Peeker e [Block]
    peekBlocksFuzzy [Block]
    xs
              pure $ Topdown ctrl $ TBlocks blocks

        TInline Inline
    x ->
          case Filter
    filter' Filter -> Inline -> Maybe FilterFunction
    forall a. Data a => Filter -> a -> Maybe FilterFunction
    `getFunctionFor` Inline
    x of
            Maybe FilterFunction
    Nothing ->
              Topdown -> LuaE e Topdown
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Topdown
    topdown
            Just FilterFunction
    fn -> do
              (inlines, ctrl) <-
                FilterFunction
    -> Pusher e Inline
    -> Peeker e [Inline]
    -> Inline
    -> LuaE e ([Inline], TraversalControl)
    forall e a.
    LuaError e =>
    FilterFunction
    -> Pusher e a
    -> Peeker e [a]
    -> a
    -> LuaE e ([a], TraversalControl)
    applySplicingFunction FilterFunction
    fn Pusher e Inline
    forall e. LuaError e => Pusher e Inline
    pushInline Peeker e [Inline]
    forall e. LuaError e => Peeker e [Inline]
    peekInlinesFuzzy Inline
    x
              pure $ Topdown ctrl $ TInlines inlines

        TInlines [Inline]
    xs ->
          case Name
    "Inlines" Name -> Filter -> Maybe FilterFunction
    `lookup` Filter
    filter' of
            Maybe FilterFunction
    Nothing ->
              Topdown -> LuaE e Topdown
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Topdown
    topdown
            Just FilterFunction
    fn -> do
              (inlines, ctrl) <-
                FilterFunction
    -> Pusher e [Inline]
    -> Peeker e [Inline]
    -> [Inline]
    -> LuaE e ([Inline], TraversalControl)
    forall e a.
    LuaError e =>
    FilterFunction
    -> Pusher e a -> Peeker e a -> a -> LuaE e (a, TraversalControl)
    applyStraightFunction FilterFunction
    fn Pusher e [Inline]
    forall e. LuaError e => Pusher e [Inline]
    pushInlines Peeker e [Inline]
    forall e. LuaError e => Peeker e [Inline]
    peekInlinesFuzzy [Inline]
    xs
              pure $ Topdown ctrl $ TInlines inlines