from __future__ import unicode_literals
# created by Edgar Gabaldi https://github.com/edgabaldi
# and Fabio C. Barrionuevo da Luz https://github.com/luzfcb


from django.utils import six
from django.utils.encoding import force_str

__all__ = (
    'ReadOnlyFieldsMixin',
    'new_readonly_form_class'
)


class ReadOnlyFieldsMixin(object):
    """Usage:
    
    class MyFormAllFieldsReadOnly(ReadOnlyFieldsMixin, forms.Form):
        ...
        
        
    class MyFormSelectedFieldsReadOnly(ReadOnlyFieldsMixin, forms.Form):
        readonly_fields = ('field1', 'field2')
        ...
    """
    readonly_fields = ()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        self.define_readonly_fields(self.fields)

    def clean(self):
        cleaned_data = super(ReadOnlyFieldsMixin, self).clean()

        for field_name, field in six.iteritems(self.fields):
            if self._must_be_readonly(field_name):
                cleaned_data[field_name] = getattr(self.instance, field_name)

        return cleaned_data

    def define_readonly_fields(self, field_list):

        fields = [field for field_name, field in six.iteritems(field_list)
                  if self._must_be_readonly(field_name)]

        map(lambda field: self._set_readonly(field), fields)

    def _all_fields(self):
        return not bool(self.readonly_fields)

    def _set_readonly(self, field):
        field.widget.attrs['disabled'] = 'true'
        field.required = False

    def _must_be_readonly(self, field_name):
        return field_name in self.readonly_fields or self._all_fields()


def new_readonly_form_class(form_class, readonly_fields=()):
    name = force_str("ReadOnly{}".format(form_class.__name__))
    class_fields = {'readonly_fields': readonly_fields}
    return type(name, (ReadOnlyFieldsMixin, form_class), class_fields)
