{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}
module Web.Eved.QueryParam
    where

import           Data.Text       (Text)
import qualified Web.HttpApiData as HttpApiData

data QueryParam a = QueryParam
    { QueryParam a -> [Text] -> Either Text a
fromQueryParam :: [Text] -> Either Text a
    , QueryParam a -> a -> [Text]
toQueryParam   :: a -> [Text]
    }

auto :: (Applicative f, HttpApiData.FromHttpApiData a, HttpApiData.ToHttpApiData a) => f (QueryParam a)
auto :: f (QueryParam a)
auto = QueryParam a -> f (QueryParam a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryParam a -> f (QueryParam a))
-> QueryParam a -> f (QueryParam a)
forall a b. (a -> b) -> a -> b
$ QueryParam :: forall a.
([Text] -> Either Text a) -> (a -> [Text]) -> QueryParam a
QueryParam
    { fromQueryParam :: [Text] -> Either Text a
fromQueryParam = \case
          []  -> Text -> Either Text a
forall a b. a -> Either a b
Left Text
"Value not found"
          Text
x:[Text]
_ -> Text -> Either Text a
forall a. FromHttpApiData a => Text -> Either Text a
HttpApiData.parseQueryParam Text
x
    , toQueryParam :: a -> [Text]
toQueryParam = Text -> [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> [Text]) -> (a -> Text) -> a -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. ToHttpApiData a => a -> Text
HttpApiData.toQueryParam
    }

list ::  Functor f => f (QueryParam a) -> f (QueryParam [a])
list :: f (QueryParam a) -> f (QueryParam [a])
list = (QueryParam a -> QueryParam [a])
-> f (QueryParam a) -> f (QueryParam [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((QueryParam a -> QueryParam [a])
 -> f (QueryParam a) -> f (QueryParam [a]))
-> (QueryParam a -> QueryParam [a])
-> f (QueryParam a)
-> f (QueryParam [a])
forall a b. (a -> b) -> a -> b
$ \QueryParam a
qp ->
    QueryParam :: forall a.
([Text] -> Either Text a) -> (a -> [Text]) -> QueryParam a
QueryParam
        { fromQueryParam :: [Text] -> Either Text [a]
fromQueryParam = (Text -> Either Text a) -> [Text] -> Either Text [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (QueryParam a -> [Text] -> Either Text a
forall a. QueryParam a -> [Text] -> Either Text a
fromQueryParam QueryParam a
qp ([Text] -> Either Text a)
-> (Text -> [Text]) -> Text -> Either Text a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
        , toQueryParam :: [a] -> [Text]
toQueryParam = (a -> [Text]) -> [a] -> [Text]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
(=<<) (QueryParam a -> a -> [Text]
forall a. QueryParam a -> a -> [Text]
toQueryParam QueryParam a
qp)
        }

defaulted :: Functor f => a -> f (QueryParam a) -> f (QueryParam a)
defaulted :: a -> f (QueryParam a) -> f (QueryParam a)
defaulted a
defaultValue = (QueryParam a -> QueryParam a)
-> f (QueryParam a) -> f (QueryParam a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((QueryParam a -> QueryParam a)
 -> f (QueryParam a) -> f (QueryParam a))
-> (QueryParam a -> QueryParam a)
-> f (QueryParam a)
-> f (QueryParam a)
forall a b. (a -> b) -> a -> b
$ \QueryParam a
qp ->
    QueryParam :: forall a.
([Text] -> Either Text a) -> (a -> [Text]) -> QueryParam a
QueryParam
        { fromQueryParam :: [Text] -> Either Text a
fromQueryParam = \[Text]
xs ->
            if [Text] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
xs
               then a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
defaultValue
               else QueryParam a -> [Text] -> Either Text a
forall a. QueryParam a -> [Text] -> Either Text a
fromQueryParam QueryParam a
qp [Text]
xs
        , toQueryParam :: a -> [Text]
toQueryParam = QueryParam a -> a -> [Text]
forall a. QueryParam a -> a -> [Text]
toQueryParam QueryParam a
qp
        }

maybe :: Functor f => f (QueryParam a) -> f (QueryParam (Maybe a))
maybe :: f (QueryParam a) -> f (QueryParam (Maybe a))
maybe = (QueryParam a -> QueryParam (Maybe a))
-> f (QueryParam a) -> f (QueryParam (Maybe a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((QueryParam a -> QueryParam (Maybe a))
 -> f (QueryParam a) -> f (QueryParam (Maybe a)))
-> (QueryParam a -> QueryParam (Maybe a))
-> f (QueryParam a)
-> f (QueryParam (Maybe a))
forall a b. (a -> b) -> a -> b
$ \QueryParam a
qp ->
    QueryParam :: forall a.
([Text] -> Either Text a) -> (a -> [Text]) -> QueryParam a
QueryParam
        { fromQueryParam :: [Text] -> Either Text (Maybe a)
fromQueryParam = \[Text]
xs ->
            if [Text] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
xs
               then Maybe a -> Either Text (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
               else a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Either Text a -> Either Text (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryParam a -> [Text] -> Either Text a
forall a. QueryParam a -> [Text] -> Either Text a
fromQueryParam QueryParam a
qp [Text]
xs
        , toQueryParam :: Maybe a -> [Text]
toQueryParam = \case
            Just a
a  -> QueryParam a -> a -> [Text]
forall a. QueryParam a -> a -> [Text]
toQueryParam QueryParam a
qp a
a
            Maybe a
Nothing -> []
        }

integer :: Applicative f => f (QueryParam Integer)
integer :: f (QueryParam Integer)
integer = f (QueryParam Integer)
forall (f :: * -> *) a.
(Applicative f, FromHttpApiData a, ToHttpApiData a) =>
f (QueryParam a)
auto

text :: Applicative f => f (QueryParam Text)
text :: f (QueryParam Text)
text = f (QueryParam Text)
forall (f :: * -> *) a.
(Applicative f, FromHttpApiData a, ToHttpApiData a) =>
f (QueryParam a)
auto