from axipy import Point, Style, Pnt, LineString, Polygon, Ellipse, Rect, Rectangle, Geometry, Text, Line

from LoadMiWor.ui.processTool.parserWor.parse import parse, search

def getTextValue(source_wor,start_index):
    out_str_value=""
    isEnd=False
    i=0
    while not isEnd:
        cur_string=source_wor[start_index+i].lstrip()

        if len(cur_string)>=255 and cur_string[-1]=="+":
            cur_string=cur_string[:-1]
            '''
            token_text = search('"{text}"', cur_string + " ")
            value_text = token_text.named['text']
            out_str_value=out_str_value+value_text
            '''
        else:


            isEnd=True
        token_text = search('"{text}"', cur_string + " ")
        value_text = token_text.named['text']
        out_str_value = out_str_value + value_text
        i=i+1
    if out_str_value.find('\\n')>=0:
        out_str_value=out_str_value.replace('\\n','\n')

    return out_str_value,i-1

def getXYFromString(str_xy):
    s_xy=str_xy.split(",")
    return float(s_xy[0]),float(s_xy[1])
def buildArrayPnt(start_index,list_string,count_pnt):
    points=[]
    for i in range(count_pnt):
        id_line=i+start_index
        pn=parse("({xy})",list_string[id_line].lstrip())
        xy=pn.named['xy'].split(",")
        points.append(Pnt(float(xy[0]),float(xy[1])))
    return points

class AxiPoint:
    def __init__(self,x,y,cs,style):
        self.__geo=Point(x,y,cs)
        self.__axi_style=style
    @property
    def geometry(self):
        return self.__geo
    @property
    def style(self):
        return self.__axi_style
class AxiPolyLine:
    def __init__(self,str_points,cs,style):
        self.__axi_style=style
        list_pnt=[]
        for pn in str_points:
            xy=pn.split(",")
            list_pnt.append(Pnt(float(xy[0]),float(xy[1])))
        self.__geo=LineString(list_pnt,cs=cs)
    @property
    def geometry(self):
        return self.__geo
    @property
    def style(self):
        return self.__axi_style
class AxiPolygon:
    def __init__(self,list_poly_points,cs,style):
        self.__axi_style=style
        self.__geo=Polygon(list_poly_points[0],cs=cs)
        if len(list_poly_points)==1:
            return
        for i in range(1,len(list_poly_points)):
            self.__geo.holes.append(list_poly_points[i])

    @property
    def geometry(self):
        return self.__geo
    @property
    def style(self):
        return self.__axi_style
class AxiRect:
    def __init__(self, geo_rect,  style):
        self.__geo=geo_rect
        self.__axi_style=style
    @property
    def geometry(self):
        return self.__geo

    @property
    def style(self):
        return self.__axi_style
class AxiGeometry:
    def __init__(self, geo_obj,  style):
        self.__geo= geo_obj
        self.__axi_style=style
    @property
    def geometry(self):
        return self.__geo

    @property
    def style(self):
        return self.__axi_style
class AxiEllipse:
    def __init__(self,rect,cs,style):
        self.__axi_style=style
        self.__geo=Ellipse(rect,cs=cs)
    @property
    def geometry(self):
        return self.__geo
    @property
    def style(self):
        return self.__axi_style
class AxiPrepareText:
    def __init__(self,text_value,rect_text,style,angle,cs):
        self.__text=text_value
        self.__rect=rect_text
        self.__style=style
        self.__angle=angle
        self.__cs=cs

    @property
    def style(self):
        return self.__style
    def createAxiTextGeoObject(self,view):
        out_rect=self.__rect
        if self.__cs is not None and self.__cs!=view.coordsystem:
            pt_0 = Point(self.__rect.xmin, self.__rect.ymin, self.__cs)
            pt_1 = Point(self.__rect.xmax, self.__rect.ymax, self.__cs)
            pt_n_0 = pt_0.reproject(view.coordsystem)
            pt_n_1 = pt_1.reproject(view.coordsystem)
            out_rect = Rect(pt_n_0.x, pt_n_0.y, pt_n_1.x, pt_n_1.y)
        if self.__cs is None:
            return Text(self.__text,rect=out_rect,angle=self.__angle,view=view)
        geo_obj_text= Text(self.__text,rect=out_rect,angle=self.__angle,view=view,cs=view.coordsystem)
        return geo_obj_text
def factoryEllipse(start_d_line,lines_wor,cs):
    ''' Парсим Ellipse'''
    token_ellips=parse("Create Ellipse ({lr}) ({ud})",lines_wor[start_d_line])
    str_lr=token_ellips.named['lr']
    xmin,ymin=getXYFromString(str_lr)
    str_ud=token_ellips.named['ud']
    xmax,ymax=getXYFromString(str_ud)
    mi_style=Style.from_mapinfo(lines_wor[start_d_line+1].lstrip()+" "+lines_wor[start_d_line+2].lstrip())
    return AxiEllipse(Rect(xmin,ymin,xmax,ymax),cs,mi_style)
def factoryPoint(start_d_line,lines_wor,cs):
    ''' Парсим точку'''
    token_point=parse("Create Point ({xy})",lines_wor[start_d_line])
    xy=token_point.named['xy'].split(",")
    mi_style=Style.from_mapinfo(lines_wor[start_d_line+1])
    return AxiPoint(float(xy[0]),float(xy[1]),cs,mi_style)
def factoryPolyLine(start_d_line,lines_wor,cs):
    token_obj=parse("Create Pline {np}",lines_wor[start_d_line])
    count_point=int(token_obj.named['np'])
    str_points=[]
    for i in range(count_point):
        id_line=i+start_d_line+1
        xy=parse("({xy})",lines_wor[id_line].lstrip())
        str_points.append(xy.named['xy'])
    str_mi_style=lines_wor[start_d_line+count_point+1].lstrip()
    return AxiPolyLine(str_points,cs,Style.from_mapinfo(str_mi_style))
def factoryRect(start_d_line,lines_wor,cs):
    mi_str=lines_wor[start_d_line].strip()+" "
    tocken_rect=search("Create Rect ({lb}) ({ru})",mi_str)
    str_lbxy=tocken_rect.named['lb']
    str_urxy=tocken_rect.named['ru']
    xy_lb=getXYFromString(str_lbxy)
    xy_ru=getXYFromString(str_urxy)
    geo_rect=Rectangle(xy_lb[0],xy_lb[1],xy_ru[0],xy_ru[1],cs=cs)
    mi_style_pen=lines_wor[start_d_line+1].strip()
    mi_style_brush = lines_wor[start_d_line + 2].strip()
    style=Style.from_mapinfo(mi_style_pen+" "+mi_style_brush)
    return AxiRect(geo_rect,style)
def factoryLine(start_d_line,lines_wor,cs):
    mi_str = lines_wor[start_d_line].strip() + " "
    tocken_rect = search("Create Line ({lb}) ({ru})", mi_str)
    str_lbxy = tocken_rect.named['lb']
    str_urxy = tocken_rect.named['ru']
    xy_lb = getXYFromString(str_lbxy)
    xy_ru = getXYFromString(str_urxy)
    geo_line=Line(Pnt(xy_lb[0],xy_lb[1]),Pnt(xy_ru[0],xy_ru[1]),cs=cs)
    mi_style_pen = lines_wor[start_d_line + 1].strip()
    style = Style.from_mapinfo(mi_style_pen)
    return AxiGeometry(geo_line,style)
def factoryTextMif(start_d_line,lines_wor,cs):
    str_mif="Text "
    '''
    mi_text_value = lines_wor[start_d_line+1].strip()
    mi_coord=lines_wor[start_d_line+2].strip()+" "
    tocken_text = search("({lb}) ({ru})",mi_coord)
    str_lbxy = tocken_text.named['lb']
    str_urxy = tocken_text.named['ru']
    xy_lb = getXYFromString(str_lbxy)
    xy_ru = getXYFromString(str_urxy)
    mi_style = lines_wor[start_d_line + 3].strip()
    style=Style.from_mapinfo(mi_style)
    angle=0
    mi_angle = lines_wor[start_d_line + 4].strip()+" "
    tocken_angle=search("Angle {angle}")
    if tocken_angle is not None:
        angle=float(tocken_angle.named['angle'])
    '''
    str_mif=str_mif+" "+lines_wor[start_d_line+1].strip()+" "
    mi_coord = lines_wor[start_d_line + 2].strip() + " "
    tocken_text = search("({lb}) ({ru})", mi_coord)
    str_lbxy = tocken_text.named['lb']
    str_urxy = tocken_text.named['ru']
    lbxy=str_lbxy.replace(',',' ')
    urxy=str_urxy.replace(',',' ')
    str_mif = str_mif +lbxy+" "+urxy+" "
    str_mif = str_mif +  lines_wor[start_d_line + 3].strip()+" "
    tocken_angle = search("Angle {angle}",lines_wor[start_d_line + 4].strip()+" ")
    if tocken_angle is not None:
        str_mif = str_mif + lines_wor[start_d_line + 4].strip()
    geo_text=Geometry.from_mif(str_mif)
    geo_text.coordsystem=cs
    mi_style = lines_wor[start_d_line + 3].strip()
    style = Style.from_mapinfo(mi_style)
    return AxiGeometry(geo_text,style)
def factoryText(start_d_line,lines_wor,cs):
    start_index = start_d_line + 1
    '''
    mi_text_value = lines_wor[start_d_line + 1].strip()
    token_text=search('"{text}"',mi_text_value+" ")
    value_text=token_text.named['text']
    '''
    value_text, offset = getTextValue(lines_wor, start_index)
    #mi_coord = lines_wor[start_d_line + 2].strip() + " "
    start_index = start_index + offset
    #mi_coord = lines_wor[start_d_line + 2].strip() + " "
    mi_coord = lines_wor[start_index + 1].strip() + " "
    tocken_text = search("({lb}) ({ru})", mi_coord)
    str_lbxy = tocken_text.named['lb']
    str_urxy = tocken_text.named['ru']
    xy_lb = getXYFromString(str_lbxy)
    xy_ru = getXYFromString(str_urxy)
    #mi_style = lines_wor[start_d_line + 3].strip()
    mi_style = lines_wor[start_index + 2].strip()
    style = Style.from_mapinfo(mi_style)
    angle = 0
    mi_angle = lines_wor[start_index + 3].strip() + " "
    tocken_angle = search("Angle {angle} ",mi_angle)
    if tocken_angle is not None:
        angle = float(tocken_angle.named['angle'])
    rect_text=Rect(xy_lb[0],xy_lb[1],xy_ru[0],xy_ru[1])
    return AxiPrepareText(value_text,rect_text,style,angle,cs)
def factoryTextReport(start_d_line,lines_wor,cs):
    start_index=start_d_line+1
    #mi_text_value = lines_wor[start_d_line + 1].strip()
    value_text,offset=getTextValue(lines_wor,start_index)
    '''
    token_text=search('"{text}"',mi_text_value+" ")
    value_text=token_text.named['text']
    '''
    start_index=start_index+offset
    mi_coord = lines_wor[start_index + 1].strip() + " "
    tocken_text = search("({lb}) ({ru})", mi_coord)
    '''
    if tocken_text is None:
        jkl=0
    '''
    str_lbxy = tocken_text.named['lb']
    str_urxy = tocken_text.named['ru']
    xy_lb = getXYFromString(str_lbxy)
    xy_ru = getXYFromString(str_urxy)
    mi_style = lines_wor[start_index + 2].strip()
    style = Style.from_mapinfo(mi_style)
    angle = 0
    mi_angle = lines_wor[start_index + 3].strip() + " "
    tocken_angle = search("Angle {angle} ",mi_angle)
    index_Priority=0
    if tocken_angle is not None:
        angle = float(tocken_angle.named['angle'])
        index_Priority=1
    mi_Priority=lines_wor[start_index + 3+index_Priority].strip() + " "
    token_Priority=search("Priority {priority} ",mi_Priority)
    priority=0
    if token_Priority is not None:
        priority=int(token_Priority.named['priority'])
    rect_text=Rect(xy_lb[0],xy_lb[1],xy_ru[0],xy_ru[1])
    return AxiPrepareText(value_text,rect_text,style,angle,cs),style,priority
def factoryPolygon(start_d_line,lines_wor,cs):
    token_obj=parse("Create Region {npoly}",lines_wor[start_d_line])
    count_poly=int(token_obj.named['npoly'])
    list_point_poly=[]
    start_index=start_d_line+1
    for i in range(count_poly):
        str_count_pnt=lines_wor[start_index].strip()
        count_pnt=int(str_count_pnt)
        start_index=start_index+1
        points=buildArrayPnt(start_index,lines_wor,count_pnt)
        list_point_poly.append(points)
        start_index=start_index+count_pnt
    #start_index=start_index+1
    str_mi_style_0=lines_wor[start_index].strip()
    str_mi_style_1=lines_wor[start_index+1].strip()
    str_mi_style=str_mi_style_0+" "+str_mi_style_1
    mi_style=Style.from_mapinfo(str_mi_style)
    return AxiPolygon(list_point_poly,cs,mi_style)

def factoryPolygonReport(start_d_line,lines_wor,cs):
    token_obj=parse("Create Region {npoly}",lines_wor[start_d_line])
    count_poly=int(token_obj.named['npoly'])
    list_point_poly=[]
    start_index=start_d_line+1
    for i in range(count_poly):
        str_count_pnt=lines_wor[start_index].strip()
        count_pnt=int(str_count_pnt)
        start_index=start_index+1
        points=buildArrayPnt(start_index,lines_wor,count_pnt)
        list_point_poly.append(points)
        start_index=start_index+count_pnt
    #start_index=start_index+1
    str_mi_style_0=lines_wor[start_index].strip()
    str_mi_style_1=lines_wor[start_index+1].strip()
    str_mi_style=str_mi_style_0+" "+str_mi_style_1
    mi_style=Style.from_mapinfo(str_mi_style)
    axi_polygon= AxiPolygon(list_point_poly,cs,mi_style)
    mi_str_priorety = lines_wor[start_index+2].strip() + " "
    token_1 = search('Priority {priority}', mi_str_priorety)
    if token_1 is None:
        priorety = 0
    else:

        priorety = int(token_1.named['priority'])
    return axi_polygon.geometry,axi_polygon.style,priorety
def factoryEllipseReport(start_index,source_wor,cs_units):
    mi_str = source_wor[start_index].strip() + " "
    tocken_Ellipse = search("Create Ellipse ({lb}) ({ru})", mi_str)
    str_lb=tocken_Ellipse['lb']
    str_ru=tocken_Ellipse['ru']
    xy_lb = getXYFromString(str_lb)
    xy_ru = getXYFromString(str_ru)
    rect=Rect(xy_lb[0],xy_lb[1],xy_ru[0],xy_ru[1])
    geo_ellipse=Ellipse(rect)
    line_style_str=None
    brush_style_str=None
    '''Читаем стили'''
    for i in range(2):
        str_wor=source_wor[start_index+i+1]
        if str_wor.lower().find("pen")>=0:
            line_style_str=str_wor.strip()
            continue
        if str_wor.lower().find("brush")>=0:
            brush_style_str=str_wor.strip()
            continue
    mi_style_str=""
    if line_style_str is not None:
        mi_style_str=mi_style_str+line_style_str
    if brush_style_str is not None:
        mi_style_str=mi_style_str+" "+brush_style_str
    mi_style=Style.from_mapinfo(mi_style_str)
    priorety = 0
    return geo_ellipse,mi_style,priorety


def factoryPolyLineReport(start_index,source_wor,cs_units):
    mi_str_1=source_wor[start_index].strip()+" "
    #token_1=search('Create Pline {count_points}',mi_str_1)
    offset=0
    if mi_str_1.lower().find('into')>=0:

        mi_str_1 = source_wor[start_index+1].strip()
        count_points=int(mi_str_1)
        offset=1
    else:
        token_1 = search('Create Pline {count_points}', mi_str_1)
        count_points=int(token_1.named['count_points'])
    if count_points==28:
        jkl=0
    points=[]
    new_start=start_index+offset
    ''' читаем точки polyline'''
    for i in range(count_points):
        mis_str=source_wor[new_start+i+1].strip()
        str_xy=mis_str.replace('(','')
        str_xy = str_xy.replace(')', '')
        xy=getXYFromString(str_xy)
        points.append(xy)
    mi_str_style=source_wor[new_start+count_points+1].strip()
    mi_str_priorety=source_wor[new_start+count_points+2].strip()+" "
    token_1 = search('Priority {priority}', mi_str_priorety)
    if token_1 is None:
        priorety=0
    else:

        priorety=int(token_1.named['priority'])

    style_rect=Style.from_mapinfo(mi_str_style)
    object_rect=LineString(points)
    return object_rect,style_rect,priorety
def factoryLineReport(start_d_line,lines_wor,cs):
    axi_geo=factoryLine(start_d_line,lines_wor,cs)
    mi_str_priorety = lines_wor[start_d_line + 2].strip() + " "
    token_1 = search('Priority {priority}', mi_str_priorety)
    if token_1 is None:
        priorety = 0
    else:

        priorety = int(token_1.named['priority'])
    return axi_geo.geometry,axi_geo.style,priorety
def factoryRectReport(start_d_line,lines_wor,cs):
    mi_str=lines_wor[start_d_line].strip()+" "
    tocken_rect=search("Create Rect ({lb}) ({ru})",mi_str)
    str_lbxy=tocken_rect.named['lb']
    str_urxy=tocken_rect.named['ru']
    xy_lb=getXYFromString(str_lbxy)
    xy_ru=getXYFromString(str_urxy)
    geo_rect=Rectangle(xy_lb[0],xy_lb[1],xy_ru[0],xy_ru[1],cs=cs)
    mi_style_pen=lines_wor[start_d_line+1].strip()
    mi_style_brush = lines_wor[start_d_line + 2].strip()
    style=Style.from_mapinfo(mi_style_pen+" "+mi_style_brush)
    mi_str_priorety = lines_wor[start_d_line + 3].strip() + " "
    token_1 = search('Priority {priority}', mi_str_priorety)
    if token_1 is None:
        priorety = 0
    else:

        priorety = int(token_1.named['priority'])
    return geo_rect,style,priorety
def factoryPointReport(start_d_line,lines_wor,cs):
    mi_str=lines_wor[start_d_line].strip()+" "
    tocken_rect=search("Create Point ({xy}) ",mi_str)
    str_lbxy=tocken_rect.named['xy']

    xy=getXYFromString(str_lbxy)
    pt=Point(xy[0],xy[1])
    mi_style=lines_wor[start_d_line+1].strip()
    style=Style.from_mapinfo(mi_style)
    mi_str_priorety = lines_wor[start_d_line + 2].strip() + " "
    token_1 = search('Priority {priority}', mi_str_priorety)
    if token_1 is None:
        priorety = 0
    else:

        priorety = int(token_1.named['priority'])
    return pt,style,priorety
def factoryGeometry(name_obj,start_d_line,lines_wor,cs):

    if name_obj=='ellipse':
        return   factoryEllipse(start_d_line,lines_wor,cs)
    if name_obj=='point':
        return factoryPoint(start_d_line,lines_wor,cs)
    if name_obj=='pline':
        return factoryPolyLine(start_d_line,lines_wor,cs)
    if name_obj=='region':
        return factoryPolygon(start_d_line,lines_wor,cs)
    if name_obj=='rect':
        return factoryRect(start_d_line,lines_wor,cs)
    if name_obj=='line':
        return factoryLine(start_d_line,lines_wor,cs)
    if name_obj=='text':
        #return factoryTextMif(start_d_line,lines_wor,cs)
        return factoryText(start_d_line,lines_wor,cs)
    return None
def factoryGeometryReport(item_wor,source_wor,cs_units=None):
    if item_wor['words'][1].lower()=='pline':
        return factoryPolyLineReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'text':
        return factoryTextReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'rect':
        return factoryRectReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'point':
        return factoryPointReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'line':
        return factoryLineReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'region':
        return factoryPolygonReport(item_wor['index'],source_wor,None)
    if item_wor['words'][1].lower() == 'ellipse':
        return factoryEllipseReport(item_wor['index'],source_wor,None)
    return None,None,None


