from django.utils.html import format_html
from django.contrib import admin
from django import forms
from django.forms.util import flatatt
from django.utils.translation import ugettext as _

from .models import (
    MailDomain,
    Mailbox,
    MailAddress
)

PASSWORD_MISMATCH_ERROR = _("Passwords don't match")


class ReadOnlyPasswordHashWidget(forms.Widget):
    def render(self, name, value, attrs):
        final_attrs = self.build_attrs(attrs)
        summary = format_html("<strong>{0}</strong>: {1} ",
                              _('Hash'), value)
        return format_html("<div{0}>{1}</div>", flatatt(final_attrs), summary)


class ReadOnlyPasswordHashField(forms.Field):
    widget = ReadOnlyPasswordHashWidget

    def __init__(self, *args, **kwargs):
        kwargs.setdefault("required", False)
        super(ReadOnlyPasswordHashField, self).__init__(*args, **kwargs)

    def bound_data(self, data, initial):
        return initial

    def _has_changed(self, initial, data):
        return False


class MailboxCreationForm(forms.ModelForm):
    """
    A form for creating mailboxes.

    """
    password1 = forms.CharField(label=_('Password'),
                                widget=forms.PasswordInput)
    password2 = forms.CharField(label=_('Password (again)'),
                                widget=forms.PasswordInput)

    class Meta:
        model = Mailbox
        fields = ('username', 'domain')

    def clean_password2(self):
        """
        Check that the two password entries match.

        """
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(PASSWORD_MISMATCH_ERROR)
        return password2

    def save(self, commit=True):
        """
        Save the provided password in hashed format.

        """
        mailbox = super(MailboxCreationForm, self).save(commit=False)
        mailbox.set_password(self.cleaned_data['password1'])
        mailbox.uid = 0
        mailbox.gid = 0
        if commit:
            mailbox.save()
        return mailbox


class MailboxChangeForm(forms.ModelForm):
    """
    A form for updating mailboxes.

    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = Mailbox
        fields = ('username', 'domain', 'password', 'home', 'uid', 'gid',
                  'active')

    def clean_password(self):
        return self.initial['password']


class MailboxAdmin(admin.ModelAdmin):
    """
    Custom admin page for mailboxes.

    """
    form = MailboxChangeForm
    add_form = MailboxCreationForm

    list_display = ('username', 'domain', 'active')
    list_filter = ('active',)
    fieldsets = (
        (None, {
            'fields': ('username', 'domain', 'password', 'active')}),
        (_('System'), {
            'fields': ('home', 'uid', 'gid')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'domain', 'password1', 'password2')}),
    )
    search_fields = ('username', 'domain')
    ordering = ('username', 'domain')
    filter_horizontal = ()

    def get_fieldsets(self, request, obj=None):
        if not obj:
            return self.add_fieldsets
        return super(MailboxAdmin, self).get_fieldsets(request, obj)

    def get_form(self, request, obj=None, **kwargs):
        """
        Use special form during mailbox creation.

        """
        defaults = {}
        if obj is None:
            defaults.update({
                'form': self.add_form,
                'fields': admin.util.flatten_fieldsets(self.add_fieldsets),
            })
        defaults.update(kwargs)
        return super(MailboxAdmin, self).get_form(request, obj, **defaults)


admin.site.register(MailDomain)
admin.site.register(Mailbox, MailboxAdmin)
admin.site.register(MailAddress)