"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/session.py $
$Id: session.py 28904 2006-10-06 17:27:59Z rmasse $
"""
from dulcinea.attachable import Attachable
from dulcinea.common import is_qp, get_request, get_publisher, get_connection
from dulcinea.common import get_session, get_response, site_now, get_site_name
from dulcinea.user import DulcineaUser
from qp.lib.util import randbytes
from qp.pub.session import Session

if not is_qp():
    import qp.pub.session
    # qp session code can be used if it has the right globals.
    qp.pub.session.get_publisher = get_publisher
    qp.pub.session.get_request = get_request
    qp.pub.session.site_now = site_now
    # qp session code wants requests with get_remote_address()
    from quixote.http_request import HTTPRequest
    def get_remote_address(self):
        return self.environ.get('REMOTE_ADDR')
    HTTPRequest.get_remote_address = get_remote_address

class DulcineaSession (Session, Attachable):

    effective_user_is = DulcineaUser
    owner_is = DulcineaUser

    def __init__(self):
        Session.__init__(self)
        Attachable.__init__(self)

    def clear_app_state(self):
        """Override to clear any session data
        """

    if not is_qp():
        # Things expected by Quixote.
        user = property(lambda self: self.get_effective_user())
        def create_form_token(self):
            return self.get_effective_user().get_tokens().new_token()
        def has_form_token(self, token):
            return token in self.get_effective_user().get_tokens()
        def remove_form_token(self, token):
            return self.get_effective_user().get_tokens().discard(token)

class DulcineaSessionManager (object):
    # This is here so that the Quixote-based Publisher can use 
    # DulcineaSessions.
    def set_cookie(self, value):
        name = get_site_name()
        path = get_request().get_environ('SCRIPT_NAME')
        if not path.endswith("/"):
            path += "/"
        config = get_publisher().config
        domain = config.session_cookie_domain
        get_response().set_cookie(name, value, domain=domain, path=path)
        return name

    def start_request(self):
        id = get_request().get_cookie(get_site_name())
        sessions = get_connection().get_root()['sessions']
        if id in sessions:
            session = sessions[id]
            get_request().session_id = id
        else:
            config = get_publisher().config
            id = get_request().get_cookie(config.session_cookie_name)
            if id in sessions:
                session = sessions[id]
                get_request().session_id = id
                self.set_cookie(id)
            else:
                session = get_publisher().create_session()
                get_request().session_id = None
        session.access()
        get_request().session = session

    def finish_successful_request(self):
        session = get_session()
        if get_request().session_id is None and session.needs_saving():
            cookie = randbytes(8)
            get_publisher().get_sessions()[cookie] = session
            self.set_cookie(cookie)
        get_publisher().commit()

    def finish_failed_request(self):
        """Called near the end of a failed request (i.e. a exception that was
        not a PublisherError was raised.
        """
        get_publisher().abort()


def update_sessions():
    import dulcinea.persistent_session
    dulcinea.persistent_session.DulcineaSession = DulcineaSession
    from datetime import datetime
    from dulcinea.common import get_publisher
    publisher = get_publisher()
    connection = get_publisher().get_connection()
    from qp.lib.spec import get_spec_problems
    sessions = connection.get_root()['session_manager'].sessions
    from qp.lib.tz import Eastern
    for session in sessions.values():
        tokens = list(session._form_tokens)[-4:]
        user = session.__dict__.get('user')
        tokenset = user.get_tokens()
        tokenset.tokens = (tokenset.tokens + tokens)[-16:]
        tokenset._p_note_change()
        del session._form_tokens
        session.owner = session.last_user
        del session.last_user
        session.effective_user = user
        del session.__dict__['user']
        session.remote_address = session._remote_address
        del session._remote_address
        session.access_time = datetime.fromtimestamp(
            session._access_time).replace(tzinfo=Eastern)
        del session._access_time
        session.authentication_time = datetime.fromtimestamp(
            session._creation_time).replace(tzinfo=Eastern)
        del session._creation_time
        del session.id
        del session.actual_user
        problems = get_spec_problems(session)
        if problems:
            for problem in problems:
                print problem
            assert 0
    from durus.btree import BTree
    new_sessions = BTree()
    connection.get_root()['sessions'] = new_sessions
    for key, value in sessions.items():
        new_sessions[key] = value
    del connection.get_root()['session_manager']
    assert 'session_manager' not in connection.get_root().keys()


