module Okapi.HTTP.RFC9651.Dictionary (
    Dictionary,
    parser,
    printer,
    member,
    member',
    list,
    list',
    raw,
) where

import Data.ByteString (ByteString)
import Data.Kind (Type)
import Data.List (find)
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 (Key, ParseError (..), memberEntries)

type Dictionary :: Type -> Type
data Dictionary a where
    Member  :: Key -> Tree Item a a  -> Dictionary a
    Member' :: Key -> Tree Item a a  -> Dictionary (Maybe a)
    List    :: Key -> Leaf BareItem a -> Dictionary [a]
    List'   :: Key -> Leaf BareItem a -> Dictionary (Maybe [a])
    Raw     :: Dictionary ByteString

type instance Context Dictionary = ByteString
type instance Failure Dictionary = ParseError

member :: Key -> Tree Item a a -> Tree Dictionary a a
member :: forall a. Key -> Tree Item a a -> Tree Dictionary a a
member Key
k Tree Item a a
c = Dictionary a -> Tree Dictionary a a
forall (t :: * -> *) i. t i -> Tree t i i
Node (Key -> Tree Item a a -> Dictionary a
forall a. Key -> Tree Item a a -> Dictionary a
Member Key
k Tree Item a a
c)

member' :: Key -> Tree Item a a -> Tree Dictionary (Maybe a) (Maybe a)
member' :: forall a.
Key -> Tree Item a a -> Tree Dictionary (Maybe a) (Maybe a)
member' Key
k Tree Item a a
c = Dictionary (Maybe a) -> Tree Dictionary (Maybe a) (Maybe a)
forall (t :: * -> *) i. t i -> Tree t i i
Node (Key -> Tree Item a a -> Dictionary (Maybe a)
forall a. Key -> Tree Item a a -> Dictionary (Maybe a)
Member' Key
k Tree Item a a
c)

list :: Key -> Leaf BareItem a -> Tree Dictionary [a] [a]
list :: forall a. Key -> Leaf BareItem a -> Tree Dictionary [a] [a]
list Key
k Leaf BareItem a
vLeaf = Dictionary [a] -> Tree Dictionary [a] [a]
forall (t :: * -> *) i. t i -> Tree t i i
Node (Key -> Leaf BareItem a -> Dictionary [a]
forall a. Key -> Leaf BareItem a -> Dictionary [a]
List Key
k Leaf BareItem a
vLeaf)

list' :: Key -> Leaf BareItem a -> Tree Dictionary (Maybe [a]) (Maybe [a])
list' :: forall a.
Key -> Leaf BareItem a -> Tree Dictionary (Maybe [a]) (Maybe [a])
list' Key
k Leaf BareItem a
vLeaf = Dictionary (Maybe [a]) -> Tree Dictionary (Maybe [a]) (Maybe [a])
forall (t :: * -> *) i. t i -> Tree t i i
Node (Key -> Leaf BareItem a -> Dictionary (Maybe [a])
forall a. Key -> Leaf BareItem a -> Dictionary (Maybe [a])
List' Key
k Leaf BareItem a
vLeaf)

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

parser :: Tree Dictionary i o -> Parser Dictionary o
parser :: forall i o. Tree Dictionary i o -> Parser Dictionary o
parser = (forall a. Dictionary a -> Parser Dictionary a)
-> Tree Dictionary i o
-> Context Dictionary
-> (Either (Failure Dictionary) o, Context Dictionary)
forall (t :: * -> *) i o.
(forall a. t a -> Parser t a) -> Tree t i o -> Parser t o
Tree.parser Dictionary a -> Parser Dictionary a
forall a. Dictionary a -> Parser Dictionary a
alg
  where
    alg :: Dictionary a -> Parser Dictionary a
    alg :: forall a. Dictionary a -> Parser Dictionary a
alg Dictionary a
t Context Dictionary
s = case Dictionary a
t of
        Member Key
key Tree Item a a
c -> case Key -> Key -> Maybe (Maybe Key)
look Key
Context Dictionary
s Key
key of
            Just (Just Key
v) -> ((Either ParseError a, Key) -> 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 Key
Context Item
v), Context Dictionary
s)
            Just Maybe Key
Nothing  -> ((Either ParseError a, Key) -> 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 Key
Context Item
"?1"), Context Dictionary
s)
            Maybe (Maybe Key)
Nothing       -> (ParseError -> Either ParseError a
forall a b. a -> Either a b
Left ParseError
ParseError, Context Dictionary
s)
        Member' Key
key Tree Item a a
c -> case Key -> Key -> Maybe (Maybe Key)
look Key
Context Dictionary
s Key
key of
            Just (Just Key
v) -> ((a -> a) -> Either ParseError a -> Either ParseError a
forall a b. (a -> b) -> Either ParseError a -> Either ParseError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
a -> Maybe a
forall a. a -> Maybe a
Just ((Either ParseError a, Key) -> 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 Key
Context Item
v)), Context Dictionary
s)
            Maybe (Maybe Key)
_             -> (a -> Either ParseError a
forall a b. b -> Either a b
Right a
Maybe a
forall a. Maybe a
Nothing, Context Dictionary
s)
        List Key
key Leaf BareItem a
vLeaf -> case Key -> Key -> Maybe (Maybe Key)
look Key
Context Dictionary
s Key
key of
            Just (Just Key
v) -> (Leaf BareItem a -> Key -> Either ParseError [a]
forall a. Leaf BareItem a -> Key -> Either ParseError [a]
parseInnerToList Leaf BareItem a
vLeaf Key
v, Context Dictionary
s)
            Maybe (Maybe Key)
_             -> (ParseError -> Either ParseError a
forall a b. a -> Either a b
Left ParseError
ParseError, Context Dictionary
s)
        List' Key
key Leaf BareItem a
vLeaf -> case Key -> Key -> Maybe (Maybe Key)
look Key
Context Dictionary
s Key
key of
            Just (Just Key
v) -> (([a] -> a) -> Either ParseError [a] -> Either ParseError a
forall a b. (a -> b) -> Either ParseError a -> Either ParseError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
[a] -> Maybe [a]
forall a. a -> Maybe a
Just (Leaf BareItem a -> Key -> Either ParseError [a]
forall a. Leaf BareItem a -> Key -> Either ParseError [a]
parseInnerToList Leaf BareItem a
vLeaf Key
v), Context Dictionary
s)
            Maybe (Maybe Key)
_             -> (a -> Either ParseError a
forall a b. b -> Either a b
Right a
Maybe [a]
forall a. Maybe a
Nothing, Context Dictionary
s)
        Dictionary a
Raw -> (a -> Either ParseError a
forall a b. b -> Either a b
Right a
Context Dictionary
s, Context Dictionary
s)
      where
        look :: Key -> Key -> Maybe (Maybe Key)
look Key
bs Key
k = ((Key, Maybe Key) -> Maybe Key)
-> Maybe (Key, Maybe Key) -> Maybe (Maybe Key)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Key, Maybe Key) -> Maybe Key
forall a b. (a, b) -> b
snd (((Key, Maybe Key) -> Bool)
-> [(Key, Maybe Key)] -> Maybe (Key, Maybe Key)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Key -> Key -> Bool
forall a. Eq a => a -> a -> Bool
== Key
k) (Key -> Bool)
-> ((Key, Maybe Key) -> Key) -> (Key, Maybe Key) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Key, Maybe Key) -> Key
forall a b. (a, b) -> a
fst) (Key -> [(Key, Maybe Key)]
memberEntries Key
bs))

printer :: Tree Dictionary i o -> Printer Dictionary i
printer :: forall i o. Tree Dictionary i o -> Printer Dictionary i
printer = (forall a. Dictionary a -> Printer Dictionary a)
-> Tree Dictionary i o -> i -> Context Dictionary
forall (t :: * -> *) i o.
Monoid (Context t) =>
(forall a. t a -> Printer t a) -> Tree t i o -> Printer t i
Tree.printer Dictionary a -> Printer Dictionary a
forall a. Dictionary a -> Printer Dictionary a
alg
  where
    alg :: Dictionary a -> Printer Dictionary a
    alg :: forall a. Dictionary a -> Printer Dictionary a
alg (Member Key
key Tree Item a a
c)      a
a         = Key
", " Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
key Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
"=" Key -> Key -> Key
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 (Member' Key
key Tree Item a a
c)     (Just a
a)  = Key
", " Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
key Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
"=" Key -> Key -> Key
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 (Member' Key
_ Tree Item a a
_)       a
Maybe a
Nothing   = Key
Context Dictionary
""
    alg (List Key
key Leaf BareItem a
vLeaf)    a
xs        = Key
", " Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
key Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
"=" Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Leaf BareItem a -> [a] -> Key
forall a. Leaf BareItem a -> [a] -> Key
renderInner Leaf BareItem a
vLeaf a
[a]
xs
    alg (List' Key
key Leaf BareItem a
vLeaf)   (Just [a]
xs) = Key
", " Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
key Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Key
"=" Key -> Key -> Key
forall a. Semigroup a => a -> a -> a
<> Leaf BareItem a -> [a] -> Key
forall a. Leaf BareItem a -> [a] -> Key
renderInner Leaf BareItem a
vLeaf [a]
xs
    alg (List' Key
_ Leaf BareItem a
_)         a
Maybe [a]
Nothing   = Key
Context Dictionary
""
    alg Dictionary a
Raw                 a
bs        = a
Context Dictionary
bs