from Mapa_PU.swdl.model.swdl.forest_map_no_sf import ForestMapNoSF,CountyLayer,BasicObjectLayer,LabelsLayer,LineLayer
from Mapa_PU.swdl.model.scheme import TreeElement,TreeElementOptional
from Mapa_PU.swdl.model.tags import Tags
import lxml
from lxml.etree import XMLParser, ElementTree


class ForestMapNoSFConverter():
    """Klasa tworząca drzewo xml forestMapNoSF"""
    def __init__(self):
        pass
    
    def create_forest_map_no_sf(self,forest_map_no_sf: ForestMapNoSF):
        """Utworzenie drzewa forestMapNoSF"""
        try:
            if forest_map_no_sf is None:
                return None
            forest_map=TreeElement(Tags.FOREST_MAP_NO_SF.value)
            #dodanie warstwy oddziałów
            forest_map.append(self.create_county_layer(forest_map_no_sf.county_layer))
            #dodanie warstwy obiektów podstawowych
            forest_map.append(self.create_basic_object_layer(forest_map_no_sf.basic_objects_layer))
            #dodanie opisów pododdziałów
            forest_map.append(self.create_labels_layer(forest_map_no_sf.subarea_labels_layer,Tags.SUBAREA_LABELS_LAYER.value, Tags.SUBAREA_LABEL_GEOM.value))
            #dodanie warstwy opisów oddziałów
            forest_map.append(self.create_labels_layer(forest_map_no_sf.county_labels_layer,Tags.COUNTY_LABEL_LAYER.value, Tags.COUNT_LABEL_GEOM.value))
            #dodanie warstwy obiektów liniowych
            forest_map.append(self.create_line_layer(forest_map_no_sf.line_layer))
            return forest_map
        except Exception as e:
            raise e 
        
    def create_county_layer(self,county_layer:CountyLayer):
        """Warstwa oddziałów"""
        if len(list(county_layer))==0:
                return None
        layer=TreeElement(Tags.COUNTY_LAYER.value)
        for cl in county_layer:
            countyGeom=TreeElement(Tags.COUNTY_GEOM.value)
            geometry=self.create_geometry_gml(cl.geometry)
            address=TreeElement(Tags.ADRESS_FOREST.value,cl.address_forest)
            countyGeom.append(geometry)
            countyGeom.append(address)
            layer.append(countyGeom)
        return layer
        
    def create_basic_object_layer(self,basic_object:BasicObjectLayer):
        """Tworzy drzewo obiektów podstawowych"""
        try:
            if len(list(basic_object))==0:
                return None
            layer=TreeElement(Tags.BASIC_OBJECTS_LAYER.value)
            for obj in basic_object:
                basic_object_geom=TreeElement(Tags.BASIC_OBJECT_GEOM.value)
                address=TreeElement(Tags.ADRESS_FOREST.value,obj.address_forest)
                basic_object_geom.append(address)
                parcel_nr=TreeElement(Tags.PARCEL_NR.value,obj.parcel_nr)
                basic_object_geom.append(parcel_nr)
                geometry=self.create_geometry_gml(obj.geometry)
                basic_object_geom.append(geometry)
                area_use_dic_count_num=TreeElement(Tags.AREA_USE_DIC_CONT_NUM.value,obj.area_use_dic_count_num)
                basic_object_geom.append(area_use_dic_count_num)
                layer.append(basic_object_geom)
            return layer
        except Exception as e:
            raise e
        
    def create_labels_layer(self,labels:LabelsLayer,layer_name:str,label_name:str):
        """Warstwa opisów """
        try:
            if len(list(labels))==0:
                return None
            labels_layer=TreeElement(layer_name)
            for label in labels:
                label_geom=TreeElement(label_name)
                address=TreeElement(Tags.ADRESS_FOREST.value,label.address_forest)
                label_geom.append(address)
                geometry=self.create_geometry_gml(label.geometry)
                label_geom.append(geometry)
                labels_layer.append(label_geom)
            return labels_layer
        except Exception as e:
            raise e
        
    def create_line_layer(self,line_layer:LineLayer):
        """Warstwa obiektów liniowych"""
        try:
            if len(list(line_layer))==0:
                return None
            layer=TreeElement(Tags.LINE_LAYER.value)
            for line in line_layer:
                line_geom=TreeElement(Tags.LINE_GEOM.value)
                width=TreeElement(Tags.WIDTH.value,line.width)
                line_geom.append(width)
                area_type_cd=TreeElement(Tags.AREA_TYPE_CD_LINE.value,line.type_cd)
                line_geom.append(area_type_cd)
                geometry=self.create_geometry_gml(line.geometry)
                line_geom.append(geometry)
                layer.append(line_geom)
            return layer
        except Exception as e:
            raise e
        
    def convert_string_to_tree(self,string):
        """Konweruje text na drzewo xml
        :param string; text
        """
        try:
            parser = XMLParser(recover=True)
            tree = ElementTree(lxml.etree.fromstring(string, parser=parser)) 
            return tree.getroot()
        except Exception as e:
            raise e
        
    def create_geometry_gml(self,value):
        """Zwraca obiekt tag Geometry z wpisana geometrią"""
        try:
            if len(value)>0:
                geometry=TreeElement(Tags.GEOMETRY.value)
                geometry.append(self.convert_string_to_tree(''.join(value)))
                return geometry
        except Exception as e:
            raise e