    {-# LANGUAGE LambdaCase           #-}
    {-# LANGUAGE OverloadedStrings    #-}
    {-# LANGUAGE TupleSections        #-}
    {- |
    Module      : Text.Pandoc.Lua.Marshaling.Sources
    Copyright   : © 2021-2026 Albert Krewinkel <albert+pandoc@tarleb.com>
    License     : GPL-2.0-or-later

    Marshal 'Sources'.
    -}
    module Text.Pandoc.Lua.Marshal.Sources
      ( peekSources
      , pushSources
      , typeSource
      ) where

    import Control.Monad ((<$!>))
    import Data.Text (Text)
    import HsLua as Lua
    import Text.Pandoc.Lua.Marshal.List (newListMetatable)
    import Text.Pandoc.Sources (Sources (..), toSources)
    import Text.Parsec (SourcePos, sourceName)

    -- | Pushes the 'Sources' as a list of lazy Lua objects.
    pushSources :: LuaError e => Pusher e Sources
    pushSources :: forall e. LuaError e => Pusher e Sources
    pushSources (Sources [(SourcePos, Text)]
    srcs) = do
      Pusher e (SourcePos, Text) -> [(SourcePos, Text)] -> LuaE e ()
    forall e a. LuaError e => Pusher e a -> [a] -> LuaE e ()
    pushList (DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 2)
    -> Pusher e (SourcePos, Text)
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> a -> LuaE e ()
    pushUD DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 2)
    forall e. LuaError e => DocumentedType e (SourcePos, Text)
    typeSource) [(SourcePos, Text)]
    srcs
      Name -> LuaE e () -> LuaE e ()
    forall e. Name -> LuaE e () -> LuaE e ()
    newListMetatable Name
    "Sources" (LuaE e () -> LuaE e ()) -> LuaE e () -> LuaE e ()
    forall a b. (a -> b) -> a -> b
    $ do
        Name -> LuaE e ()
    forall e. Name -> LuaE e ()
    pushName Name
    "__tostring"
        HaskellFunction e -> LuaE e ()
    forall e. LuaError e => HaskellFunction e -> LuaE e ()
    pushHaskellFunction (HaskellFunction e -> LuaE e ()) -> HaskellFunction e -> LuaE e ()
    forall a b. (a -> b) -> a -> b
    $ do
          sources <- Peek e [(SourcePos, Text)] -> LuaE e [(SourcePos, Text)]
    forall e a. LuaError e => Peek e a -> LuaE e a
    forcePeek (Peek e [(SourcePos, Text)] -> LuaE e [(SourcePos, Text)])
    -> Peek e [(SourcePos, Text)] -> LuaE e [(SourcePos, Text)]
    forall a b. (a -> b) -> a -> b
    $ Peeker e (SourcePos, Text) -> Peeker e [(SourcePos, Text)]
    forall a e. LuaError e => Peeker e a -> Peeker e [a]
    peekList (DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 2)
    -> Peeker e (SourcePos, Text)
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> Peeker e a
    peekUD DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 2)
    forall e. LuaError e => DocumentedType e (SourcePos, Text)
    typeSource) (CInt -> StackIndex
    nthBottom CInt
    1)
          pushText . mconcat $ map snd sources
          return 1
        StackIndex -> LuaE e ()
    forall e. LuaError e => StackIndex -> LuaE e ()
    rawset (CInt -> StackIndex
    nth CInt
    3)
      StackIndex -> LuaE e ()
    forall e. StackIndex -> LuaE e ()
    setmetatable (CInt -> StackIndex
    nth CInt
    2)

    -- | Retrieves sources from the stack.
    peekSources :: LuaError e => Peeker e Sources
    peekSources :: forall e. LuaError e => Peeker e Sources
    peekSources StackIndex
    idx = LuaE e Type -> Peek e Type
    forall e a. LuaE e a -> Peek e a
    liftLua (StackIndex -> LuaE e Type
    forall e. StackIndex -> LuaE e Type
    ltype StackIndex
    idx) Peek e Type -> (Type -> Peek e Sources) -> Peek e Sources
    forall a b. Peek e a -> (a -> Peek e b) -> Peek e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
      Type
    TypeTable  -> [Sources] -> Sources
    forall a. Monoid a => [a] -> a
    mconcat ([Sources] -> Sources) -> Peek e [Sources] -> Peek e Sources
    forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
    <$!> Peeker e Sources -> Peeker e [Sources]
    forall a e. LuaError e => Peeker e a -> Peeker e [a]
    peekList Peeker e Sources
    forall e. LuaError e => Peeker e Sources
    peekSourcesSingleton StackIndex
    idx
      Type
    _          -> Peeker e Sources
    forall e. LuaError e => Peeker e Sources
    peekSourcesSingleton StackIndex
    idx

    -- | Retrieves a Sources singleton, i.e., a list with exactly one item.
    peekSourcesSingleton :: LuaError e => Peeker e Sources
    peekSourcesSingleton :: forall e. LuaError e => Peeker e Sources
    peekSourcesSingleton = [Peeker e Sources] -> Peeker e Sources
    forall e a. LuaError e => [Peeker e a] -> Peeker e a
    choice
      [ (Text -> Sources) -> Peek e Text -> Peek e Sources
    forall a b. (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Text -> Sources
    forall a. ToSources a => a -> Sources
    toSources (Peek e Text -> Peek e Sources)
    -> (StackIndex -> Peek e Text) -> Peeker e Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackIndex -> Peek e Text
    forall e. Peeker e Text
    peekText
      , ((SourcePos, Text) -> Sources)
    -> Peek e (SourcePos, Text) -> Peek e Sources
    forall a b. (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([(SourcePos, Text)] -> Sources
    Sources ([(SourcePos, Text)] -> Sources)
    -> ((SourcePos, Text) -> [(SourcePos, Text)])
    -> (SourcePos, Text)
    -> Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((SourcePos, Text) -> [(SourcePos, Text)] -> [(SourcePos, Text)]
    forall a. a -> [a] -> [a]
    :[])) (Peek e (SourcePos, Text) -> Peek e Sources)
    -> (StackIndex -> Peek e (SourcePos, Text)) -> Peeker e Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 1)
    -> StackIndex -> Peek e (SourcePos, Text)
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> Peeker e a
    peekUD DocumentedTypeWithList e (SourcePos, Text) (ZonkAny 1)
    forall e. LuaError e => DocumentedType e (SourcePos, Text)
    typeSource
      , ((String, Text) -> Sources)
    -> Peek e (String, Text) -> Peek e Sources
    forall a b. (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([(String, Text)] -> Sources
    forall a. ToSources a => a -> Sources
    toSources ([(String, Text)] -> Sources)
    -> ((String, Text) -> [(String, Text)])
    -> (String, Text)
    -> Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((String, Text) -> [(String, Text)] -> [(String, Text)]
    forall a. a -> [a] -> [a]
    :[])) (Peek e (String, Text) -> Peek e Sources)
    -> (StackIndex -> Peek e (String, Text)) -> Peeker e Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Peeker e String
    -> (StackIndex -> Peek e Text)
    -> StackIndex
    -> Peek e (String, Text)
    forall e a b.
    LuaError e =>
    Peeker e a -> Peeker e b -> Peeker e (a, b)
    peekPair Peeker e String
    forall e. Peeker e String
    peekString StackIndex -> Peek e Text
    forall e. Peeker e Text
    peekText
      , ((String, Text) -> Sources)
    -> Peek e (String, Text) -> Peek e Sources
    forall a b. (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([(String, Text)] -> Sources
    forall a. ToSources a => a -> Sources
    toSources ([(String, Text)] -> Sources)
    -> ((String, Text) -> [(String, Text)])
    -> (String, Text)
    -> Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((String, Text) -> [(String, Text)] -> [(String, Text)]
    forall a. a -> [a] -> [a]
    :[])) (Peek e (String, Text) -> Peek e Sources)
    -> (StackIndex -> Peek e (String, Text)) -> Peeker e Sources
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
        (\StackIndex
    idx -> (,)
          (String -> Text -> (String, Text))
    -> Peek e String -> Peek e (Text -> (String, Text))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Peeker e String -> Name -> Peeker e String
    forall e a. LuaError e => Peeker e a -> Name -> Peeker e a
    peekFieldRaw Peeker e String
    forall e. Peeker e String
    peekString Name
    "name" StackIndex
    idx
          Peek e (Text -> (String, Text))
    -> Peek e Text -> Peek e (String, Text)
    forall a b. Peek e (a -> b) -> Peek e a -> Peek e b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> (StackIndex -> Peek e Text) -> Name -> StackIndex -> Peek e Text
    forall e a. LuaError e => Peeker e a -> Name -> Peeker e a
    peekFieldRaw StackIndex -> Peek e Text
    forall e. Peeker e Text
    peekText Name
    "text" StackIndex
    idx)
      ]

    -- | A @Sources@ item.
    type Source = (SourcePos, Text)

    -- | Source object type.
    typeSource :: LuaError e => DocumentedType e Source
    typeSource :: forall e. LuaError e => DocumentedType e (SourcePos, Text)
    typeSource = Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) (SourcePos, Text)]
    -> DocumentedType e (SourcePos, Text)
    forall e a.
    LuaError e =>
    Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) a]
    -> DocumentedType e a
    deftype Name
    "Source"
      [ Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation Operation
    Tostring (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ ((SourcePos, Text) -> LuaE e Text)
    -> HsFnPrecursor e ((SourcePos, Text) -> LuaE e Text)
    forall a e. a -> HsFnPrecursor e a
    lambda
        ### liftPure snd
        HsFnPrecursor e ((SourcePos, Text) -> LuaE e Text)
    -> Parameter e (SourcePos, Text) -> HsFnPrecursor e (LuaE e Text)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> DocumentedType e (SourcePos, Text)
    -> Text -> Text -> Parameter e (SourcePos, Text)
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype
    -> Text -> Text -> Parameter e a
    udparam DocumentedType e (SourcePos, Text)
    forall e. LuaError e => DocumentedType e (SourcePos, Text)
    typeSource Text
    "srcs" Text
    "Source to print in native format"
        HsFnPrecursor e (LuaE e Text)
    -> FunctionResults e Text -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Text -> TypeSpec -> Text -> FunctionResults e Text
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Text
    forall e. Pusher e Text
    pushText TypeSpec
    "string" Text
    "source contents"
      ]
      [ Name
    -> Text
    -> (Pusher e String, (SourcePos, Text) -> String)
    -> Member e (DocumentedFunction e) (SourcePos, Text)
    forall e b a fn.
    Name -> Text -> (Pusher e b, a -> b) -> Member e fn a
    readonly Name
    "name" Text
    "source name"
          (Pusher e String
    forall e. String -> LuaE e ()
    pushString, SourcePos -> String
    sourceName (SourcePos -> String)
    -> ((SourcePos, Text) -> SourcePos) -> (SourcePos, Text) -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (SourcePos, Text) -> SourcePos
    forall a b. (a, b) -> a
    fst)
      , Name
    -> Text
    -> (Pusher e Text, (SourcePos, Text) -> Text)
    -> Member e (DocumentedFunction e) (SourcePos, Text)
    forall e b a fn.
    Name -> Text -> (Pusher e b, a -> b) -> Member e fn a
    readonly Name
    "text" Text
    "source text"
          (Pusher e Text
    forall e. Pusher e Text
    pushText, (SourcePos, Text) -> Text
    forall a b. (a, b) -> b
    snd)
      ]