import json

from django import forms

from opentech.apply.categories.models import Category


class LazyChoices:
    def __init__(self, queryset, display):
        self.queryset = queryset
        self.display = display

    def __iter__(self):
        for choice in self.queryset.values_list(*self.display):
            yield choice


class LazyWidgets:
    def __init__(self, widget, model):
        self.model = model
        self.widget = widget

    def __iter__(self):
        for obj in self.model.objects.all():
            yield self.widget(
                attrs={'id': obj.id, 'label_tag': obj.name},
                choices=LazyChoices(obj.options, ['id', 'value']),
            )


class OptionsWidget(forms.CheckboxSelectMultiple):
    template_name = 'projects/widgets/options_widget.html'
    option_template_name = 'projects/widgets/options_option.html'

    def __init__(self, *args, **kwargs):
        choices = kwargs['choices']
        super().__init__(*args, **kwargs)
        self.choices = choices


class CategoriesWidget(forms.MultiWidget):
    template_name = 'projects/widgets/categories_widget.html'

    def __init__(self, *args, **kwargs):
        kwargs['widgets'] = list()
        super().__init__(*args, **kwargs)
        self.widgets = LazyWidgets(OptionsWidget, Category)

    def decompress(self, value):
        data = json.loads(value)
        return [
            data.get(str(widget.attrs['id']), list()) for widget in self.widgets
        ]

    def value_from_datadict(self, data, files, name):
        data = {
            widget.attrs['id']: widget.value_from_datadict(data, files, name + '_%s' % i)
            for i, widget in enumerate(self.widgets)
        }
        return json.dumps(data)

    def get_context(self, *args, **kwargs):
        context = super().get_context(*args, **kwargs)
        # Mutliwidget kills the wrap_label option when it is building the context
        context['wrap_label'] = True
        return context