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.form import *


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

    def form_new(self, is_admin = False):
        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', 'is_admin', 'roles'):
            widget = form.get_widget(f)
            if widget:
                setattr(self.user, f, widget.parse())
        self.user.store()


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

    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 display_form:
            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>bla bla bla (explanation)</p>"
            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/token' % (request.get_scheme(), request.get_server())
                body = _("""You have been given an identification token.

Go to %s to use it.

Your token is %s""") % (site_url, self.user.identification_token)
                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 len(misc.cfg.get('idp', {}).items()) == 0:
            '<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(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')) )
        if len(misc.cfg.get('idp', {}).items()) == 0:
            return error_page('users',
                    _('Liberty support must be setup before creating users.'))
        # XXX: user must be logged in to get here
        user_ui = UserUI(None)
        first_user = User.count() == 0
        form = user_ui.form_new(first_user)
        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()
                user_ui.user.name_identifiers = req.user.name_identifiers
                user_ui.user.lasso_dump = req.user.lasso_dump
                user_ui.user.store()
                get_session().set_user(user_ui.user.id)
            return redirect('.')
    
    def _q_lookup(self, component):
        get_response().breadcrumb.append( ('users/', _('Users')) )
        try:
            return UserPage(component)
        except KeyError:
            raise errors.TraversalError()
