import random
import lasso

from quixote import get_request, get_session, redirect, get_publisher
from quixote.directory import Directory

from larpe.qommon.form import *

from larpe import emails
from larpe import errors
from larpe import misc
from larpe import storage
from larpe.users import User
from larpe.hosts import Host

from menu import *

class UserUI:
    def __init__(self, user):
        self.user = user

    def form_new(self):
        form = Form(enctype="multipart/form-data")
        form.add(StringWidget, "name", title = _('User Name'), required = True, size=30)
        form.add(StringWidget, "email", title = _('Email'), required = False, size=30)
        form.add_submit("submit", _("Submit"))
        form.add_submit("cancel", _("Cancel"))
        return form

    def form_edit(self):
        form = Form(enctype="multipart/form-data")
        form.add(StringWidget, "id", title = _('User Id'), required = False, size=30,
                value = self.user.id, readonly = 'readonly')
        form.add(StringWidget, "name", title = _('User Name'), required = True, size=30,
                value = self.user.name)
        form.add(StringWidget, "email", title = _('Email'), required = False, size=30,
                value = self.user.email)
        form.add_submit("submit", _("Submit"))
        form.add_submit("cancel", _("Cancel"))
        return form

    def submit_form(self, form):
        if not self.user:
            self.user = User()
        for f in ('name', 'email'):
            widget = form.get_widget(f)
            if widget:
                setattr(self.user, f, widget.parse())
        self.user.is_admin = True
        self.user.store()


class UserPage(Directory):
    _q_exports = ['', 'edit', 'delete', 'token']

    def __init__(self, component):
        self.user = User.get(component)
        self.user_ui = UserUI(self.user)
        get_response().breadcrumb.append((component + '/', self.user.name))

    def _q_index [html] (self):
        html_top('users', '%s - %s' % (_('User'), self.user.name))
        '<h2>%s - %s</h2>' % (_('User'), self.user.name)
        '<div class="form">'
        '<div class="title">%s</div>' % _('Name')
        '<div class="StringWidget content">%s</div>' % self.user.name
        if self.user.email:
            '<div class="title">%s</div>' % _('Email')
            '<div class="StringWidget content">%s</div>' % self.user.email
#         if self.user.lasso_dump:
#             identity = lasso.Identity.newFromDump(self.user.lasso_dump)
#             server = misc.get_lasso_server()
#             if len(identity.providerIds) and server:
#                 '<h3>%s</h3>' % _('Liberty Alliance Details')
#                 '<div class="StringWidget content"><ul>'
#                 for pid in identity.providerIds:
#                     provider = server.getProvider(pid)
#                     label = misc.get_provider_label(provider)
#                     if label:
#                         label = '%s (%s)' % (label, pid)
#                     else:
#                         label = pid
#                     federation = identity.getFederation(pid)
#                     '<li>'
#                     _('Account federated with %s') % label
#                     '<br />'
#                     if federation.localNameIdentifier:
#                         _("local: ") + federation.localNameIdentifier.content
#                     if federation.remoteNameIdentifier:
#                         _("remote: ") + federation.remoteNameIdentifier.content
#                     '</li>'
#                 '</ul></div>'

#                 # XXX: only display this in debug mode:
#                 '<h4>%s</h4>' % _('Lasso Identity Dump')
#                 '<pre>%s</pre>' % self.user.lasso_dump
        '</div>'

    def debug [html] (self):
        get_response().breadcrumb.append( ('debug', _('Debug')) )
        html_top('users', 'Debug')
        "<h2>Debug - %s</h2>" % self.user.name
        "<pre>"
        self.user.lasso_dump
        "</pre>"

    def edit [html] (self):
        form = self.user_ui.form_edit()
        if form.get_widget('cancel').parse():
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append( ('edit', _('Edit')) )
            html_top('users', title = _('Edit User'))
            '<h2>%s</h2>' % _('Edit User')
            form.render()
        else:
            self.user_ui.submit_form(form)
            return redirect('..')

    def delete [html] (self):
        form = Form(enctype="multipart/form-data")
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
                        "You are about to irrevocably delete this user.")))
        form.add_submit("submit", _("Submit"))
        form.add_submit("cancel", _("Cancel"))
        if form.get_widget('cancel').parse():
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('delete', _('Delete')))
            html_top('users', title = _('Delete User'))
            '<h2>%s %s</h2>' % (_('Deleting User :'), self.user.name)
            form.render()
        else:
            self.user.remove_self()
            return redirect('..')

    def token [html] (self):
        form = Form(enctype="multipart/form-data", use_tokens = False)
        form.add_submit("submit", _("Generate"))
        form.add_submit("cancel", _("Cancel"))
        request = get_request()
        if request.form.has_key('cancel') or request.form.has_key('done'):
            return redirect('..')

        get_response().breadcrumb.append(('token', _('Identification Token')))

        if not form.is_submitted() or form.has_errors():
            html_top('users', title = _('Identification Token'))
            '<h2>%s</h2>' % _('Identification Token')
            '<p>%s</p>' % _('You are about to generate a token than can be used to federate the account.')
            '<p>%s</p>' % _('After that, you will have the choice to send it to the user by email so that he can federate his accounts.')
            if self.user.identification_token:
                '<p>%s</p>' % _('Note that user has already been issued an identification token : %s') % self.user.identification_token
            form.render()
        else:
            if request.form.has_key('submit'):
                html_top('users', title = _('Identification Token'))
                token = '-'.join(['%04d' % random.randint(1, 9999) for x in range(4)])
                self.user.identification_token = str(token)
                self.user.store()

                '<p>'
                _('Identification Token for %s') % self.user.name
                ' : %s</p>' % self.user.identification_token

                form = Form(enctype="multipart/form-data", use_tokens = False)
                form.add_submit('done', _('Done'))
                if self.user.email:
                    form.add_submit("submit-email", _("Send by email"))
                form.render()
            else:
                site_url = '%s://%s%s/token?token=%s' \
                    % (request.get_scheme(), request.get_server(),
                       get_request().environ['SCRIPT_NAME'], self.user.identification_token)
                body = _("""You have been given an identification token.

Your token is %(token)s

Click on %(url)s to use it.
""") % {'token': self.user.identification_token, 'url': site_url}
                try:
                    emails.email(_('Identification Token'), body, self.user.email)
                except errors.EmailError, e:
                    html_top('users', title = _('Identification Token'))
                    _('Failed sending email. Check your email configuration.')
                    '<div class="buttons"><a href=".."><input type="button" value="%s" /></a></div><br />' % _('Back')
                else:
                    return redirect('..')

class UsersDirectory(Directory):

    _q_exports = ['', 'new']

    def _q_index [html] (self):
        get_publisher().reload_cfg()
        get_response().breadcrumb.append( ('users/', _('Users')) )
        html_top('users', title = _('Users'))

        
        if not list(Host.select(lambda x: x.name == 'larpe')):
            '<p>%s</p>' % _('Liberty support must be setup before creating users.')
        else:
            """<ul id="nav-users-admin">
              <li><a href="new">%s</a></li>
            </ul>""" % _('New User')

        debug_cfg = get_publisher().cfg.get('debug', {})

        users = User.select(lambda x: x.name is not None, order_by = 'name')

        '<ul class="biglist">'
        for user in users:
            '<li>'
            '<strong class="label">%s</strong>' % user.name
            if user.email:
                '<p class="details">'
                user.email
                '</p>'

            '<p class="commands">'
            command_icon('%s/' % user.id, 'view')
            if not user.name_identifiers:
                if not user.identification_token:
                    command_icon('%s/token' % user.id, 'token',
                            label = _('Identification Token'), icon = 'stock_exec_16.png')
                else:
                    command_icon('%s/token' % user.id, 'token',
                            label = _('Identification Token (current: %s)') % \
                                user.identification_token,
                            icon = 'stock_exec_16.png')
            command_icon('%s/edit' % user.id, 'edit')
            command_icon('%s/delete' % user.id, 'remove')
            if debug_cfg.get('logger', False):
                command_icon('../logger/by_user/%s/' % user.id, 'logs',
                        label = _('Logs'), icon = 'stock_harddisk_16.png')
            '</p></li>'
        '</ul>'

    def new [html] (self):
        get_response().breadcrumb.append( ('users/', _('Users')) )
        get_response().breadcrumb.append( ('new', _('New')) )
        hosts = list(Host.select(lambda x: x.name == 'larpe'))
        if not hosts:
            return error_page('users', _('Liberty support must be setup before creating users.'))
        host = hosts[0]
        # XXX: user must be logged in to get here
        user_ui = UserUI(None)
        # FIXME : should be able to use User.count(). Track fake user creations.
        users = User.select(lambda x: x.name is not None)
        first_user = (len(users) == 0)
        form = user_ui.form_new()
        if form.get_widget('cancel').parse():
            return redirect('.')

        if not form.is_submitted() or form.has_errors():
            html_top('users', title = _('New User'))
            '<h2>%s</h2>' % _('New User')
            form.render()
        else:
            user_ui.submit_form(form)
            if first_user:
                req = get_request()
                if hasattr(req, str('user')) and req.user:
                    user_ui.user.name_identifiers = req.user.name_identifiers
                    user_ui.user.lasso_dump = req.user.lasso_dump
                    user_ui.user.store()
                # TODO : SAML 2.0
                get_session().set_user(user_ui.user.id, host.provider_id)
            return redirect('.')
    
    def _q_lookup(self, component):
        get_response().breadcrumb.append( ('users/', _('Users')) )
        try:
            return UserPage(component)
        except KeyError:
            raise errors.TraversalError()
