module Okapi.HTTP.Request.Method (
    KnownMethod (..),
    Method (..),
    ParseError (..),
    parse,
    print,
    raw,
    method,
    knownMethodToStd,
    extractMethod,
    GET,
    POST,
    PUT,
    DELETE,
) where

import GHC.TypeLits (Symbol)
import Network.HTTP.Types qualified as HTTP
import Okapi.Tree (Failure, Context)
import Prelude hiding (print)

data KnownMethod (m :: Symbol) where
    GET :: KnownMethod "GET"
    POST :: KnownMethod "POST"
    PUT :: KnownMethod "PUT"
    DELETE :: KnownMethod "DELETE"

deriving instance Eq (KnownMethod m)
deriving instance Show (KnownMethod m)

type GET = KnownMethod "GET"
type POST = KnownMethod "POST"
type PUT = KnownMethod "PUT"
type DELETE = KnownMethod "DELETE"

data Method a where
    Raw :: Method HTTP.Method
    Method :: KnownMethod m -> Method (KnownMethod m)

data ParseError = ParseError deriving (ParseError -> ParseError -> Bool
(ParseError -> ParseError -> Bool)
-> (ParseError -> ParseError -> Bool) -> Eq ParseError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ParseError -> ParseError -> Bool
== :: ParseError -> ParseError -> Bool
$c/= :: ParseError -> ParseError -> Bool
/= :: ParseError -> ParseError -> Bool
Eq, Int -> ParseError -> ShowS
[ParseError] -> ShowS
ParseError -> String
(Int -> ParseError -> ShowS)
-> (ParseError -> String)
-> ([ParseError] -> ShowS)
-> Show ParseError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ParseError -> ShowS
showsPrec :: Int -> ParseError -> ShowS
$cshow :: ParseError -> String
show :: ParseError -> String
$cshowList :: [ParseError] -> ShowS
showList :: [ParseError] -> ShowS
Show)

type instance Context Method = HTTP.Method
type instance Failure Method = ParseError

parse :: Method method -> HTTP.Method -> Either ParseError method
parse :: forall method. Method method -> Method -> Either ParseError method
parse Method method
Raw Method
m = method -> Either ParseError method
forall a b. b -> Either a b
Right method
Method
m
parse (Method KnownMethod m
km) Method
m
    | Method
m Method -> Method -> Bool
forall a. Eq a => a -> a -> Bool
== StdMethod -> Method
HTTP.renderStdMethod (KnownMethod m -> StdMethod
forall (m :: Symbol). KnownMethod m -> StdMethod
knownMethodToStd KnownMethod m
km) = method -> Either ParseError method
forall a b. b -> Either a b
Right method
KnownMethod m
km
    | Bool
otherwise = ParseError -> Either ParseError method
forall a b. a -> Either a b
Left ParseError
ParseError

print :: Method method -> method -> HTTP.Method
print :: forall method. Method method -> method -> Method
print Method method
Raw method
m = method
Method
m
print (Method KnownMethod m
km) method
_ = StdMethod -> Method
HTTP.renderStdMethod (KnownMethod m -> StdMethod
forall (m :: Symbol). KnownMethod m -> StdMethod
knownMethodToStd KnownMethod m
km)

raw :: Method HTTP.Method
raw :: Method Method
raw = Method Method
Raw

method :: KnownMethod m -> Method (KnownMethod m)
method :: forall (m :: Symbol). KnownMethod m -> Method (KnownMethod m)
method KnownMethod m
km = (KnownMethod m -> Method (KnownMethod m)
forall (m :: Symbol). KnownMethod m -> Method (KnownMethod m)
Method KnownMethod m
km)

knownMethodToStd :: KnownMethod m -> HTTP.StdMethod
knownMethodToStd :: forall (m :: Symbol). KnownMethod m -> StdMethod
knownMethodToStd KnownMethod m
GET = StdMethod
HTTP.GET
knownMethodToStd KnownMethod m
POST = StdMethod
HTTP.POST
knownMethodToStd KnownMethod m
PUT = StdMethod
HTTP.PUT
knownMethodToStd KnownMethod m
DELETE = StdMethod
HTTP.DELETE

extractMethod :: Method (KnownMethod m) -> HTTP.StdMethod
extractMethod :: forall (m :: Symbol). Method (KnownMethod m) -> StdMethod
extractMethod (Method KnownMethod m
km) = KnownMethod m -> StdMethod
forall (m :: Symbol). KnownMethod m -> StdMethod
knownMethodToStd KnownMethod m
km