from django.contrib.auth.models import User
from django.forms import ValidationError, MultipleChoiceField
from django.utils.translation import ugettext as _

import pyuca
from models import username, MailingList
from widgets import ForcedValueWidget, FilteredSelectMultiple

def order_choices(choices):
    '''Sort choices using Unicode collations'''
    return sorted(list(choices),
            key=lambda x: pyuca.collator.sort_key(x[1]))

def order_field_choices(field):
    '''Order choices of this field'''
    field.choices = order_choices(field.choices)

class Func2Iter(object):
    '''Transform a generator producing function into an iterator'''
    def __init__(self, func):
        self.func = func

    def __iter__(self):
        return self.func().__iter__()

class RecipientField(MultipleChoiceField):
    '''Field allowing selection among user or list for recipients'''

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        self.user_qs = kwargs.pop('user_qs', User.objects.filter())
        self.user_qs = self.user_qs.filter(is_active=True, delegations_by__isnull=True)
        self.list_qs = kwargs.pop('list_qs', MailingList.objects.active())
        kwargs.setdefault('choices', Func2Iter(self.get_recipients_choices))
        super(RecipientField, self).__init__(*args, **kwargs)

    def reset_choices(self):
        '''Reset the list of choices'''
        self._set_choices(Func2Iter(self.get_recipients_choices))

    def get_recipients_choices(self):
        '''
           Create a unique list of recipients from the list of users and the
           list of mailing-lists.
        '''
        users = self.user_qs
        if self.user:
            users = users.exclude(pk=self.user.pk)
        lists = self.list_qs
        user_choices = []
        list_choices = []
        for user in users:
            i = 'user-%s' % user.id
            name = username(user)
            user_choices.append((i, name))
        user_choices = order_choices(user_choices)
        for mailing_list in lists:
            i = 'list-%s' % mailing_list.id
            list_choices.append((i, mailing_list.name))
        list_choices = order_choices(list_choices)
        if list_choices and user_choices:
            choices = list_choices+[('', '---')]+user_choices
        else:
            choices = list_choices+user_choices
        if len(choices) == 1:
            self.widget = ForcedValueWidget(value=[choices[0][0]],
                    display_value=choices[0][1])
        else:
            self.widget = FilteredSelectMultiple(_('Recipients'), False)
        return choices

    def clean(self, value):
        '''Validate that the value is not empty.'''
        value = super(RecipientField, self).clean(value)
        if not value:
            raise ValidationError(_(u'you must set at least one user recipient or one list recipient...'))
        return value


