import lasso
import urllib

from quixote import get_request, get_response, get_session, get_session_manager, get_publisher, redirect
from quixote.directory import Directory
import authentic.root
from authentic import misc
from authentic.form import *
from authentic import template
from authentic import identities
from authentic import liberty

from authentic import emails

from authentic import tokens


def memorize_ip():
    session = get_session()
    identity = identities.store.get_identity(session.user)
    identity.cdc_ip_check_last_ip = get_request().environ.get('X_FORWARDED_FOR',
            get_request().environ.get('REMOTE_ADDR'))
    authentic.identities.store.save(identity)


OldRootDirectory = authentic.root.RootDirectory

class LibertyDirectory(liberty.root.RootDirectory):
    pass


class TokenDirectory(Directory):
    _q_exports = ['']
    def __init__(self, component):
        self.component = component

    def _q_index [html] (self):
        try:
            token = tokens.Token.get(self.component)
        except KeyError:
            return self.missingtoken()

        if token.type != 'cdc-ip-check':
            return self.missingtoken()

        if token.session_id != get_session().id:
            return self.missingtoken()

        memorize_ip()
        token.remove_self()

        request = get_request()
        return redirect(request.environ['SCRIPT_NAME'] + '/login')

    def missingtoken [html] (self):
        template.html_top(_('Address Confirmation'))

        'booh'


class TokensDirectory(Directory):
    def _q_lookup(self, component):
        return TokenDirectory(component)

class AlternateRootDirectory(OldRootDirectory):
    liberty = LibertyDirectory()

    confirm = TokensDirectory()

    def __init__(self):
        OldRootDirectory.__init__(self)
        if not 'confirm' in self._q_exports:
            self._q_exports.append('confirm')

    def login [html] (self):
        session = get_session()
        if not session.user:
            return OldRootDirectory.login(self)

        if not session.lasso_login_dump:
            return redirect('/')

        identity = identities.store.get_identity(session.user)

        server = misc.get_lasso_server()
        login = lasso.Login.newFromDump(server, session.lasso_login_dump)

        if login.request.requestAuthnContext:
            t = list(login.request.requestAuthnContext.authnContextClassRef)
            if lasso.LIB_AUTHN_CONTEXT_CLASS_REF_INTERNET_PROTOCOL_PASSWORD in t:
                t = self.login_ip_check()
                if not t:
                    return self.login_success(identity)
                return t

        return OldRootDirectory.login(self)

    def login_ip_check(self):
        session = get_session()
        identity = identities.store.get_identity(session.user)
        if not hasattr(identity, 'cdc_ip_check_last_ip'):
            identity.cdc_ip_check_last_ip = None
            return self.ip_check_change(identity)

        remote_ip = get_request().environ.get('X_FORWARDED_FOR',
                get_request().environ.get('REMOTE_ADDR'))
        if identity.cdc_ip_check_last_ip != remote_ip:
            return self.ip_check_ip_change(identity)

        session.authentication_method = 'password-and-ip'
        return None

    
    def ip_check_ip_change [html] (self, identity):
        template.html_top(_('Address Confirmation'))

        text = str(os.path.join(get_publisher().app_dir, 'ipcheck/message'))
        if os.path.exists(text):
            htmltext(file(text).read())

        self.sendmail(identity)

    def sendmail(self, identity):
        token = tokens.Token()
        token.type = 'cdc-ip-check'
        token.session_id = get_session().id
        token.store()
        msg = str(os.path.join(get_publisher().app_dir, 'ipcheck/email'))
        msg = file(msg).read()

        req = get_request()
        url = '%s://%s%s/confirm/%s' % (req.get_scheme(), req.get_server(),
                urllib.quote(req.environ.get('SCRIPT_NAME')),
                token.id)

        msg = msg.replace('[name]', identity.name or identity.email)
        msg = msg.replace('[url]', url)
        emails.email(_('Asking for confirmation'), msg, identity.email)


    def login_success(self, identity):
        session = get_session()
        if not session.lasso_login_dump:
            return OldRootDirectory.login_success(self, identity)

        server = misc.get_lasso_server()
        login = lasso.Login.newFromDump(server, session.lasso_login_dump)

        if login.request.requestAuthnContext:
            t = list(login.request.requestAuthnContext.authnContextClassRef)
            if lasso.LIB_AUTHN_CONTEXT_CLASS_REF_INTERNET_PROTOCOL_PASSWORD in t:
                t = self.login_ip_check()
                if t:
                    return t

        return OldRootDirectory.login_success(self, identity)


    def registration_callback(self, identity):
        identity.cdc_ip_check_last_ip = get_request().environ.get('X_FORWARDED_FOR',
                get_request().environ.get('REMOTE_ADDR'))
        authentic.identities.store.save(identity)


authentic.root.RootDirectory = AlternateRootDirectory
