import re
import urlparse
from wsgiref.util import application_uri

class GoogleOpenIdClientApp(object):
    AX_NS = "http://openid.net/srv/ax/1.0"
    FINISHED_URL = re.compile("^/finished/([A-Za-z0-9]+)$")

    def __init__(self, sessions, store, onsuccess, make_consumer):
        self.make_consumer = make_consumer
        self.store = store
        self.sessions = sessions
        self.onsuccess = onsuccess

    def __call__(self, environ, start_response):
        path = environ['PATH_INFO']

        appuri = application_uri(environ)
        if not appuri.endswith('/'):
            appuri += '/'

        if path == '/':
            session = self.sessions.create()
            consumer = self.make_consumer(session.data, self.store)
            url = "https://www.google.com/accounts/o8/id"
            request = consumer.begin(url)
            request.addExtensionArg(self.AX_NS, "mode", "fetch_request")
            request.addExtensionArg(self.AX_NS, "type.email", "http://axschema.org/contact/email")
            request.addExtensionArg(self.AX_NS, "required", "email")
            url = request.redirectURL(appuri, "%sfinished/%s" % (appuri, session.id))

            start_response('302 Found',
                           [('Location', url)])
            return []

        match = self.FINISHED_URL.match(path)
        if match:
            # TODO: QUERY_STRING may be empty or absent
            query = dict(urlparse.parse_qsl(environ['QUERY_STRING']))
            session_id = match.group(1)
            if session_id in self.sessions:
                session = self.sessions[session_id]
                consumer = self.make_consumer(session.data, self.store)
                response = consumer.complete(query, "%sfinished/%s" % (appuri, session.id))
                del self.sessions[session_id]
                start_response('200 OK',
                               [('Content-Type', 'text/plain')])

                if response.status == "success":
                    return ["Hi %s" % response.getSigned(self.AX_NS, "value.email")]
                else:
                    return ["You declined! %s" % response.status]

        start_response('404 Not Found',
                       [('Content-Type', 'text/plain')])
        return ['path not found: %s' % path]
