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

    Marshaling/unmarshaling functions of 'Row' values.
    -}
    module Text.Pandoc.Lua.Marshal.Row
      ( peekRow
      , peekRowFuzzy
      , pushRow
      , typeRow
      , mkRow
      ) where

    import Control.Applicative (optional)
    import Control.Monad ((<$!>))
    import Data.Aeson (encode)
    import Data.Maybe (fromMaybe)
    import HsLua
    import Text.Pandoc.Lua.Marshal.Attr (peekAttr, pushAttr)
    import Text.Pandoc.Lua.Marshal.Cell (peekCellFuzzy, pushCell)
    import Text.Pandoc.Lua.Marshal.Filter (peekFilter)
    import Text.Pandoc.Lua.Marshal.List (pushPandocList)
    import Text.Pandoc.Lua.Marshal.Shared (walkBlocksAndInlines)
    import Text.Pandoc.Definition

    -- | Push a table Row as a table with fields @attr@, @alignment@,
    -- @row_span@, @col_span@, and @contents@.
    pushRow :: LuaError e => Row -> LuaE e ()
    pushRow :: forall e. LuaError e => Row -> LuaE e ()
    pushRow = DocumentedTypeWithList e Row Void -> Row -> LuaE e ()
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> a -> LuaE e ()
    pushUD DocumentedTypeWithList e Row Void
    forall e. LuaError e => DocumentedType e Row
    typeRow

    -- | Retrieves a 'Cell' object from the stack.
    peekRow :: LuaError e => Peeker e Row
    peekRow :: forall e. LuaError e => Peeker e Row
    peekRow = DocumentedTypeWithList e Row Void -> Peeker e Row
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> Peeker e a
    peekUD DocumentedTypeWithList e Row Void
    forall e. LuaError e => DocumentedType e Row
    typeRow

    -- | Retrieves a 'Cell' from the stack, accepting either a 'pandoc Cell'
    -- userdata object or a table with fields @attr@, @alignment@, @row_span@,
    -- @col_span@, and @contents@.
    peekRowFuzzy :: LuaError e => Peeker e Row
    peekRowFuzzy :: forall e. LuaError e => Peeker e Row
    peekRowFuzzy 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 Row) -> Peek e Row
    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
    TypeUserdata -> Peeker e Row
    forall e. LuaError e => Peeker e Row
    peekRow StackIndex
    idx
      Type
    TypeTable -> (Attr -> [Cell] -> Row) -> (Attr, [Cell]) -> Row
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Attr -> [Cell] -> Row
    Row ((Attr, [Cell]) -> Row) -> Peek e (Attr, [Cell]) -> Peek e Row
    forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
    <$!> Peeker e Attr -> Peeker e [Cell] -> Peeker e (Attr, [Cell])
    forall e a b.
    LuaError e =>
    Peeker e a -> Peeker e b -> Peeker e (a, b)
    peekPair Peeker e Attr
    forall e. LuaError e => Peeker e Attr
    peekAttr (Peeker e Cell -> Peeker e [Cell]
    forall a e. LuaError e => Peeker e a -> Peeker e [a]
    peekList Peeker e Cell
    forall e. LuaError e => Peeker e Cell
    peekCellFuzzy) StackIndex
    idx
      Type
    _ -> ByteString -> Peek e Row
    forall a e. ByteString -> Peek e a
    failPeek (ByteString -> Peek e Row) -> Peek e ByteString -> Peek e Row
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Name -> StackIndex -> Peek e ByteString
    forall e. Name -> StackIndex -> Peek e ByteString
    typeMismatchMessage Name
    "Cell or table" StackIndex
    idx

    -- | Row object type.
    typeRow :: LuaError e => DocumentedType e Row
    typeRow :: forall e. LuaError e => DocumentedType e Row
    typeRow = Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) Row]
    -> DocumentedType e Row
    forall e a.
    LuaError e =>
    Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) a]
    -> DocumentedType e a
    deftype Name
    "Row"
      [ Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation Operation
    Eq (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Maybe Row -> Maybe Row -> LuaE e Bool)
    -> HsFnPrecursor e (Maybe Row -> Maybe Row -> LuaE e Bool)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "__eq"
         ### liftPure2 (\a b -> fromMaybe False ((==) <$> a <*> b))
         HsFnPrecursor e (Maybe Row -> Maybe Row -> LuaE e Bool)
    -> Parameter e (Maybe Row)
    -> HsFnPrecursor e (Maybe Row -> LuaE e Bool)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e (Maybe Row)
    -> TypeSpec -> Text -> Text -> Parameter e (Maybe Row)
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter (Peek e Row -> Peek e (Maybe Row)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (Peek e Row -> Peek e (Maybe Row))
    -> (StackIndex -> Peek e Row) -> Peeker e (Maybe Row)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackIndex -> Peek e Row
    forall e. LuaError e => Peeker e Row
    peekRow) TypeSpec
    "Row" Text
    "self" Text
    ""
         HsFnPrecursor e (Maybe Row -> LuaE e Bool)
    -> Parameter e (Maybe Row) -> HsFnPrecursor e (LuaE e Bool)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e (Maybe Row)
    -> TypeSpec -> Text -> Text -> Parameter e (Maybe Row)
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter (Peek e Row -> Peek e (Maybe Row)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (Peek e Row -> Peek e (Maybe Row))
    -> (StackIndex -> Peek e Row) -> Peeker e (Maybe Row)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackIndex -> Peek e Row
    forall e. LuaError e => Peeker e Row
    peekRow) TypeSpec
    "any" Text
    "object" Text
    ""
         HsFnPrecursor e (LuaE e Bool)
    -> FunctionResults e Bool -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Bool -> TypeSpec -> Text -> FunctionResults e Bool
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Bool
    forall e. Pusher e Bool
    pushBool TypeSpec
    "boolean" Text
    "true iff the two values are equal"
      , 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
    $ (Row -> LuaE e String) -> HsFnPrecursor e (Row -> LuaE e String)
    forall a e. a -> HsFnPrecursor e a
    lambda
        ### liftPure show
        HsFnPrecursor e (Row -> LuaE e String)
    -> Parameter e Row -> HsFnPrecursor e (LuaE e String)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> (StackIndex -> Peek e Row)
    -> TypeSpec -> Text -> Text -> Parameter e Row
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter StackIndex -> Peek e Row
    forall e. LuaError e => Peeker e Row
    peekRow TypeSpec
    "Row" Text
    "self" Text
    ""
        HsFnPrecursor e (LuaE e String)
    -> FunctionResults e String -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e String -> TypeSpec -> Text -> FunctionResults e String
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e String
    forall e. String -> LuaE e ()
    pushString TypeSpec
    "string" Text
    "native Haskell representation"
      , Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation (Name -> Operation
    CustomOperation Name
    "__tojson") (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ (Row -> LuaE e ByteString)
    -> HsFnPrecursor e (Row -> LuaE e ByteString)
    forall a e. a -> HsFnPrecursor e a
    lambda
        ### liftPure encode
        HsFnPrecursor e (Row -> LuaE e ByteString)
    -> Parameter e Row -> HsFnPrecursor e (LuaE e ByteString)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> DocumentedType e Row -> Text -> Text -> Parameter e Row
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype
    -> Text -> Text -> Parameter e a
    udparam DocumentedType e Row
    forall e. LuaError e => DocumentedType e Row
    typeRow Text
    "self" Text
    ""
        HsFnPrecursor e (LuaE e ByteString)
    -> FunctionResults e ByteString -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e ByteString
    -> TypeSpec -> Text -> FunctionResults e ByteString
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e ByteString
    forall e. Pusher e ByteString
    pushLazyByteString TypeSpec
    "string" Text
    "JSON representation"
      ]
      [ Name
    -> Text
    -> (Pusher e Attr, Row -> Attr)
    -> (Peeker e Attr, Row -> Attr -> Row)
    -> Member e (DocumentedFunction e) Row
    forall e b a fn.
    LuaError e =>
    Name
    -> Text
    -> (Pusher e b, a -> b)
    -> (Peeker e b, a -> b -> a)
    -> Member e fn a
    property Name
    "attr" Text
    "row attributes"
          (Pusher e Attr
    forall e. LuaError e => Pusher e Attr
    pushAttr, \(Row Attr
    attr [Cell]
    _) -> Attr
    attr)
          (Peeker e Attr
    forall e. LuaError e => Peeker e Attr
    peekAttr, \(Row Attr
    _ [Cell]
    cells) Attr
    attr ->
                       Attr -> [Cell] -> Row
    Row Attr
    attr [Cell]
    cells)
      , Name
    -> Text
    -> (Pusher e [Cell], Row -> [Cell])
    -> (Peeker e [Cell], Row -> [Cell] -> Row)
    -> Member e (DocumentedFunction e) Row
    forall e b a fn.
    LuaError e =>
    Name
    -> Text
    -> (Pusher e b, a -> b)
    -> (Peeker e b, a -> b -> a)
    -> Member e fn a
    property Name
    "cells" Text
    "row cells"
          (Pusher e Cell -> Pusher e [Cell]
    forall e a. LuaError e => Pusher e a -> Pusher e [a]
    pushPandocList Pusher e Cell
    forall e. LuaError e => Cell -> LuaE e ()
    pushCell, \(Row Attr
    _ [Cell]
    cells) -> [Cell]
    cells)
          (Peeker e Cell -> Peeker e [Cell]
    forall a e. LuaError e => Peeker e a -> Peeker e [a]
    peekList Peeker e Cell
    forall e. LuaError e => Peeker e Cell
    peekCellFuzzy, \(Row Attr
    attr [Cell]
    _) [Cell]
    cells ->
                                     Attr -> [Cell] -> Row
    Row Attr
    attr [Cell]
    cells)

      , AliasIndex
    -> Text -> [AliasIndex] -> Member e (DocumentedFunction e) Row
    forall e fn a. AliasIndex -> Text -> [AliasIndex] -> Member e fn a
    alias AliasIndex
    "identifier" Text
    "cell ID"         [AliasIndex
    "attr", AliasIndex
    "identifier"]
      , AliasIndex
    -> Text -> [AliasIndex] -> Member e (DocumentedFunction e) Row
    forall e fn a. AliasIndex -> Text -> [AliasIndex] -> Member e fn a
    alias AliasIndex
    "classes"    Text
    "cell classes"    [AliasIndex
    "attr", AliasIndex
    "classes"]
      , AliasIndex
    -> Text -> [AliasIndex] -> Member e (DocumentedFunction e) Row
    forall e fn a. AliasIndex -> Text -> [AliasIndex] -> Member e fn a
    alias AliasIndex
    "attributes" Text
    "cell attributes" [AliasIndex
    "attr", AliasIndex
    "attributes"]

      , DocumentedFunction e -> Member e (DocumentedFunction e) Row
    forall e a.
    DocumentedFunction e -> Member e (DocumentedFunction e) a
    method (DocumentedFunction e -> Member e (DocumentedFunction e) Row)
    -> DocumentedFunction e -> Member e (DocumentedFunction e) Row
    forall a b. (a -> b) -> a -> b
    $ Name -> (Row -> LuaE e Row) -> HsFnPrecursor e (Row -> LuaE e Row)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "clone"
        ### return
        HsFnPrecursor e (Row -> LuaE e Row)
    -> Parameter e Row -> HsFnPrecursor e (LuaE e Row)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> (StackIndex -> Peek e Row)
    -> TypeSpec -> Text -> Text -> Parameter e Row
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter StackIndex -> Peek e Row
    forall e. LuaError e => Peeker e Row
    peekRow TypeSpec
    "Row" Text
    "self" Text
    ""
        HsFnPrecursor e (LuaE e Row)
    -> FunctionResults e Row -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Row -> TypeSpec -> Text -> FunctionResults e Row
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Row
    forall e. LuaError e => Row -> LuaE e ()
    pushRow TypeSpec
    "Row" Text
    "cloned object"

      , DocumentedFunction e -> Member e (DocumentedFunction e) Row
    forall e a.
    DocumentedFunction e -> Member e (DocumentedFunction e) a
    method (DocumentedFunction e -> Member e (DocumentedFunction e) Row)
    -> DocumentedFunction e -> Member e (DocumentedFunction e) Row
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Row -> Filter -> LuaE e Row)
    -> HsFnPrecursor e (Row -> Filter -> LuaE e Row)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "walk"
        ### flip walkBlocksAndInlines
        HsFnPrecursor e (Row -> Filter -> LuaE e Row)
    -> Parameter e Row -> HsFnPrecursor e (Filter -> LuaE e Row)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> (StackIndex -> Peek e Row)
    -> TypeSpec -> Text -> Text -> Parameter e Row
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter StackIndex -> Peek e Row
    forall e. LuaError e => Peeker e Row
    peekRow TypeSpec
    "Row" Text
    "self" Text
    ""
        HsFnPrecursor e (Filter -> LuaE e Row)
    -> Parameter e Filter -> HsFnPrecursor e (LuaE e Row)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Filter -> TypeSpec -> Text -> Text -> Parameter e Filter
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Filter
    forall e. LuaError e => Peeker e Filter
    peekFilter TypeSpec
    "Filter" Text
    "lua_filter" Text
    "table of filter functions"
        HsFnPrecursor e (LuaE e Row)
    -> FunctionResults e Row -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Row -> TypeSpec -> Text -> FunctionResults e Row
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Row
    forall e. LuaError e => Row -> LuaE e ()
    pushRow TypeSpec
    "Row" Text
    "modified cell"
      ]

    -- | Constructor function for 'Row' values.
    mkRow :: LuaError e => DocumentedFunction e
    mkRow :: forall e. LuaError e => DocumentedFunction e
    mkRow = Name
    -> (Maybe [Cell] -> Maybe Attr -> LuaE e Row)
    -> HsFnPrecursor e (Maybe [Cell] -> Maybe Attr -> LuaE e Row)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "Row"
      ### liftPure2 (\mCells mAttr -> Row
                      (fromMaybe nullAttr mAttr)
                      (fromMaybe [] mCells))
      HsFnPrecursor e (Maybe [Cell] -> Maybe Attr -> LuaE e Row)
    -> Parameter e (Maybe [Cell])
    -> HsFnPrecursor e (Maybe Attr -> LuaE e Row)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Parameter e [Cell] -> Parameter e (Maybe [Cell])
    forall e a. Parameter e a -> Parameter e (Maybe a)
    opt (Peeker e [Cell] -> TypeSpec -> Text -> Text -> Parameter e [Cell]
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter (Peeker e Cell -> Peeker e [Cell]
    forall a e. LuaError e => Peeker e a -> Peeker e [a]
    peekList Peeker e Cell
    forall e. LuaError e => Peeker e Cell
    peekCellFuzzy) TypeSpec
    "{Cell,...}" Text
    "cells"
               Text
    "list of table cells in this row")
      HsFnPrecursor e (Maybe Attr -> LuaE e Row)
    -> Parameter e (Maybe Attr) -> HsFnPrecursor e (LuaE e Row)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Parameter e Attr -> Parameter e (Maybe Attr)
    forall e a. Parameter e a -> Parameter e (Maybe a)
    opt (Peeker e Attr -> TypeSpec -> Text -> Text -> Parameter e Attr
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Attr
    forall e. LuaError e => Peeker e Attr
    peekAttr TypeSpec
    "Attr" Text
    "attr" Text
    "row attributes")
      HsFnPrecursor e (LuaE e Row)
    -> FunctionResults e Row -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Row -> TypeSpec -> Text -> FunctionResults e Row
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Row
    forall e. LuaError e => Row -> LuaE e ()
    pushRow TypeSpec
    "Row" Text
    "new Row object"
      #? "Creates a table row."