from osgeo import ogr, osr

from rosreestrXml.ui.tools.KPT.cadastral_plan_territory.add_tool import RecordInfoDate

def getBObject(tagB_object):
    result=[]
    result.append({'name':'реестровый_номер','value':tagB_object.reg_numb_border})
    result.append({'name': 'код_границы', 'value': tagB_object.type_boundary.code})
    result.append({'name': 'тип_границы', 'value': tagB_object.type_boundary.value})

    return result
class ZoneContourPoints:
    def __init__(self,tagOrdinate,reversXY=False):
        self.__xmlTag=tagOrdinate
        self.__prepare(reversXY)
    def __prepare(self,reversXY):
        if reversXY :
            self.__x = self.__xmlTag.y
            self.__y = self.__xmlTag.x
        else:

            self.__x=self.__xmlTag.x
            self.__y=self.__xmlTag.y
    @property
    def pointXY(self):
        return float(self.__x),float(self.__y)
class ZoneContour:
    def __init__(self,xmlTagContour,reverseXY=False):
        self.__xmlObj=xmlTagContour
        self.__reverseXY=reverseXY
        self.__objPoints=None
        self.__prepare()
    def __prepare(self):
        objSpatial=None
        try:
            objSpatial=self.__xmlObj.entity_spatial.spatials_elements.spatial_element[0].ordinates
        except:
            pass
        if objSpatial is None:
            return
        self.__objPoints=[]
        for point in objSpatial.ordinate:
            self.__objPoints.append(ZoneContourPoints(point,self.__reverseXY))
    @property
    def Geometry(self):
        geometry = ogr.Geometry(ogr.wkbLinearRing)
        for point in self.__objPoints:
            x,y=point.pointXY
            geometry.AddPoint(x,y)
        return geometry
class ZoneContours:
    def __init__(self,tagB_contours_location,reverseXY=False):
        self.__xmlTag=tagB_contours_location
        self.__reverseXY=reverseXY
        self.__countrs=[]
        self.__prepare()
    def __prepare(self):
        if self.__xmlTag.contours is None:
            return
        for xml_contour in self.__xmlTag.contours.contour:
            self.__countrs.append(ZoneContour(xml_contour,self.__reverseXY))
            jkl=0
    def getGeometry(self):
        type_geometry=ogr.wkbPolygon
        if len(self.__countrs)==0:
            return None
        if len(self.__countrs) ==1:
            geometry = ogr.Geometry(type_geometry)
            geo_lineString=self.__countrs[0].Geometry
            if geo_lineString is None:
                return None
            geometry.AddGeometry(geo_lineString)
            return geometry

        geometry_multiPolygon = ogr.Geometry(ogr.wkbMultiPolygon)
        for countr in self.__countrs:
            geo_lineString = countr.Geometry
            if geo_lineString is None:
                continue
            geometry = ogr.Geometry(ogr.wkbPolygon)
            geometry.AddGeometry(geo_lineString)
            geometry_multiPolygon.AddGeometry(geometry)
        return geometry_multiPolygon





class Zone:
    def __init__(self,xmlTagZones_and_Territories,cad_number,reverseXY):
        self.__xmlObj=xmlTagZones_and_Territories
        self.__cadNumber=cad_number
        self.__objContours=None

        try:
            self.__objContours=ZoneContours(xmlTagZones_and_Territories.b_contours_location,reverseXY)
        except:
            pass
    @staticmethod

    def struct():
        struct = []

        struct.append({'name': 'дата_регистрации', 'type': ogr.OFTString, 'width': 22})
        struct.append({'name': 'реестровый_номер', 'type': ogr.OFTString, 'width': 20})
        struct.append({'name': 'тип_границы', 'type': ogr.OFTString, 'width': 512})
        struct.append({'name': 'код_границы', 'type': ogr.OFTInteger})
        struct.append({'name': 'тип_зоны', 'type': ogr.OFTString, 'width': 512})
        struct.append({'name': 'код_типа_зоны', 'type': ogr.OFTInteger})
        struct.append({'name': 'номер', 'type': ogr.OFTString, 'width': 100})
        struct.append({'name': 'индекс', 'type': ogr.OFTString, 'width': 100})
        return struct

    def Write(self,layer,str_styleMi=None):
        valRegDate=RecordInfoDate(self.__xmlObj.record_info)
        att = []
        if valRegDate is not None:
            att.append({'name': 'дата_регистрации', 'value': valRegDate.strftime("%Y-%m-%d")})
        b_object_values=getBObject(self.__xmlObj.b_object_zones_and_territories.b_object)
        if len(b_object_values)>0:
            att.extend(b_object_values)
        feature = ogr.Feature(layer.GetLayerDefn())
        if str_styleMi is not None:
            att.append({'name': 'MI_STYLE', 'value': str_styleMi})
        for atr_item in att:
            # print(atr_item['name'])
            # print(atr_item['value'])
            feature.SetField(atr_item['name'], atr_item['value'])
        geoObj = None
        if self.__objContours is not None :
            ''' Формируем геометрию '''
            geoObj=self.__objContours.getGeometry()

        #if geoObj is not None:
        feature.SetGeometry(geoObj)

        layer.CreateFeature(feature)
        jkl=0

class Zones:
    __name = "зоны_територии_границы"
    __nameProcess = "Импорт зон и территорий"
    def __init__(self,tagZones,cadastralNumber,properties):

        if tagZones is None:
            return
        self.__xmlZones=tagZones
        self.__CadastralNumber=cadastralNumber
        self.__properties=properties
        self.__cs_wkt=properties['cs']
        #self.__str_styleMi=properties['zones']['style']
        self.__str_styleMi=""
        self.__listZone=[]

        for itemtagZone in self.__xmlZones.zones_and_territories_record:
            self.__listZone.append(Zone(itemtagZone,self.__CadastralNumber,self.__properties['reverseXY']))
        return
    def setName(self,name_layer):
        self.__name=name_layer

    @property
    def NameLayer(self):
        return self.__name

    @property
    def NameProcess(self):
        return self.__nameProcess
    def CreateLayer(self,ds,createNewLayer=True):
        srs = osr.SpatialReference()
        srs.ImportFromWkt(self.__cs_wkt)
        layer=None
        if not createNewLayer:
            layer=ds.GetLayer(self.__name)
            if layer is not None:
                return layer

        layer = ds.CreateLayer(self.__name, srs, geom_type=ogr.wkbPolygon)
        struct_layer=Zone.struct()
        for fld in struct_layer:
            # create fields
            field_cur = ogr.FieldDefn(fld['name'], fld['type'])
            type_field = fld['type']
            if fld['type'] == ogr.OFTString:
                field_cur.SetWidth(fld['width'])
            layer.CreateField(field_cur)
        if self.__str_styleMi is not None:
            field_cur = ogr.FieldDefn("MI_STYLE", ogr.OFTString)
            field_cur.SetWidth(128)
            layer.CreateField(field_cur)
        return layer
    def Write(self,layer,dbDictionary=None,dbDoc=None):
        if self.__listZone is None:
            return
        ''' Получаем стиль из классификатора'''
        mi_style=dbDictionary.GetStyle('kpt_11_style','zone')
        if mi_style[0] is None:
            print(mi_style[1])
            str_mi_style='Pen (2, 6, 16711680) Brush (1, 16777215, 16777215)'
        else:
            str_mi_style=mi_style[0]
        #layer.StartTransaction()
        for zone in self.__listZone:
            '''
            if dbDoc is not None:
                if dbDoc.IsConnect is False:
                    dbDoc.initDb()
            '''
            zone.Write(layer,str_mi_style)
        #layer.CommitTransaction()
class Municipal_bound:
    def __init__(self,xmlMunicipal_bound,cad_number,reverseXY):
        self.__xmlObj=xmlMunicipal_bound
        self.__cadNumber=cad_number
        self.__objContours=None
        try:
            self.__objContours=ZoneContours(self.__xmlObj.b_contours_location,reverseXY)
        except:
            pass
    @staticmethod

    def struct():
        struct = []

        struct.append({'name': 'дата_регистрации', 'type': ogr.OFTString, 'width': 22})
        struct.append({'name': 'реестровый_номер', 'type': ogr.OFTString, 'width': 20})
        struct.append({'name': 'тип_границы', 'type': ogr.OFTString, 'width': 512})
        struct.append({'name': 'код_границы', 'type': ogr.OFTInteger})
        struct.append({'name': 'тип_зоны', 'type': ogr.OFTString, 'width': 512})
        struct.append({'name': 'код_типа_зоны', 'type': ogr.OFTInteger})
        struct.append({'name': 'номер', 'type': ogr.OFTString, 'width': 100})
        struct.append({'name': 'индекс', 'type': ogr.OFTString, 'width': 100})
        return struct

    def Write(self,layer,str_styleMi=None):
        valRegDate=RecordInfoDate(self.__xmlObj.record_info)
        att = []
        if valRegDate is not None:
            att.append({'name': 'дата_регистрации', 'value': valRegDate.strftime("%Y-%m-%d")})
        b_object_values=getBObject(self.__xmlObj.b_object_municipal_boundary.b_object)
        if len(b_object_values)>0:
            att.extend(b_object_values)
        feature = ogr.Feature(layer.GetLayerDefn())
        if str_styleMi is not None:
            att.append({'name': 'MI_STYLE', 'value': str_styleMi})
        for atr_item in att:
            # print(atr_item['name'])
            # print(atr_item['value'])
            feature.SetField(atr_item['name'], atr_item['value'])
        geoObj = None
        if self.__objContours is not None :
            ''' Формируем геометрию '''
            geoObj=self.__objContours.getGeometry()

        #if geoObj is not None:
        feature.SetGeometry(geoObj)

        layer.CreateFeature(feature)
        jkl=0

class Municipal_boundaries:
    __name='муниципальные_границы'
    __nameProcess = "Импорт муниципальныых границ"
    def __init__(self,tagBoundMunicipal,cadastralNumber,properties):

        if tagBoundMunicipal is None:
            self.__noData=True
            return

        self.__xmlZones=tagBoundMunicipal
        self.__CadastralNumber=cadastralNumber
        self.__properties=properties
        self.__cs_wkt=properties['cs']

        #self.__str_styleMi=properties['municipal']['style']
        self.__str_styleMi=''
        self.__listZone=[]

        for itemtagZone in self.__xmlZones.municipal_boundary_record:
            self.__listZone.append(Municipal_bound(itemtagZone,self.__CadastralNumber,self.__properties['reverseXY']))
        return

    @property
    def NameLayer(self):
        return self.__name

    @property
    def NameProcess(self):
        return self.__nameProcess
    def CreateLayer(self,ds,createNewLayer=True):
        srs = osr.SpatialReference()
        srs.ImportFromWkt(self.__cs_wkt)
        layer=None
        if not createNewLayer:
            layer=ds.GetLayer(self.__name)
            if layer is not None:
                return layer

        layer = ds.CreateLayer(self.__name, srs, geom_type=ogr.wkbPolygon)
        struct_layer=Zone.struct()
        for fld in struct_layer:
            # create fields
            field_cur = ogr.FieldDefn(fld['name'], fld['type'])
            type_field = fld['type']
            if fld['type'] == ogr.OFTString:
                field_cur.SetWidth(fld['width'])
            layer.CreateField(field_cur)
        if self.__str_styleMi is not None:
            field_cur = ogr.FieldDefn("MI_STYLE", ogr.OFTString)
            field_cur.SetWidth(128)
            layer.CreateField(field_cur)
        return layer
    def Write(self,layer,dbDictionary=None,mapCatalog=None):
        if self.__listZone is None:
            return
        ''' Получаем стиль из базы'''

        mi_style = dbDictionary.GetStyle('kpt_11_style', 'municipal_bound')
        if mi_style[0] is None:
            print(mi_style[1])
            str_mi_style = 'Pen (2, 6, 16711680) Brush (1, 16777215, 16777215)'
        else:
            str_mi_style = mi_style[0]
        #layer.StartTransaction()
        for zone in self.__listZone:
            '''
            if dbDoc is not None:
                if dbDoc.IsConnect is False:
                    dbDoc.initDb()
            '''
            zone.Write(layer,str_mi_style)
        mapCatalog.addLayerInfoInMapCataalog(layer,self.__properties['cs_mi'])
        layer=None
