module Okapi.HTTP.RFC9651.Item (
    Item,
    parser,
    printer,
    bareItem,
    bareItemEq,
    item,
    params,
    raw,
) where

import Data.ByteString (ByteString)
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)
import Okapi.HTTP.RFC9651.Lexer (ParseError (..), firstAndRest, strip)
import Okapi.HTTP.RFC9651.Parameters (Parameters)
import Okapi.HTTP.RFC9651.Parameters qualified as Parameters

type Item :: Type -> Type
data Item a where
    Bare   :: Leaf BareItem a -> Item a
    BareEq :: ByteString -> Item ()
    Params :: Tree Parameters p p -> Item p
    Raw    :: Item ByteString

type instance Context Item = ByteString
type instance Failure Item = ParseError

bareItem :: Leaf BareItem a -> Tree Item a a
bareItem :: forall a. Leaf BareItem a -> Tree Item a a
bareItem = Item a -> Tree Item a a
forall (t :: * -> *) i. t i -> Tree t i i
Node (Item a -> Tree Item a a)
-> (Leaf BareItem a -> Item a) -> Leaf BareItem a -> Tree Item a a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Leaf BareItem a -> Item a
forall a. Leaf BareItem a -> Item a
Bare

bareItemEq :: ByteString -> Tree Item () ()
bareItemEq :: ByteString -> Tree Item () ()
bareItemEq = Item () -> Tree Item () ()
forall (t :: * -> *) i. t i -> Tree t i i
Node (Item () -> Tree Item () ())
-> (ByteString -> Item ()) -> ByteString -> Tree Item () ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Item ()
BareEq

item :: Leaf BareItem a -> Tree Parameters p p -> Tree Item (a, p) (a, p)
item :: forall a p.
Leaf BareItem a -> Tree Parameters p p -> Tree Item (a, p) (a, p)
item Leaf BareItem a
vLeaf Tree Parameters p p
c = (,) (a -> p -> (a, p))
-> Tree Item (a, p) a -> Tree Item (a, p) (p -> (a, p))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((a, p) -> a
forall a b. (a, b) -> a
fst ((a, p) -> a) -> Tree Item a a -> Tree Item (a, p) a
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
=. Item a -> Tree Item a a
forall (t :: * -> *) i. t i -> Tree t i i
Node (Leaf BareItem a -> Item a
forall a. Leaf BareItem a -> Item a
Bare Leaf BareItem a
vLeaf)) Tree Item (a, p) (p -> (a, p))
-> Tree Item (a, p) p -> Tree Item (a, p) (a, p)
forall a b.
Tree Item (a, p) (a -> b)
-> Tree Item (a, p) a -> Tree Item (a, p) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((a, p) -> p
forall a b. (a, b) -> b
snd ((a, p) -> p) -> Tree Item p p -> Tree Item (a, p) p
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
=. Item p -> Tree Item p p
forall (t :: * -> *) i. t i -> Tree t i i
Node (Tree Parameters p p -> Item p
forall p. Tree Parameters p p -> Item p
Params Tree Parameters p p
c))

params :: Tree Parameters p p -> Tree Item p p
params :: forall p. Tree Parameters p p -> Tree Item p p
params = Item p -> Tree Item p p
forall (t :: * -> *) i. t i -> Tree t i i
Node (Item p -> Tree Item p p)
-> (Tree Parameters p p -> Item p)
-> Tree Parameters p p
-> Tree Item p p
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tree Parameters p p -> Item p
forall p. Tree Parameters p p -> Item p
Params

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

parser :: Tree Item i o -> Parser Item o
parser :: forall i o. Tree Item i o -> Parser Item o
parser = (forall a. Item a -> Parser Item a)
-> Tree Item i o
-> Context Item
-> (Either (Failure Item) o, Context Item)
forall (t :: * -> *) i o.
(forall a. t a -> Parser t a) -> Tree t i o -> Parser t o
Tree.parser Item a -> Parser Item a
forall a. Item a -> Parser Item a
alg
  where
    alg :: Item a -> Parser Item a
    alg :: forall a. Item a -> Parser Item a
alg Item a
t Context Item
s = case Item a
t of
        Bare Leaf BareItem a
vLeaf -> (Leaf BareItem a
vLeaf.decode (ByteString -> ByteString
strip ByteString
bare), Context Item
s)
        BareEq ByteString
c   -> (if ByteString -> ByteString
strip ByteString
bare ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
c then a -> Either ParseError a
forall a b. b -> Either a b
Right () else ParseError -> Either ParseError a
forall a b. a -> Either a b
Left ParseError
ParseError, Context Item
s)
        Params Tree Parameters a a
c   -> ((Either ParseError a, ByteString) -> Either ParseError a
forall a b. (a, b) -> a
fst (Tree Parameters a a -> Parser Parameters a
forall i o. Tree Parameters i o -> Parser Parameters o
Parameters.parser Tree Parameters a a
c ByteString
Context Parameters
ps), Context Item
s)
        Item a
Raw        -> (a -> Either ParseError a
forall a b. b -> Either a b
Right a
Context Item
s, Context Item
s)
      where
        (ByteString
bare, ByteString
ps) = Word8 -> ByteString -> (ByteString, ByteString)
firstAndRest Word8
59 ByteString
Context Item
s

printer :: Tree Item i o -> Printer Item i
printer :: forall i o. Tree Item i o -> Printer Item i
printer = (forall a. Item a -> Printer Item a)
-> Tree Item i o -> i -> Context Item
forall (t :: * -> *) i o.
Monoid (Context t) =>
(forall a. t a -> Printer t a) -> Tree t i o -> Printer t i
Tree.printer Item a -> Printer Item a
forall a. Item a -> Printer Item a
alg
  where
    alg :: Item a -> Printer Item a
    alg :: forall a. Item a -> Printer Item a
alg (Bare Leaf BareItem a
vLeaf) a
v  = Leaf BareItem a
vLeaf.encode a
v
    alg (BareEq ByteString
c)   () = ByteString
Context Item
c
    alg (Params Tree Parameters a a
c)   a
p  = Tree Parameters a a -> Printer Parameters a
forall i o. Tree Parameters i o -> Printer Parameters i
Parameters.printer Tree Parameters a a
c a
p
    alg Item a
Raw          a
bs = a
Context Item
bs