module Web.Route.Invertible.Query
  ( QueryString
  , QueryParams
  , simpleQueryParams
  , paramsQuerySimple
  ) where

import Control.Arrow (second)
import qualified Data.ByteString as BS
import qualified Data.HashMap.Lazy as HM
import Network.HTTP.Types.URI (SimpleQuery)

-- |The type of URL query strings, variables, and parameters, after URI decoding but before UTF-8 decoding.
type QueryString = BS.ByteString
-- |A map from query variables to values, based on 'SimpleQuery'.
type QueryParams = HM.HashMap QueryString [QueryString]

simpleQueryParams :: SimpleQuery -> QueryParams
simpleQueryParams :: SimpleQuery -> QueryParams
simpleQueryParams = ([QueryString] -> [QueryString] -> [QueryString])
-> [(QueryString, [QueryString])] -> QueryParams
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> [(k, v)] -> HashMap k v
HM.fromListWith [QueryString] -> [QueryString] -> [QueryString]
forall a. [a] -> [a] -> [a]
(++) ([(QueryString, [QueryString])] -> QueryParams)
-> (SimpleQuery -> [(QueryString, [QueryString])])
-> SimpleQuery
-> QueryParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SimpleQueryItem -> (QueryString, [QueryString]))
-> SimpleQuery -> [(QueryString, [QueryString])]
forall a b. (a -> b) -> [a] -> [b]
map ((QueryString -> [QueryString])
-> SimpleQueryItem -> (QueryString, [QueryString])
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second QueryString -> [QueryString]
forall (m :: * -> *) a. Monad m => a -> m a
return)

paramsQuerySimple :: QueryParams -> SimpleQuery
paramsQuerySimple :: QueryParams -> SimpleQuery
paramsQuerySimple QueryParams
q = [ (QueryString
n, QueryString
v) | (QueryString
n, [QueryString]
vl) <- QueryParams -> [(QueryString, [QueryString])]
forall k v. HashMap k v -> [(k, v)]
HM.toList QueryParams
q, QueryString
v <- [QueryString]
vl ]