-- |
-- A dynamic parameter-parsing map.
module Web.Route.Invertible.Map.ParameterType
  ( ParameterTypeMap
  , singletonParameterType
  , insertParameterType
  , lookupParameterType
  ) where

import Prelude hiding (lookup)

import Data.Dynamic (Dynamic, toDyn)
import qualified Data.Map.Strict as M
import Data.Maybe (maybeToList)

import Web.Route.Invertible.Parameter
import Web.Route.Invertible.Map.Monoid

-- |A map of 'ParameterType's.
type ParameterTypeMap s a = MonoidMap (ParameterType s) a

-- |Equivalent to @'MM.singleton' . 'parameterTypeOf'@
singletonParameterType :: Parameter s p => proxy p -> a -> ParameterTypeMap s a
singletonParameterType :: proxy p -> a -> ParameterTypeMap s a
singletonParameterType proxy p
p = Map (ParameterType s) a -> ParameterTypeMap s a
forall k a. Map k a -> MonoidMap k a
MonoidMap (Map (ParameterType s) a -> ParameterTypeMap s a)
-> (a -> Map (ParameterType s) a) -> a -> ParameterTypeMap s a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParameterType s -> a -> Map (ParameterType s) a
forall k a. k -> a -> Map k a
M.singleton (proxy p -> ParameterType s
forall s (proxy :: * -> *) a.
Parameter s a =>
proxy a -> ParameterType s
parameterTypeOf proxy p
p)

-- |Equivalent to @'MM.insert' . 'parameterTypeOf'@
insertParameterType :: Parameter s p => proxy p -> a -> ParameterTypeMap s a -> ParameterTypeMap s a
insertParameterType :: proxy p -> a -> ParameterTypeMap s a -> ParameterTypeMap s a
insertParameterType proxy p
p a
a (MonoidMap Map (ParameterType s) a
m) = Map (ParameterType s) a -> ParameterTypeMap s a
forall k a. Map k a -> MonoidMap k a
MonoidMap (Map (ParameterType s) a -> ParameterTypeMap s a)
-> Map (ParameterType s) a -> ParameterTypeMap s a
forall a b. (a -> b) -> a -> b
$ ParameterType s
-> a -> Map (ParameterType s) a -> Map (ParameterType s) a
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert (proxy p -> ParameterType s
forall s (proxy :: * -> *) a.
Parameter s a =>
proxy a -> ParameterType s
parameterTypeOf proxy p
p) a
a Map (ParameterType s) a
m

-- |/O(n)/. Find all types in the map that can parse the given string data, returning 'toDyn' of the parsed string (the result of 'parseParameter') and the associated map value.
lookupParameterType :: s -> ParameterTypeMap s a -> [(Dynamic, a)]
lookupParameterType :: s -> ParameterTypeMap s a -> [(Dynamic, a)]
lookupParameterType s
s (MonoidMap Map (ParameterType s) a
m) = do
  (ParameterType Proxy a
t, a
nt) <- Map (ParameterType s) a -> [(ParameterType s, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map (ParameterType s) a
m
  a
x <- Maybe a -> [a]
forall a. Maybe a -> [a]
maybeToList (Maybe a -> [a]) -> Maybe a -> [a]
forall a b. (a -> b) -> a -> b
$ Proxy a -> s -> Maybe a
forall s (proxy :: * -> *) a.
Parameter s a =>
proxy a -> s -> Maybe a
parseParameterAs Proxy a
t s
s
  (Dynamic, a) -> [(Dynamic, a)]
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn a
x, a
nt)