{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleContexts       #-}

    This module provides the generic interface to the various typed
    session implementations, including both server-side and client-side
    typed sessions.
module Snap.Snaplet.TypedSession (
    ) where

import Snap.Snaplet

import Data.Map (Map)
import qualified Data.Map as M

    The generic interface to typed session implementations.  Both the
    client-side and server-side implementations of sessions implement
    the common interface specified here.
class HasTypedSession v t | v -> t where
        Retrieves the session for the current request, always creating
        it if necessary.
    getSession   :: Handler b v t

        Stores a new value for the current session.
    setSession   :: t -> Handler b v ()

        Completely clears the current session, removing all associated
        cookies and server-side storage if applicable.
    clearSession :: Handler b v ()

        Marks a session as recently used, resetting the session timeout
    touchSession :: Handler b v ()

    A convenience function for gaining access to the session.  The
    session is touched and then passed to the nested 'Handler'.
withSession :: HasTypedSession v t => (t -> Handler b v a) -> Handler b v a
withSession handler = touchSession >> getSession >>= handler

    Gets a named value from a session that happens to be a 'Map'.
getFromSession :: (Ord k, HasTypedSession v (Map k a))
               => k -> Handler b v (Maybe a)
getFromSession key = fmap (M.lookup key) getSession

    Sets a named value in a session that happens to be a 'Map'.
setInSession :: (Ord k, HasTypedSession v (Map k a))
             => k -> a -> Handler b v ()
setInSession k v = withSession $ setSession . M.insert k v

    Deletes a named value from a session that happens to be a 'Map'.
deleteFromSession :: (Ord k, HasTypedSession v (Map k a))
                  => k -> Handler b v ()
deleteFromSession key = withSession $ setSession . M.delete key