from django.contrib.admin.filterspecs import FilterSpec
from django.contrib.admin.filterspecs import RelatedFilterSpec


class FKFilterSpec(RelatedFilterSpec):
    def __init__(self, f, request, params, model, model_admin):
        filter_by_key = f.name+'_fk_filter_by'
        filter_by_val = getattr(model_admin, filter_by_key, None)
        if filter_by_val != None:
            self.fk_filter_on = True
            # we call FilterSpec constructor, not RelatedFilterSpec
            # constructor; RelatedFilterSpec constructor will try to          
            # get all the pk values on the related models, which we
            # won't need.
            FilterSpec.__init__(self, f, request, params, model, model_admin)
            filter_name_key = f.name+'_fk_filter_name'
            filter_name_val = getattr(model_admin, filter_name_key, None)
            if filter_name_val == None:
                self.lookup_title = f.verbose_name
            else:
                self.lookup_title = f.verbose_name+' '+filter_name_val
            self.lookup_kwarg = f.name+'__'+filter_by_val+'__exact'
            self.lookup_val = request.GET.get(self.lookup_kwarg, None)
            values_list = f.rel.to.objects.values_list(filter_by_val, flat=True).distinct()
            self.lookup_choices = list(values_list)
        else:
            RelatedFilterSpec.__init__(self, f, request, params, model, model_admin)
            self.fk_filter_on = False
            filter_related_key = f.name+'_fk_filter_related_only'
            filter_related_val = getattr(model_admin, filter_related_key, False)
            filter_nf_key = f.name+'_fk_filter_name_field'
            filter_nf_val = getattr(model_admin, filter_nf_key, 'pk')
            if filter_related_val:
                values_list = model_admin.queryset(request).distinct().values_list(f.name+'__pk',f.name+'__'+filter_nf_val).order_by(f.name+'__'+filter_nf_val).distinct()
                self.lookup_choices = list(values_list)


    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
               'display': _('All')}
        if self.fk_filter_on:
            for val in self.lookup_choices:
                yield {'selected': smart_unicode(val) == self.lookup_val,
                       'query_string': cl.get_query_string({self.lookup_kwarg: val}),
                       'display': val}
        else:
            for pk_val,val in self.lookup_choices:
                yield {'selected': self.lookup_val == smart_unicode(pk_val),
                       'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
                       'display': val}

FilterSpec.filter_specs.insert(0, (lambda f: bool(f.rel), FKFilterSpec))