module Okapi.HTTP.RFC9651.List (
    List,
    parser,
    printer,
    item,
    innerList,
    items,
    raw,
) where

import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.Kind (Type)
import Okapi.Tree (Failure, Leaf, Parser, Printer, Context)
import Okapi.Tree qualified as Tree
import Okapi.Tree (Tree (..))
import Okapi.Tree qualified as Tree
import Okapi.HTTP.RFC9651.BareItem (BareItem, parseInnerToList, renderInner)
import Okapi.HTTP.RFC9651.Item (Item)
import Okapi.HTTP.RFC9651.Item qualified as Item
import Okapi.HTTP.RFC9651.Lexer (ParseError (..), firstAndRest, splitTop, strip)

type List :: Type -> Type
data List a where
    ListItem  :: Tree Item a a -> List a
    InnerList :: Leaf BareItem a -> List [a]
    Items     :: Tree Item a a -> List [a]
    Raw       :: List ByteString

type instance Context List = ByteString
type instance Failure List = ParseError

item :: Tree Item a a -> Tree List a a
item :: forall a. Tree Item a a -> Tree List a a
item = List a -> Tree List a a
forall (t :: * -> *) i. t i -> Tree t i i
Node (List a -> Tree List a a)
-> (Tree Item a a -> List a) -> Tree Item a a -> Tree List a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree Item a a -> List a
forall a. Tree Item a a -> List a
ListItem

innerList :: Leaf BareItem a -> Tree List [a] [a]
innerList :: forall a. Leaf BareItem a -> Tree List [a] [a]
innerList = List [a] -> Tree List [a] [a]
forall (t :: * -> *) i. t i -> Tree t i i
Node (List [a] -> Tree List [a] [a])
-> (Leaf BareItem a -> List [a])
-> Leaf BareItem a
-> Tree List [a] [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Leaf BareItem a -> List [a]
forall a. Leaf BareItem a -> List [a]
InnerList

items :: Tree Item a a -> Tree List [a] [a]
items :: forall a. Tree Item a a -> Tree List [a] [a]
items = List [a] -> Tree List [a] [a]
forall (t :: * -> *) i. t i -> Tree t i i
Node (List [a] -> Tree List [a] [a])
-> (Tree Item a a -> List [a])
-> Tree Item a a
-> Tree List [a] [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree Item a a -> List [a]
forall a. Tree Item a a -> List [a]
Items

raw :: Tree List ByteString ByteString
raw :: Tree List ByteString ByteString
raw = List ByteString -> Tree List ByteString ByteString
forall (t :: * -> *) i. t i -> Tree t i i
Node List ByteString
Raw

parser :: Tree List i o -> Parser List o
parser :: forall i o. Tree List i o -> Parser List o
parser = (forall a. List a -> Parser List a)
-> Tree List i o
-> Context List
-> (Either (Failure List) o, Context List)
forall (t :: * -> *) i o.
(forall a. t a -> Parser t a) -> Tree t i o -> Parser t o
Tree.parser List a -> Parser List a
forall a. List a -> Parser List a
alg
  where
    alg :: List a -> Parser List a
    alg :: forall a. List a -> Parser List a
alg List a
t Context List
s = case List a
t of
        ListItem Tree Item a a
c      -> let (ByteString
m, ByteString
rest) = Word8 -> ByteString -> (ByteString, ByteString)
firstAndRest Word8
44 ByteString
Context List
s
                           in ((Either ParseError a, ByteString) -> Either ParseError a
forall a b. (a, b) -> a
fst (Tree Item a a -> Parser Item a
forall i o. Tree Item i o -> Parser Item o
Item.parser Tree Item a a
c (ByteString -> ByteString
strip ByteString
m)), ByteString
Context List
rest)
        InnerList Leaf BareItem a
vLeaf -> let (ByteString
m, ByteString
rest) = Word8 -> ByteString -> (ByteString, ByteString)
firstAndRest Word8
44 ByteString
Context List
s
                           in (Leaf BareItem a -> ByteString -> Either ParseError [a]
forall a. Leaf BareItem a -> ByteString -> Either ParseError [a]
parseInnerToList Leaf BareItem a
vLeaf (ByteString -> ByteString
strip ByteString
m), ByteString
Context List
rest)
        Items Tree Item a a
c         -> ((ByteString -> Either ParseError a)
-> [ByteString] -> Either ParseError [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (\ByteString
m -> (Either ParseError a, ByteString) -> Either ParseError a
forall a b. (a, b) -> a
fst (Tree Item a a -> Parser Item a
forall i o. Tree Item i o -> Parser Item o
Item.parser Tree Item a a
c ByteString
Context Item
m)) (ByteString -> [ByteString]
members ByteString
Context List
s), ByteString
Context List
BS.empty)
        List a
Raw             -> (a -> Either ParseError a
forall a b. b -> Either a b
Right a
Context List
s, ByteString
Context List
BS.empty)
      where
        members :: ByteString -> [ByteString]
members ByteString
bs = (ByteString -> Bool) -> [ByteString] -> [ByteString]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (ByteString -> Bool) -> ByteString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
BS.null) ((ByteString -> ByteString) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> ByteString
strip (Word8 -> ByteString -> [ByteString]
splitTop Word8
44 ByteString
bs))

printer :: Tree List i o -> Printer List i
printer :: forall i o. Tree List i o -> Printer List i
printer = (forall a. List a -> Printer List a)
-> Tree List i o -> i -> Context List
forall (t :: * -> *) i o.
Monoid (Context t) =>
(forall a. t a -> Printer t a) -> Tree t i o -> Printer t i
Tree.printer List a -> Printer List a
forall a. List a -> Printer List a
alg
  where
    alg :: List a -> Printer List a
    alg :: forall a. List a -> Printer List a
alg (ListItem Tree Item a a
c)      a
a  = ByteString
", " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Tree Item a a -> Printer Item a
forall i o. Tree Item i o -> Printer Item i
Item.printer Tree Item a a
c a
a
    alg (InnerList Leaf BareItem a
vLeaf) a
xs = ByteString
", " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Leaf BareItem a -> [a] -> ByteString
forall a. Leaf BareItem a -> [a] -> ByteString
renderInner Leaf BareItem a
vLeaf a
[a]
xs
    alg (Items Tree Item a a
c)         a
xs = [ByteString] -> ByteString
BS.concat [ByteString
", " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Tree Item a a -> Printer Item a
forall i o. Tree Item i o -> Printer Item i
Item.printer Tree Item a a
c a
x | a
x <- a
[a]
xs]
    alg List a
Raw               a
bs = a
Context List
bs