# Copyright (C) 2005 JanRain, Inc.
# Copyright (C) 2009, 2010 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os

from apache_openid import logging
from apache_openid.utils import OK
from cgi import escape


message_text = {
    'empty': ('message', 'Enter an OpenID URL to continue'),
    'cancel': ('message', 'Authorization cancelled'),
    'bad_html': ('error', 'No OpenID information was found at that URL'),
    'http_failed': ('error', 'There was an error communicating with the '
        'server'),
    'failure': ('error', 'The server reported an error'),
    'denied': ('error', 'Either you have not been granted access to this '
        'resource or your entitlement has timed out.  Please try again.'),
    'discovery': ('error', 'Failed to discover an OpenID server'),
    }


class Template(object):

    def __init__(self, request, response, session, template_path):
        self.request = request
        self.response = response
        self.session = session
        self._template_path = template_path

    def render(self, template, values={}):
        if template == 'login_page.html':
            content = self.get_template(template) % self.fill_login_page(values)
        else:
            content = self.get_template(template) % values
        self.response.apache_request.content_type = 'text/html; charset=UTF-8'
        self.response.apache_request.set_content_length(len(content))
        self.response.apache_request.write(content)
        self.session['message'] = None
        self.session.save()
        return OK

    def fill_login_page(self, values):
        """Generate the HTML for the login page."""
        openid_identifier = values.get('openid_identifier')
        messages = values.get('messages')
        allowed_ops = values.get('allowed_ops')
        target = values.get('target')

        message_chunks = []
        for name in messages:
            message_info = message_text.get(name)
            if message_info is None:
                message_info = ('error', 'An error occurred')

            chunk = "<div class='%s'>%s</div>" % message_info
            message_chunks.append(chunk)

        if self.request.cookied_user:
            chunk = ("<div class='message'>You are currently logged "
                     "in as %s. (<a href='%s'>logout</a>)</div>"
                     % (escape(self.request.cookied_user),
                        escape(self.request.action_url('logout'), True)))
            message_chunks.append(chunk)

        message_html = '\n'.join(message_chunks)

        if target:
            resource = (
                '<div class="message">Authorization is required to access '
                '<a href="%s">%s</a></div>') % (target, escape(target))
        else:
            resource = ''

        if not openid_identifier:
            openid_identifier = ''

        if len(allowed_ops) == 0:
            # use a text input box
            form_input = '<p>Enter your OpenID identity URL to continue.</p>'
            form_input += ('<input type="text" name="openid_identifier" '
                'value="%s">' % (openid_identifier,))
            onload_js = 'document.oid_form.openid_identifier.focus();'
        elif len(allowed_ops) == 1:
            # use a hidden field
            for k in allowed_ops.keys():
                form_input = ('<input type="hidden" name="openid_identifier" '
                    'value="%s">' % (allowed_ops[k].decode('utf-8'),))
            if target and not self.request.cookied_user and not messages:
                onload_js = ('document.getElementById(\'continue_btn\').style.visibility=\'hidden\'; '
                    + 'document.oid_form.submit();')
            else:
                onload_js = ''
        else:
            # use a dropdown list
            form_input = '<p>Enter your OpenID identity URL to continue.</p>'
            form_input += '<select name="openid_identifier">'
            for k in allowed_ops.keys():
                form_input += ('<option value="%s">'
                    '%s</option>' % (allowed_ops[k], k,))
            form_input += '</select>'
            onload_js = ''

        return dict(
            action=escape(self.request.action_url('login'), True),
            resource=resource,
            title='OpenID Authentication Required',
            message=message_html,
            openid_identifier=escape(openid_identifier, True),
            form_input=form_input,
            onload=onload_js,
            )

    def get_template(self, template):
        return file('%s/%s' % (self.template_path, template)).read()

    @property
    def template_path(self):
        if self._template_path is None:
            return os.path.join(os.path.dirname(__file__), 'templates')
        else:
            return self._template_path
