from xml.etree import ElementTree as ET

from django.forms.models import modelform_factory

from staff.oebs.controllers.datasources.oebs_datasource import OEBSDatasource
from staff.oebs.exceptions import OEBSResponseError, OEBSSchemaError


class XmlDatasource(OEBSDatasource):
    def _deserialize_data(self, data):
        root = ET.fromstring(data)

        if root.tag == 'ROWSET':
            return self._iterate_rows(root)

        if root.tag == 'Error':
            exception = self.wrap_in_exception(root)
            raise exception

        raise OEBSResponseError(data.decode('utf-8'))

    def _iterate_rows(self, root):
        from staff.oebs.models import library
        model = library[self.object_type]
        form_class = modelform_factory(model, fields='__all__')
        for row in root:
            raw_dict = {}
            for field in row:
                raw_dict[field.tag.lower()] = field.text
                for nested in field.getchildren():
                    raw_dict[nested.tag.lower()] = nested.text
            yield self.clean(raw_dict, form_class)

    def clean(self, raw_dict, form_class):
        form = form_class(raw_dict)
        if form.is_valid():
            return form.cleaned_data
        else:
            raise OEBSSchemaError(repr(form.errors))

    def wrap_in_exception(self, root):
        msg = root.findall('./Desc/US')[0].text
        return OEBSResponseError(msg)
