import random
import lasso

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

from menu import *

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

from larpe.form 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(CheckboxWidget, 'is_admin', title = _('Administrator Account'),
#                value = is_admin)
#        roles = list(Role.select())
#        if len(roles):
#            form.add(WidgetList, 'roles', title = _('Roles'), element_type = SingleSelectWidget,
#                    add_element_label = _('Add Role'),
#                    element_kwargs = {
#                        'render_br': False,
#                        'options': [(None, '---')] + [(x.id, x.name) for x in roles]})

        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(CheckboxWidget, 'is_admin', title = _('Administrator Account'),
#                value = self.user.is_admin)
#        roles = list(Role.select())
#        if len(roles):
#            form.add(WidgetList, 'roles', title = _('Roles'), element_type = SingleSelectWidget,
#                    value = self.user.roles,
#                    add_element_label = _('Add Role'),
#                    element_kwargs = {
#                        'render_br': False,
#                        'options': [(None, '---')] + [(x.id, x.name) for x in roles]})

        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.roles or self.user.is_admin:
            '<div class="title">%s</div>' % _('Roles')
            '<div class="StringWidget content"><ul>'
            if self.user.is_admin:
                '<li><strong>%s</strong></li>' % _('Site Administrator')
            for k in self.user.roles or []:
                try:
                    '<li>%s</li>' % Role.get(k).name
                except KeyError:
                    pass # removed role ?
            '</ul></div>'
        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 form.get_widget('roles').get_widget('add_element').parse():
#             form.clear_errors()
#             display_form = True
#         else:
#             display_form = (not form.is_submitted() or form.has_errors())

        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 %s

Click on %s to use it.
""") % (self.user.identification_token, site_url)
                emails.email(_('Identification Token'), body, self.user.email)
                return redirect('..')

class UsersDirectory(Directory):

    _q_exports = ['', 'new']

    def _q_index [html] (self):
        misc.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 = misc.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)
        first_user = User.count() == 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()
