# -*- coding: utf-8 -*-
"""Moduł pomocniczy tworzacy obiekty Xml subareaData
"""
from Mapa_PU.swdl.model.scheme import TreeElement,TreeElementOptional
from Mapa_PU.swdl.model.tags import Tags
from Mapa_PU.swdl.model.swdl.subarea_data import SubareaData,LandUseMeasure
import lxml
from lxml.etree import XMLParser, ElementTree

"""klasa pomocnicza tworzaca drzewo subareaData XML
"""
class SubareaDataConverter():
    
    def create_subarea_data(self,subarea_data):
        """tworzenie drzewa subareaData
        :param subarea_data; obiekt Subarea
        """
        try:
            subarea=TreeElement(Tags.SUBAREA_DATA.value)
            subarea.append(TreeElement(Tags.ADRESS_FOREST.value,subarea_data.address_forest))
            subarea.append(TreeElementOptional.create(Tags.ACCORD_CD.value,subarea_data.accord_cd))
            subarea.append(TreeElementOptional.create(Tags.DAMAGE_DEGREE.value,subarea_data.damage_degree))
            subarea.append(TreeElementOptional.create(Tags.CAUSE_CD.value,subarea_data.cause_cd))
            subarea.append(TreeElementOptional.create(Tags.AREA_TYPE_CD.value,subarea_data.area_type_cd))
            subarea.append(TreeElementOptional.create(Tags.POSITION_CD.value,subarea_data.position_cd))
            subarea.append(TreeElementOptional.create(Tags.RELIEF_CD.value,subarea_data.relief_cd))
            subarea.append(TreeElementOptional.create(Tags.SITE_TYPE_CD.value,subarea_data.site_type_cd))
            subarea.append(TreeElementOptional.create(Tags.DEGRADATION_CD.value,subarea_data.degradation_cd))
            subarea.append(TreeElementOptional.create(Tags.VEG_COVER_CD.value,subarea_data.veg_cover_cd))
            subarea.append(TreeElementOptional.create(Tags.SILVICULTURE_CD.value,subarea_data.silviculture_cd))
            subarea.append(TreeElementOptional.create(Tags.FOREST_FUNC_CD.value,subarea_data.forest_func_cd))
            subarea.append(TreeElementOptional.create(Tags.STAND_STRUCT_CD.value,subarea_data.stand_struct_cd))
            subarea.append(TreeElementOptional.create(Tags.SLOPE_CD.value,subarea_data.slope_cd))
            subarea.append(TreeElementOptional.create(Tags.EXPOSURE_CD.value,subarea_data.exposure_cd))
            subarea.append(TreeElementOptional.create(Tags.MOISTURE_CD.value,subarea_data.moisture_cd))
            subarea.append(TreeElementOptional.create(Tags.SOIL_PEC_CD.value,subarea_data.soil_pec_cd))
            subarea.append(TreeElementOptional.create(Tags.SOIL_SUB_TYPE_CD.value,subarea_data.soil_sub_type_cd))
            subarea.append(TreeElementOptional.create(Tags.PLANT_COMM_CD.value,subarea_data.plant_comm_cd))
            subarea.append(TreeElementOptional.create(Tags.ROTATION_AGE.value,subarea_data.rotation_age))
            subarea.append(TreeElement(Tags.SUB_AREA.value,subarea_data.subarea))
            subarea.append(TreeElementOptional.create(Tags.RECONSTR_PERIOD.value,subarea_data.reconstr_period))
            subarea.append(TreeElementOptional.create(Tags.SUBAREA_INFO.value,subarea_data.subarea_info))
            subarea.append(TreeElementOptional.create(Tags.ALTITUDE_MAX.value,subarea_data.altitude_max))
            subarea.append(TreeElementOptional.create(Tags.ALTITUDE_MIN.value,subarea_data.altitude_min))
            subarea.append(TreeElementOptional.create(Tags.SEED_BASE_NR.value,subarea_data.seed_base_nr))
            subarea.append(TreeElementOptional.create(Tags.CONTROL_UNIT_CD.value,subarea_data.seed_base_nr))
            subarea.append(TreeElementOptional.create(Tags.RECONSTR_CD.value,subarea_data.reconstr_cd))
            subarea.append(TreeElementOptional.create(Tags.PHASE_CD.value,subarea_data.phase_cd))
            
            #obiekty damages
            if len(subarea_data.damages_list)>0:
                damages=TreeElement(Tags.DAMAGES.value)
                for damage in subarea_data.damages_list:
                    damages.append(self.create_damages(damage))
                subarea.append(damages)
            
            #obiekty random_samples
            if len(subarea_data.random_samples)>0:
                samples=TreeElement(Tags.RANDOM_SAMPLES.value)
                for sample in subarea_data.random_samples:
                    samples.append(self.create_random_sample(sample))
                subarea.append(samples)
            
            #obiekty arod_stand_pecs
            if len(subarea_data.arod_stand_pecs)>0:
                arod_stand_pec=TreeElement(Tags.AROD_STAND_PEC.value)
                for stand_pec in subarea_data.arod_stand_pecs:
                    arod_stand_pec.append(self.create_arod_stand_pec(stand_pec))
                subarea.append(arod_stand_pec)
            
            #obiekty ArodCategories
            if len(subarea_data.arod_categories) >0:
                arod_cat=TreeElement(Tags.AROD_CATEGORIES.value)
                for category in subarea_data.arod_categories:
                    arod_cat.append(self.create_arod_category(category))
                subarea.append(arod_cat)

            #obiekty ArodCue
            if len(subarea_data.arod_cues)>0:
                arod_cues=TreeElement(Tags.AROD_CUE.value)
                for cue in subarea_data.arod_cues:
                    arod_cues.append(self.create_cue(cue))
                subarea.append(arod_cues)
 
            #obiekty done_measures
            if len(subarea_data.done_measures)>0:
                done_measures=TreeElement(Tags.DONE_MEASURES.value)
                for measure in subarea_data.done_measures:
                    done_measures.append(self.create_done_measure(measure))
                subarea.append(done_measures)
 
            #obiekty ArodGoal
            if len(subarea_data.arod_goals)>0:
                goals=TreeElement(Tags.AROD_GOAL.value)
                for goal in subarea_data.arod_goals:
                    goals.append(self.create_goal(goal))
                subarea.append(goals)
            
            #obiekty ArodPhenomena
            if len(subarea_data.arod_phenomenas)>0:
                phenomenas=TreeElement(Tags.AROD_PHENOMENA.value)
                for phenomena in subarea_data.arod_phenomenas:
                    phenomenas.append(self.create_phenomena(phenomena))
                subarea.append(phenomenas)
            
            #obiekty ArodProtSites
            if len(subarea_data.arod_prot_sites)>0:
                prot_sites=TreeElement(Tags.AROD_PROT_SITE.value)
                for ps in subarea_data.arod_prot_sites:
                    prot_sites.append(self.create_prot_site(ps))
                subarea.append(prot_sites)
            
            #obiekty ArodSoilSpecs
            if len(subarea_data.arod_soil_specs)>0:
                soil_specs=TreeElement(Tags.AROD_SOIL_SPEC.value)
                for soil in subarea_data.arod_soil_specs:
                    soil_specs.append(self.create_soil_spec(soil)) 
                subarea.append(soil_specs)
            
            #obiekty ArodSpecArea
            if len(subarea_data.arod_spec_areas)>0:
                spec_areas=TreeElement(Tags.AROD_SPEC_AREA.value)
                for asa in subarea_data.arod_spec_areas:
                    spec_areas.append(self.create_spec_area(asa))
                subarea.append(spec_areas)
            
            #obiekty TreeLayers
            if len(subarea_data.tree_layers)>0:
                layers=TreeElement(Tags.TREE_LAYERS.value)
                for layer in subarea_data.tree_layers:
                    layers.append(self.create_tree_layer(layer))
                subarea.append(layers)
            
            #obiekty Parcels
            if len(subarea_data.subarea_parcels)>0:
                parcels=TreeElement(Tags.SUBAREA_PARCELS.value)
                for parcel in subarea_data.subarea_parcels:
                    parcels.append(self.create_parcel(parcel))
                subarea.append(parcels)
            
            #obiekt subarea_ownership_structure
            if len(subarea_data.subarea_ownership_structure)>0:
                ownership_structure=TreeElement(Tags.SUBAREA_OWNERSHIP_STRUCTURE.value)
                for ownershipShare in subarea_data.subarea_ownership_structure:
                    ownership_structure.append(self.create_ownership_share(ownershipShare))
                subarea.append(ownership_structure)
                
            #obiekty protectAreas obszary chronione
            if len(subarea_data.protect_areas)>0:
                protect_areas=TreeElement(Tags.PROTECT_AREAS.value)
                for pa in subarea_data.protect_areas:
                    protect_area=TreeElement(Tags.PROTECT_AREA.value)
                    protect_area.append(TreeElement(Tags.PROTECT_AREA_CD.value,pa.protect_area_cd))
                    protect_area.append(TreeElement(Tags.PROTECT_AREA_NAME.value,pa.protect_area_name))
                    protect_areas.append(protect_area)
                subarea.append(protect_areas)
                
            #geometria
            if len(subarea_data.geometry)>0:
                geometry=TreeElement(Tags.GEOMETRY.value)
                geo=[''.join(gml) for gml in subarea_data.geometry]
                geometry.append(self.convert_string_to_tree(geo[0]))
                subarea.append(geometry)
           
            return subarea
        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_parcel(self,parcel):
        """Działaka ewidencyjna
        :param parcel; obiekt działki
        """
        try:
            subarea_parcel=TreeElement(Tags.SUBAREA_PARCEL.value)
            subarea_parcel.append(TreeElement(Tags.PARCEL_NR.value,parcel.parcel_nr))
            subarea_parcel.append(TreeElement(Tags.COUNTY_CD.value,parcel.county_cd))
            subarea_parcel.append(TreeElement(Tags.DISTRICT_CD.value,parcel.district_cd))
            subarea_parcel.append(TreeElement(Tags.MUNICIPALITY_CD.value,parcel.municipality_cd))
            subarea_parcel.append(TreeElement(Tags.COMMUNITY_CD.value,parcel.community_cd))
            subarea_parcel.append(TreeElementOptional.create(Tags.OWNERSHIP_CD.value,parcel.ownership_cd))
            subarea_parcel.append(TreeElement(Tags.PARCEL_AREA.value,parcel.parcel_area))
            subarea_parcel.append(TreeElementOptional.create(Tags.REG_SHEET_NR2.value,parcel.regSheetNr2))
            parcels_land_use=TreeElement(Tags.PARCELS_LAND_USE.value)
            for p in parcel.parcels_land_use:
                parcel_land_use=TreeElement(Tags.PARCEL_LAND_USE.value)
                parcel_land_use.append(TreeElement(Tags.AREA_USE_DIC.value,p.area_use_dic))
                parcel_land_use.append(TreeElement(Tags.SOIL_QUALITY_DIC.value,p.soil_quality_dic))
                parcel_land_use.append(TreeElement(Tags.LAND_USE_AREA.value,p.land_use_area))
                parcel_land_use.append(TreeElement(Tags.AROD_LAND_USE_AREA.value,p.arod_land_use_area))
                if p.geometry is not None:
                    geometry=TreeElement(Tags.GEOMETRY.value)
                    geometry.append(self.convert_string_to_tree(''.join(p.geometry)))
                    parcel_land_use.append(geometry)
                parcel_land_use.append(TreeElement(Tags.FOR_AFFORESTATION.value,p.for_afforestation))
                #Zabie gospodarcze
                parcel_land_use.append(self.create_land_use_measures(p.land_use_measures))
                parcel_land_use.append(TreeElement(Tags.SHAPE_NR.value,p.shape_nr))
                
                parcels_land_use.append(parcel_land_use)
            subarea_parcel.append(parcels_land_use)
            if parcel.geometry is not None:
                geometry=TreeElement(Tags.GEOMETRY.value)
                geometry.append(self.convert_string_to_tree(''.join(parcel.geometry)))
                subarea_parcel.append(geometry)
            return subarea_parcel
        except Exception as e:
            raise e
            
    
    def create_tree_layer(self,layer):
        """Warstwa drzewostanu
        :param layer; warstwa
        """
        try:
            l=TreeElement(Tags.TREE_LAYER.value)
            l.append(TreeElement(Tags.STOREY_CD.value,layer.storey_cd))
            l.append(TreeElement(Tags.STOREY_RANK_ORDER.value,layer.storey_rank_order))
            l.append(TreeElementOptional.create(Tags.STAND_DENSITY_INDEX.value,layer.stand_density_index))
            l.append(TreeElementOptional.create(Tags.MIXTURE_CD.value,layer.mixture_cd))
            l.append(TreeElementOptional.create(Tags.DENSITY_CD.value,layer.density_cd))
            l.append(TreeElementOptional.create(Tags.LOCATION_CD.value,layer.location_cd))
            l.append(TreeElementOptional.create(Tags.TREE_STOCK_CD.value,layer.tree_stock_cd))
            l.append(TreeElementOptional.create(Tags.SILV_QUALITY_CD.value,layer.silv_quality_cd))
            if layer.layer_species is not None:
                layer_species=TreeElement(Tags.LAYER_SPECIES.value)
                for tree in layer.layer_species:
                    tree_species=TreeElement(Tags.TREE_SPECIES.value)
                    tree_species.append(TreeElement(Tags.SPECIES_CD.value,tree.species_cd))
                    tree_species.append(TreeElement(Tags.SPECIES_RANK_ORDER.value,tree.species_rank_order))
                    tree_species.append(TreeElementOptional.create(Tags.PART_CD.value,tree.part_cd))
                    tree_species.append(TreeElementOptional.create(Tags.SPECIES_AGE.value,tree.species_age))
                    tree_species.append(TreeElementOptional.create(Tags.DBH.value,tree.dbh))
                    tree_species.append(TreeElementOptional.create(Tags.HEIGHT.value,tree.height))
                    tree_species.append(TreeElementOptional.create(Tags.VOLUME.value,tree.volume))
                    tree_species.append(TreeElementOptional.create(Tags.VOLUME_HA.value,tree.volume_ha))
                    tree_species.append(TreeElementOptional.create(Tags.INCREMENT.value,tree.increment))
                    tree_species.append(TreeElementOptional.create(Tags.INCREMENT_HA.value,tree.increment_ha))
                    tree_species.append(TreeElementOptional.create(Tags.TECH_QUALITY_CD.value,tree.tech_quality_cd))
                    tree_species.append(TreeElementOptional.create(Tags.SITE_CLASS_CD.value,tree.site_class_cd))
                    layer_species.append(tree_species)
                l.append(layer_species)
            return l
        except Exception as e:
            raise e
    
    def create_soil_spec(self,soil):
        """Gatunek gleby
        :param soil; gatunek gleby
        """
        try:
            soil=TreeElement(Tags.SOIL_SPEC.value)
            soil.append(TreeElement(Tags.SOIL_SPECIES_CD.value,soil.soil_species_cd))
            soil.append(TreeElement(Tags.SOIL_SPEC_RANK_ORDER.value,soil.soil_rank_order))
            soil.append(TreeElement(Tags.SOIL_LEVEL_DIC_CD.value,soil.soil_level_dic_cd))
        except Exception as e:
            raise e
    
    def create_phenomena(self,phenomena):
        """Osobliwoś przyrodnicza
        :param phenomena; Osobliwośc
        """
        try:
            ph=TreeElement(Tags.PHENOMENA.value)
            ph.append(TreeElement(Tags.PHENOMENA_CD.value,phenomena.phenomena_cd))
            ph.append(TreeElementOptional.create(Tags.LOCATION_CD.value,phenomena.location_cd))
            ph.append(TreeElementOptional.create(Tags.SPECIES_CD.value,phenomena.species_cd))
            ph.append(TreeElementOptional.create(Tags.PLANT_CD.value,phenomena.plant_cd))
            ph.append(TreeElementOptional.create(Tags.PHEN_NUM.value,phenomena.phen_num))
            ph.append(TreeElementOptional.create(Tags.PHEN_AREA.value,phenomena.phen_area))
            ph.append(TreeElementOptional.create(Tags.NATURE_MON_FL.value,phenomena.nature_mon_fl))
            
            if phenomena.geometry is not None:
                geo=[''.join(gml) for gml in phenomena.geometry]
                geometry=TreeElement(Tags.GEOMETRY.value)
                geometry.append(self.convert_string_to_tree(geo[0]))
                ph.append(geometry)
            
            return ph
        except Exception as e:
            raise e
    
    def create_cue(self,cue):
        """Wskazówka gospodarcza
        :param cue; wskazówka
        """
        try:
            arod_cue=TreeElement(Tags.CUE.value)
            arod_cue.append(TreeElement(Tags.SITE_NR.value,cue.site_nr))
            arod_cue.append(TreeElement(Tags.MEASURE_CD.value,cue.measure_cd))
            arod_cue.append(TreeElementOptional.create(Tags.URGENCY.value,cue.urgency))
            arod_cue.append(TreeElementOptional.create(Tags.CUTTING_NR.value,cue.cutting_nr))
            arod_cue.append(TreeElementOptional.create(Tags.CUTTING_AREA.value,cue.cutting_area))
            arod_cue.append(TreeElementOptional.create(Tags.LARGE_TIMBER_PERC.value,cue.large_timber_perc))
            arod_cue.append(TreeElementOptional.create(Tags.LARGE_TIMBER.value,cue.large_timber))
            arod_cue.append(TreeElementOptional.create(Tags.LARGE_TIMBER_NETTO.value,cue.large_timber_netto))
            arod_cue.append(TreeElementOptional.create(Tags.CUE_RANK_ORDER.value,cue.cue_rank_order))
            return arod_cue
        except Exception as e:
            raise e
    
    def create_arod_category(self,category):
        """Kategoria ochronności
        :param category; kategoria
        """
        try:
            arod_category=TreeElement(Tags.AROD_CATEGORY.value)
            arod_category.append(TreeElement(Tags.CATEGORY_CD.value,category.category_cd))
            arod_category.append(TreeElement(Tags.CATEGORY_RANK_ORDER.value,category.category_rank_order))
            return arod_category
        except Exception as e:
            raise e
        
    def create_arod_stand_pec(self,stand_pec):
        """Cecha drzewostanu
        :param stand_pec; obiekt cechy drzewostanu
        """
        try:
            return TreeElement(Tags.FOREST_PEC_DIC.value,stand_pec.forest_pec_cd)
        except Exception as e:
            raise e
    
    def create_spec_area(self,asa):
        """Powierzchnia nie stanowiąca wydzielenia
        :param asa; powierzchnia nie stanowiąca wydzielenia
        """
        try:
            spec_area=TreeElement(Tags.SPEC_AREA.value)
            spec_area.append(TreeElementOptional.create(Tags.SPECIAL_AREA_CD.value,asa.special_area_cd))
            spec_area.append(TreeElementOptional.create(Tags.LOCATION_CD.value,asa.location_cd))
            spec_area.append(TreeElementOptional.create(Tags.SPECIAL_AREA.value,asa.special_area))
            spec_area.append(TreeElementOptional.create(Tags.SPECIAL_AREA_YEAR.value,asa.special_area_year))
            spec_area.append(TreeElementOptional.create(Tags.SPECIAL_AREA_NUM.value,asa.special_area_num))
            if len(asa.species_spec_areas)>0:
                for sp in asa.species_spec_areas:
                    species=TreeElement(Tags.SPECIES_SPEC_AREA.value)
                    species.append(TreeElement(Tags.SPECIES_CD.value,sp.species_cd))
                    species.append(TreeElement(Tags.SPECIES_AGE.value,sp.species_age))
                    spec_area.append(species)
            spec_area.append(TreeElement(Tags.COUNTY_CD.value,asa.county_cd))
            spec_area.append(TreeElement(Tags.DISTRICT_CD.value,asa.district_cd))
            spec_area.append(TreeElement(Tags.MUNICIPALITY_CD.value,asa.municipality_cd))
            spec_area.append(TreeElement(Tags.COMMUNITY_CD.value,asa.community_cd))
            spec_area.append(TreeElement(Tags.PARCEL_NR.value,asa.parcel_nr))
            #geometria
            geometries=TreeElement(Tags.GEOMETRIES.value)
            if len(asa.geometry)>0:
                for g in asa.geometry:
                    geometry=TreeElement(Tags.GEOMETRY.value)
                    geometry.append(self.convert_string_to_tree(''.join(g)))
                    geometries.append(geometry)
            spec_area.append(geometries)
            spec_area.append(TreeElement(Tags.SPAREA_ORDER.value,asa.sparea_order))
            return spec_area
        except Exception as e:
            raise e
    
    def create_goal(self,goal):
        """Gospodarczy typ drzewostanu
        :param goal; gospodarczy typ drzewostanu
        """
        try:
            goal_xml=TreeElement(Tags.GOAL.value)
            goal_xml.append(TreeElement(Tags.GOAL_TYPE_FL.value,goal.goal_type_fl))
            goal_xml.append(TreeElement(Tags.GOAL_RANK_ORDER.value,goal.goal_rank_order))
            goal_xml.append(TreeElement(Tags.SPECIES_CD.value,goal.species_cd))
            goal_xml.append(TreeElementOptional.create(Tags.GOAL_SPECIES_PERC.value,goal.goal_species_perc))
            return goal_xml
        except Exception as e:
            raise e
    
    def create_prot_site(self,ps):
        """Siedlisko przyrodnicze
        :param ps; ProtSite
        """
        try:
            prot_site=TreeElement(Tags.PROT_SITE.value)
            #TODO do implementacji po wyjasnieniu skąd brac obiekty z bazy
            return prot_site
        except Exception as e:
            raise e
        
    def create_damages(self,damage):
        """tworzenie drzewa szkód
        :param damages_list; obiekt szkody
        """
        try:
            #TODO do implementacji po wyjasnieniu skąd brac obiekty z bazy
            return None
        except Exception as e:
            raise e
        
    def create_done_measure(self,measure):
        """tworzy drzewo zabiegów
        :param measure; obiekt zabiegu
        """
        try:
           #TODO do implementacji po wyjasnieniu skąd brac obiekty z bazy
           return None
        except Exception as e:
            raise e
        
    def create_random_sample(self,sample):
        """tworzy drzewo powierzchni prubnej
        :param sample; powierzchnia
        """
        try:
            #TODO do implementacji po wyjasnieniu skąd brac obiekty z bazy
            return None
        except Exception as e:
            raise e 
        
    def create_ownership_share(self,ownership_share):
        """Pojedyńcza własnośc dla wydzielenia
        :param  ownership_share; własnośc
        """
        try:
            #TODO do implementacji po wyjasnieniu skąd brac obiekty z bazy
            oss=TreeElement(Tags.OWNERSHIP_SHARE.value)
            oss.append(TreeElement(Tags.OWNERSHIP_CATEGORY_GUS.value,ownership_share.ownership_category_gus))
            oss.append(TreeElement(Tags.SHARE.value,ownership_share.share))
            oss.append(TreeElement(Tags.SHARE_AREA.value,ownership_share.share_area))
            return oss
        except Exception as e:
            raise e
        
    def create_land_use_measures(self,land_use_measures:[]):
        """Zwraca obiekt drzewa zabiegów gospodarczych"""
        try:
            if len(land_use_measures)==0:
                return None
            measures=TreeElement(Tags.LAND_USE_MEASURES.value)
            for m in land_use_measures:
                measure=TreeElement(Tags.LAND_USE_MEASURE.value)
                measure_cd=TreeElement(Tags.MEASURE_CD.value,m.measure_cd)
                measure.append(measure_cd)
                large_timber=TreeElement(Tags.LARGE_TIMBER.value,m.large_timber)
                measure.append(large_timber)
                large_timber_netto=TreeElement(Tags.LARGE_TIMBER_NETTO.value,m.large_timber_netto)
                measure.append(large_timber_netto)
                cue_area_div=TreeElement(Tags.CUE_AREA_DIV.value,m.cue_area_div)
                measure.append(cue_area_div)
                cue_rank_order=TreeElement(Tags.CUE_RANK_ORDER.value,m.cue_rank_order)
                measure.append(cue_rank_order)
                measures.append(measure)
            return measures
        except Exception as e:
            raise e
        
    def create_geometry_gml(self,value):
        """Zwraca obiekt tag Geometry z wpisana geometrią"""
        try:
            if value is not None and len(value)>0:
                geometry=TreeElement(Tags.GEOMETRY.value)
                geo=[''.join(gml) for gml in value]
                geometry.append(self.convert_string_to_tree(geo[0]))
                return geometry
        except Exception as e:
            raise e