import logging
from pathlib import Path

from .crtdrd_layers_entry_data import CrtdrdVectorialLayerData, VecType, SourceType, PhotoSource, VectorialSource
from ..constants import CARTODRUID_CONFIG_NAME, QGIS_PLUGIN_NAME
from .xml_reader import XMLReader
from ..logger.qgis_logger_handler import QgisLoggerHandler


class CrtdrdLayersInterpreter:


    """
        Read the crtdrdLayers.xml and stores its values.
        :ivar project_xml_path: path to the crtdrdLayers.xml to read.
        :vartype project_xml_path: str
        :ivar entries: stores the <entry> labels found on the xml and it's children.
        :vartype entries: list
        :ivar logger: logger of the application.
        :vartype logger: logging.Logger
    """

    project_xml_path = None

    entries = []

    def __init__(self):
        """Constructor."""
        self.logger = QgisLoggerHandler(
            QGIS_PLUGIN_NAME,
            level=logging.INFO
        ).get_logger()

    def to_bool(self, value):
        """
        Convert value to bool. Used to  avoid mistakes when reading and saving variables
        """
        if value is None:
            return False
        return value.lower() in ("true", "1", "yes")

    def to_int(self, value):
        """
        Convert value to int. Used to  avoid mistakes when reading and saving variables
        """
        return int(value) if value not in (None, "") else None

    def source_type(self, source:str):
        """
        Returns the type of the source, depending on his label.
        """
        if source in SourceType._value2member_map_:
            return SourceType[source]
        return None


    def read_config(self):
        """
            Opens the assigned xml with self.project_xml_path and create a CrtdrdVectorialLayerData for every <entry> found and
            stores them into self.entries.
        """
        root = XMLReader.safe_parse_xml((Path(self.project_xml_path) / CARTODRUID_CONFIG_NAME).as_posix(),
                                        self.logger)
        self.entries = []
        for entry in root.iter("entry"):
            new_entry = CrtdrdVectorialLayerData()

            new_entry.layer_name = entry.findtext("string")
            data = entry.find("es.jcyl.ita.crtcyl.core.model.VectorialLayer")
            if data is None:
                data = entry.find("es.jcyl.ita.crtcyl.core.model.LinkVectorialLayer")
            if data is not None:
                new_entry.id = data.findtext("id")
                new_entry.visible_name = data.findtext("visibleName")
                new_entry.description = data.findtext("description")
                v_type = data.findtext("vectorialType")
                if v_type:
                    new_entry.vectorial_type = VecType(self.to_int(v_type))

                new_entry.showed_on_toc = self.to_bool(data.findtext("showedOnToc"))

                new_entry.order = self.to_int(data.findtext("order"))
                new_entry.z_order = self.to_int(data.findtext("zOrder"))

                new_entry.range_min = self.to_int(data.findtext("rangeMin"))
                new_entry.range_max = self.to_int(data.findtext("rangeMax"))

                new_entry.renderize_labels = self.to_bool(data.findtext("renderizeLabels"))

                new_entry.label_range_min = self.to_int(data.findtext("labelRangeMin"))
                new_entry.label_range_max = self.to_int(data.findtext("labelRangeMax"))

                new_entry.geometry_size_restriction_min = self.to_int(data.findtext("geometrySizeRestrictionMin"))
                new_entry.geometry_size_restriction_max = self.to_int(data.findtext("geometrySizeRestrictionMax"))

                new_entry.label_expression = data.findtext("labelExpression")

                new_entry.show_arrow_heads = self.to_bool(data.findtext("showArrowHeads"))

                new_entry.symb_id = data.findtext("symbId")
                new_entry.label_symb_id = data.findtext("labelSymbId")

                new_entry.symbology_expression = data.findtext("symbologyExpression")
                new_entry.label_symbology_expression = data.findtext("labelSymbologyExpression")

                new_entry.allow_overlaps = self.to_bool(data.findtext("allowOverlaps"))

                new_entry.can_change_symbology = self.to_bool(data.findtext("canChangeSymbology"))
                new_entry.can_copy = self.to_bool(data.findtext("canCopy"))
                new_entry.can_create = self.to_bool(data.findtext("canCreate"))
                new_entry.can_delete_all = self.to_bool(data.findtext("canDeleteAll"))
                new_entry.can_die_cut = self.to_bool(data.findtext("canDieCut"))
                new_entry.can_edit_vertices = self.to_bool(data.findtext("canEditVertices"))
                new_entry.can_explode = self.to_bool(data.findtext("canExplode"))
                new_entry.can_paste = self.to_bool(data.findtext("canPaste"))

                new_entry.exportable = self.to_bool(data.findtext("exportable"))
                new_entry.can_sanitize = self.to_bool(data.findtext("canSanitize"))
                new_entry.can_zoom_visibles = self.to_bool(data.findtext("canZoomVisibles"))

                new_entry.deletable = self.to_bool(data.findtext("deletable"))
                new_entry.editable = self.to_bool(data.findtext("editable"))
                new_entry.identificable = self.to_bool(data.findtext("identificable"))
                new_entry.inspectable = self.to_bool(data.findtext("inspectable"))

                new_entry.layer_editable = self.to_bool(data.findtext("layerEditable"))
                new_entry.layer_removable = self.to_bool(data.findtext("layerRemovable"))

                new_entry.selectable = self.to_bool(data.findtext("selectable"))
                new_entry.visible = self.to_bool(data.findtext("visible"))


                new_entry.alpha_edit_finisher = data.findtext("alphaEditFinisher")
                new_entry.attributes_class_name = data.findtext("attributesClassName")

                new_entry.edit_after_creation = self.to_bool(data.findtext("editAfterCreation"))
                new_entry.values_from_list = data.findtext("valuesFromList")

                new_entry.sql_identify = data.findtext("sqlIdentify")
                new_entry.sql_as_list_view = data.findtext("sqlAsListView")
                new_entry.definition_query = data.findtext("definitionQuery")

                sources = data.find("sources")
                if sources is not None:

                    source_data = sources.find(SourceType.PhotoServiceDescriptor.value)
                    if source_data is not None:
                        new_source = PhotoSource(id=source_data.findtext("id"),
                                                 class_manager=source_data.findtext("classManager"),
                                                 path=source_data.findtext("path"))
                        new_entry.source = new_source
                        new_entry.source_type = SourceType.PhotoServiceDescriptor
                    source_data = sources.find(SourceType.SpatiaLiteServiceDescriptor.value)
                    if source_data is not None:
                        new_source = VectorialSource(id=source_data.findtext("id"),
                                                     data_table=source_data.findtext("dataTable"),
                                                     db_url=source_data.findtext("dbURL"),
                                                     index_table=source_data.findtext("indexTable"))
                        new_entry.source = new_source
                        new_entry.source_type = SourceType.SpatiaLiteServiceDescriptor
                    source_data = sources.find(SourceType.SpatiaLiteQueryServiceDescriptor.value)
                    if source_data is not None:
                        new_source = VectorialSource(id=source_data.findtext("id"),
                                                     data_table=source_data.findtext("dataTable"),
                                                     db_url=source_data.findtext("dbURL"),
                                                     index_table=source_data.findtext("indexTable"))
                        new_entry.source = new_source
                        new_entry.source_type = SourceType.SpatiaLiteQueryServiceDescriptor
                    source_data = sources.find(SourceType.RepoSpatiaLiteServiceDescriptor.value)
                    if source_data is not None:
                        new_source = VectorialSource(id=source_data.findtext("id"),
                                                     data_table=source_data.findtext("dataTable"),
                                                     db_url=source_data.findtext("dbURL"),
                                                     index_table=source_data.findtext("indexTable"))
                        new_entry.source = new_source
                        new_entry.source_type = SourceType.RepoSpatiaLiteServiceDescriptor


                self.entries.append(new_entry)
