
import uuid, pickle
from datetime import datetime

from flask.sessions import SessionInterface, SessionMixin

from appl import app, db
from appl import models

class Session(dict, SessionMixin):
    def __init__(self, data=None, sessid=None, ipaddr=None):
        self.sessid = sessid
        self.ipaddr = ipaddr
        self.permanent = True
        if data:
            dict.__init__(self, data)
        else:
            dict.__init__(self)

class SQLA_SessionInterface(SessionInterface):

    def open_session(self, app, request):

        models.Session.query.filter(
                models.Session.expires <= datetime.utcnow()).delete()
        db.session.commit()

        sessid = request.cookies.get(app.session_cookie_name)
        ipaddr = request.remote_addr

#        print(f'opensess: {sessid}')

        if not sessid:
            return Session(sessid=str(uuid.uuid4()), ipaddr=ipaddr)

        saved = models.Session.query.filter_by(session_id=sessid).first()

        if saved and saved.expires <= datetime.utcnow():
            # expired session
            db.session.delete(saved)
            db.session.commit()
            saved = None

        if saved:
            data = pickle.loads(saved.data)
            return Session(data, sessid=sessid)

        return Session(sessid=str(uuid.uuid4()), ipaddr=ipaddr)

    def save_session(self, app, session, response):

        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)

        saved = models.Session.query.filter_by(
                                        session_id=session.sessid).first()

#        print(f'savesess: {session} {session.sessid} {saved}')
        if not session:    # dict has no entries
            if session.modified:
                if saved:
                    db.session.delete(saved)
                    db.session.commit()
                response.delete_cookie(app.session_cookie_name, 
                                       domain=domain, path=path)
            return

        data = pickle.dumps(dict(session))
        expires = self.get_expiration_time(app, session)
        if saved:
            saved.data = data
            saved.expires = expires
            db.session.commit()
        else:
            db.session.add(models.Session(session_id=session.sessid, 
                           created=datetime.utcnow(), expires=expires,
                           data=data, ipaddr=session.ipaddr))
            db.session.commit()
        response.set_cookie(app.session_cookie_name, session.sessid,
                            expires=expires, 
                            httponly=self.get_cookie_httponly(app),
                            domain=domain, path=path, 
                            secure=self.get_cookie_secure(app))
