# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php

"""
Creates a session object.

In your application, use::

    environ['paste.flup_session_service'].session

This will return a dictionary.  The contents of this dictionary will
be saved to disk when the request is completed.  The session will be
created when you first fetch the session dictionary, and a cookie will
be sent in that case.  There's current no way to use sessions without
cookies, and there's no way to delete a session except to clear its
data.
"""

from paste import httpexceptions
from paste import wsgilib
import flup.middleware.session
flup_session = flup.middleware.session

# This is a dictionary of existing stores, keyed by a tuple of
# store type and parameters
store_cache = {}

class NoDefault(object):
    pass

class SessionMiddleware(object):

    session_classes = {
        'memory': (flup_session.MemorySessionStore,
                   [('session_timeout', 'timeout', int, 60)]),
        'disk': (flup_session.DiskSessionStore,
                 [('session_timeout', 'timeout', int, 60),
                  ('session_dir', 'storeDir', str, '/tmp/sessions')]),
        'shelve': (flup_session.ShelveSessionStore,
                   [('session_timeout', 'timeout', int, 60),
                    ('session_file', 'storeFile', str,
                     '/tmp/session.shelve')]),
        }


    def __init__(self, app,
                 global_conf=None,
                 session_type=NoDefault,
                 cookie_name=NoDefault,
                 **store_config
                 ):
        self.application = app
        if session_type is NoDefault:
            session_type = global_conf.get('session_type', 'disk')
        self.session_type = session_type
        try:
            self.store_class, self.store_args = self.session_classes[self.session_type]
        except KeyError:
            raise KeyError(
                "The session_type %s is unknown (I know about %s)"
                % (self.session_type,
                   ', '.join(self.session_classes.keys())))
        kw = {}
        for config_name, kw_name, coercer, default in self.store_args:
            value = coercer(store_config.get(config_name, default))
            kw[kw_name] = value
        self.store = self.store_class(**kw)
        if cookie_name is NoDefault:
            cookie_name = global_conf.get('session_cookie', '_SID_')
        self.cookie_name = cookie_name

    def __call__(self, environ, start_response):
        service = flup_session.SessionService(
            self.store, environ, cookieName=self.cookie_name,
            fieldName=self.cookie_name)
        environ['paste.flup_session_service'] = service

        def cookie_start_response(status, headers, exc_info=None):
            service.addCookie(headers)
            return start_response(status, headers, exc_info)

        try:
            app_iter = self.application(environ, cookie_start_response)
        except httpexceptions.HTTPException as e:
            headers = (e.headers or {}).items()
            service.addCookie(headers)
            e.headers = dict(headers)
            service.close()
            raise
        except:
            service.close()
            raise

        return wsgilib.add_close(app_iter, service.close)

def make_session_middleware(app, global_conf,
                            session_type=NoDefault,
                            cookie_name=NoDefault,
                            **store_config):
    """
    Wraps the application in a session-managing middleware.
    The session service can then be found in
    ``environ['paste.flup_session_service']``
    """
    return SessionMiddleware(
        app, global_conf=global_conf,
        session_type=session_type, cookie_name=cookie_name,
        **store_config)
