# lint-amnesty, pylint: disable=missing-module-docstring
import logging
import re

from lxml import etree
from xblock.fields import Scope, String
from xmodule.editing_module import XMLEditingDescriptor  # pylint: disable=unused-import
from xmodule.xml_module import XmlDescriptor  # pylint: disable=unused-import

from .exceptions import SerializationError

log = logging.getLogger(__name__)

PRE_TAG_REGEX = re.compile(r'<pre\b[^>]*>(?:(?=([^<]+))\1|<(?!pre\b[^>]*>))*?</pre>')


class RawMixin:
    """
    Common code between RawDescriptor and XBlocks converted from XModules.
    """
    resources_dir = None

    data = String(help="XML data for the module", default="", scope=Scope.content)

    @classmethod
    def definition_from_xml(cls, xml_object, system):  # lint-amnesty, pylint: disable=missing-function-docstring, unused-argument
        try:
            data = etree.tostring(xml_object, pretty_print=True, encoding='unicode')
            pre_tag_data = []
            for pre_tag_info in xml_object.findall('.//pre'):
                if len(pre_tag_info.findall('.//pre')) == 0:
                    pre_tag_data.append(etree.tostring(pre_tag_info))

            if pre_tag_data:
                matches = re.finditer(PRE_TAG_REGEX, data)
                for match_num, match in enumerate(matches):
                    data = re.sub(match.group(), pre_tag_data[match_num].decode(), data)
            etree.XML(data)  # it just checks if generated string is valid xml
            return {'data': data}, []
        except etree.XMLSyntaxError:
            return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')}, []

    def definition_to_xml(self, resource_fs):  # lint-amnesty, pylint: disable=unused-argument
        """
        Return an Element if we've kept the import OLX, or None otherwise.
        """
        # If there's no self.data, it means that an XBlock/XModule originally
        # existed for this data at the time of import/editing, but was later
        # uninstalled. RawDescriptor therefore never got to preserve the
        # original OLX that came in, and we have no idea how it should be
        # serialized for export. It's possible that we could do some smarter
        # fallback here and attempt to extract the data, but it's reasonable
        # and simpler to just skip this node altogether.
        if not self.data:
            log.warning(
                "Could not serialize %s: No XBlock installed for '%s' tag.",
                self.location,
                self.location.block_type,
            )
            return None

        # Normal case: Just echo back the original OLX we saved.
        try:
            return etree.fromstring(self.data)
        except etree.XMLSyntaxError as err:
            # Can't recover here, so just add some info and
            # re-raise
            lines = self.data.split('\n')
            line, offset = err.position
            msg = (
                "Unable to create xml for module {loc}. "
                "Context: '{context}'"
            ).format(
                context=lines[line - 1][offset - 40:offset + 40],
                loc=self.location,
            )
            raise SerializationError(self.location, msg)  # lint-amnesty, pylint: disable=raise-missing-from

    @classmethod
    def parse_xml_new_runtime(cls, node, runtime, keys):
        """
        Interpret the parsed XML in `node`, creating a new instance of this
        module.
        """
        # In the new/blockstore-based runtime, XModule parsing (from
        # XmlMixin) is disabled, so definition_from_xml will not be
        # called, and instead the "normal" XBlock parse_xml will be used.
        # However, it's not compatible with RawMixin, so we implement
        # support here.
        data_field_value = cls.definition_from_xml(node, None)[0]["data"]
        for child in node.getchildren():
            node.remove(child)
        # Get attributes, if any, via normal parse_xml.
        try:
            block = super().parse_xml_new_runtime(node, runtime, keys)
        except AttributeError:
            block = super().parse_xml(node, runtime, keys, id_generator=None)
        block.data = data_field_value
        return block


class EmptyDataRawMixin:
    """
    Common code between EmptyDataRawDescriptor and XBlocks converted from XModules.
    """
    resources_dir = None

    data = String(default='', scope=Scope.content)

    @classmethod
    def definition_from_xml(cls, xml_object, system):  # lint-amnesty, pylint: disable=unused-argument
        if len(xml_object) == 0 and len(list(xml_object.items())) == 0:
            return {'data': ''}, []
        return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')}, []

    def definition_to_xml(self, resource_fs):  # lint-amnesty, pylint: disable=unused-argument
        if self.data:
            return etree.fromstring(self.data)
        return etree.Element(self.category)

@@ -843,725 +843,8 @@
 ent%0A
-        try:%0A            data = etree.tostring(xml_object, pretty_print=True, encoding='unicode')%0A            pre_tag_data = %5B%5D%0A            for pre_tag_info in xml_object.findall('.//pre'):%0A                if len(pre_tag_info.findall('.//pre')) == 0:%0A                    pre_tag_data.append(etree.tostring(pre_tag_info))%0A%0A            if pre_tag_data:%0A                matches = re.finditer(PRE_TAG_REGEX, data)%0A                for match_num, match in enumerate(matches):%0A                    data = re.sub(match.group(), pre_tag_data%5Bmatch_num%5D.decode(), data)%0A            etree.XML(data)  # it just checks if generated string is valid xml%0A            return %7B'data': data%7D, %5B%5D%0A        except etree.XMLSyntaxError:%0A    
     

remove pre tag processing for course import