
from PyQt5.QtWidgets import QWidget, QApplication,QMainWindow,QLabel
from PyQt5.QtGui import QPixmap,QPainter,QResizeEvent,QCloseEvent,QPaintEvent,QFont
from PyQt5.QtCore import QSize,QTimer,QRect,Qt
import async_communication as CM
import message_pb2 as message
import google.protobuf.text_format as tf
import projector_control as PJC

MeasureStatu={"ok":0,"无数据":1,"噪声":2,"超界":3}
ArrowType={0:"正确图片",0x01:"向后调整",0x02:"向前调整",0x04:"向右调整",0x08:"向左调整"
           ,0x10:"左前调整",0x06:"右前调整",0x09:"右后调整",0x05:"左后调整"}
class PicLabel(QLabel):
    def __init__(self,parent):
        super(PicLabel,self).__init__(parent=parent)
        self.image=None
        self.show = False
        self.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150)")
        self.timer=QTimer()
        self.timer.timeout.connect(self.OnTimer)
    def FlashImg(self,pixmap):
        self.image=pixmap
        if self.timer.isActive()==False:
            self.timer.start(500)
    def ShowImg(self,pixmap):
        self.timer.stop()
        self.show=True
        self.image=pixmap
        self.repaint()

    def OnTimer(self):
        self.show=not self.show
        self.repaint()

    def paintEvent(self, a0: QPaintEvent) -> None:
        if self.show==True:
            if not self.image == None:
                w, h = self.size().width(),self.size().height()
                iw, ih = self.image.width(), self.image.height()
                painter=QPainter(self)
                painter.drawPixmap(QRect(0,0,w,h),self.image,QRect(0,0,iw,ih))



class Frame(QMainWindow):
    def __init__(self,images,prj_parameter,second_screen=False):
        super(Frame, self).__init__()
        self.images=images
        self.images = {}
        self.icpu_statu = CM.TimeStatu(timeout=0.1)
        self.measure_statu = CM.TimeStatu(timeout=0.1)
        self.terminal_statu = CM.TimeStatu(timeout=0.1)

        for key, file in images.items():
            self.images[key] =  pix = QPixmap(file)

        self.InitUI()

        self.last_door_statu=None
        self.last_moving_statu = None
        self.last_show = None
        self.last_back_io = "正常"
        self.flag = None
        if second_screen == True:
            desktop = QApplication.desktop()
            screen_count = desktop.screenCount()
            displays = [desktop.availableGeometry(i) for i in range(desktop.screenCount())]
            second_offx = 0
            second_offy = 0

            if len(displays) == 2:
                second_offx = displays[1].width()
                second_offy = displays[1].height()
            self.setGeometry(second_offx,second_offy,200,500)

        if prj_parameter is not None:
            prj_ip=prj_parameter['ip']
            prj_port=prj_parameter['port']
            prj_type=prj_parameter['type']
            self.pjc_=PJC.ProjectorControl(prj_ip,prj_port,prj_type)
            self.pjc_.start()
        else:
            self.pjc_=None

        self.timer = QTimer()
        self.timer.timeout.connect(self.Switch)
        self.timer.start(200)


    def InitUI(self):
        self.measure_info_txt=QLabel(self)
        self.car_number_txt = QLabel(self)
        self.car_number_txt.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150)")
        self.car_number_txt.setAlignment(Qt.AlignCenter)
        self.measure_info_txt.setStyleSheet("color:blue")
        self.panel_txt=PicLabel(self)
        self.panel_arrow=PicLabel(self)

    def receive_icpu(self,statu):
        self.icpu_statu=statu
    def receive_measureInfo(self,statu):
        self.measure_statu=statu
    def receive_terminal(self,statu):
        self.terminal_statu=statu
    def closeEvent(self, a0: QCloseEvent) -> None:
        if self.pjc_ is not None:
            self.pjc_.lightOff()
            self.pjc_.exit()
            self.pjc_.join()
    def resizeEvent(self, a0: QResizeEvent) -> None:
        w, h = a0.size().width(), a0.size().height()
        w, h = self.size().width(), self.size().height()
        top_w, top_h = w, int(h * 0.15)
        car_number_w,car_number_h=w, int(h * 0.10)
        txt_w, txt_h = w, int(h * 0.20)
        arrow_w, arrow_h = w, int(h * 0.55)
        font = QFont()
        font.setBold(True)
        font.setPixelSize(int(w / 40))
        self.measure_info_txt.setFont(font)
        self.measure_info_txt.setGeometry(0, 0, top_w, top_h)
        font.setPixelSize(int(w / 20))
        self.car_number_txt.setFont(font)
        self.car_number_txt.setGeometry(0, top_h, car_number_w, car_number_h)

        self.panel_txt.setGeometry(0, top_h+car_number_h, txt_w, txt_h)
        self.panel_arrow.setGeometry(0, top_h +car_number_h+ txt_h, arrow_w, arrow_h)

    def Switch(self):
        if self.terminal_statu.timeout() is False:
            terminal_statu = message.terminal_node_statu()
            tf.Parse(self.terminal_statu.statu, terminal_statu)
            print(terminal_statu.car_number)
            self.car_number_txt.setText(terminal_statu.car_number)
            self.car_number_txt.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150);color:green")
        else:
            self.car_number_txt.setText("车牌号为空！")
            self.car_number_txt.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150);color:red")
        #先判断连接状态
        if self.icpu_statu.timeout():
            self.panel_txt.ShowImg(self.images['传感器超时'])
            self.panel_arrow.FlashImg(self.images['传感器超时'])
            self.last_show="超时"
            return
        if self.measure_statu.timeout():
            self.panel_txt.ShowImg(self.images['测绘超时'])
            self.panel_arrow.FlashImg(self.images['测绘超时'])
            self.last_show="超时"
            return
        #有车才显示
        icpu_statu=message.in_mcpu_statu()
        tf.Parse(self.icpu_statu.statu,icpu_statu)

        measure_info=message.measure_info()
        tf.Parse(self.measure_statu.statu,measure_info)

        # if 门关，self.last_moving_statu 清除上一帧数据

        # if self.last_moving_statu none  且后光电从被压到释放 且当前雷达数据为噪声
           #提示  雷达呗干扰
        if icpu_statu.door_statu == 3:
            self.last_moving_statu = None

        if icpu_statu.back_io == 2:#正常
            if not self.last_back_io=="正常":
                self.last_back_io="正常"
                self.flag = True
        elif icpu_statu.back_io == 1:
            if not self.last_back_io=="超界":
                self.last_back_io="超界"
                self.flag = False


        # 外门状态控制投影仪
        if self.pjc_ is not None:
            if icpu_statu.door_statu==3: #关门状态
                if not self.last_door_statu=="closed":
                    print("close")
                    self.pjc_.lightOff()
                    self.last_door_statu="closed"
            elif icpu_statu.door_statu==2 or icpu_statu.door_statu==4:
                if not self.last_door_statu=="opened":
                    self.pjc_.lightOn()
                    print("open")
                    self.last_door_statu="opened"



        if icpu_statu.is_occupy != 2:
            self.panel_txt.ShowImg(self.images["空闲"])
            self.panel_arrow.ShowImg(self.images["空闲"])
            self.last_show = "空闲"
            return


        #以下是有车的处理
        #1,显示测量数据（实时和静态）

        realtime_info_txt=''
        static_info_txt=''

        realtime_info_txt="(实时) 中心(%.3f,%.3f) 角度:%.2f° 宽:%.3f 轴距:%.3f 前轮角:%.2f°"%\
                    (measure_info.cx,measure_info.cy,measure_info.theta,measure_info.width,
                    measure_info.wheelbase,measure_info.front_theta)
        if not self.last_moving_statu==None:
            static_info_txt="(静止) 中心(%.3f,%.3f) 角度:%.2f° 宽:%.3f 轴距:%.3f 前轮角:%.2f°"%\
                    (self.last_moving_statu.cx,self.last_moving_statu.cy,
                     self.last_moving_statu.theta,self.last_moving_statu.width,
                     self.last_moving_statu.wheelbase,self.last_moving_statu.front_theta)
        self.measure_info_txt.setText(realtime_info_txt+"\n"+static_info_txt)

        #2,获取车辆运动状态（静止or动态）
        border_statu=measure_info.border_statu
        is_moving = ((border_statu >> 11) & 0x01) == 1
        lidar_statu=measure_info.ground_status  # 测量状态（正常,无数据、噪声、超界）



        if is_moving:
            self.last_moving_statu=None
        else:
            #当前静止
            if lidar_statu==MeasureStatu["ok"]:
                self.last_moving_statu=measure_info
            elif lidar_statu==MeasureStatu["超界"]:
                if not self.last_moving_statu ==None:
                    #上一刻静止且数据正确，当前静止，不可能出现超界，将超界清除
                    new_border=border_statu
                    new_border = (new_border & (~(0x01 << 0)))
                    new_border = (new_border & (~(0x01 << 1)))
                    new_border = (new_border & (~(0x01 << 2)))
                    new_border = (new_border & (~(0x01 << 3)))
                    new_border = (new_border & (~(0x01 << 6)))
                    new_border = (new_border & (~(0x01 << 7)))
                    new_border = (new_border & (~(0x01 << 8)))
                    new_border = (new_border & (~(0x01 << 9)))
                    border_statu=new_border
            elif lidar_statu==MeasureStatu["无数据"]:
                #当前静止无车，清除上一时刻数据
                self.last_moving_statu=None
            elif lidar_statu==MeasureStatu["噪声"]:
                if not self.last_moving_statu==None:
                    #上一时刻静止且正确，当前噪声，不显示当前数据，显示上一正确数据
                    measure_info.CopyFrom(self.last_moving_statu)
        #先判断光电
        if is_moving:
            if icpu_statu.back_io==1:
                self.panel_txt.ShowImg(self.images["请调整"])
                self.panel_arrow.FlashImg(self.images["向前调整"])
                self.last_show="调整"
                return

        #光电正常
        if lidar_statu==MeasureStatu["无数据"]:
            self.panel_txt.ShowImg(self.images["空闲"])
            self.panel_arrow.ShowImg(self.images["空闲"])
            self.last_show="空闲"
            return
        elif lidar_statu==MeasureStatu["噪声"]:
            if self.last_moving_statu is None and self.flag is True:
                self.panel_txt.ShowImg(self.images["检查杂物"])
                self.panel_arrow.ShowImg(self.images["检查杂物"])
                self.last_show = "检查杂物"
                return
            if self.last_show=="超时":
                self.panel_txt.ShowImg(self.images["空闲"])
                self.panel_arrow.ShowImg(self.images["空闲"])
                self.last_show="空闲"
            return
        elif lidar_statu==MeasureStatu["ok"]:
            self.panel_txt.ShowImg(self.images['正确文字'])
            self.panel_arrow.ShowImg(self.images['正确图片'])
            return
        elif lidar_statu==MeasureStatu["超界"]:
            if (border_statu>>7)&0x01==1:
                self.panel_txt.ShowImg(self.images['轴距超差'])
                self.panel_arrow.ShowImg(self.images['轴距超差'])
                self.last_show="轴距超差"
                return
            if (border_statu>>9)&0x01==1:
                self.panel_txt.ShowImg(self.images['请调整'])
                self.panel_arrow.FlashImg(self.images['向左旋转'])
                self.last_show="请调整"
                return
            if (border_statu>>8)&0x01==1:
                self.panel_txt.ShowImg(self.images['请调整'])
                self.panel_arrow.FlashImg(self.images['向右旋转'])
                self.last_show="请调整"
                return
            if (border_statu>>10)&0x01==1:
                self.panel_txt.ShowImg(self.images['请调整'])
                self.panel_arrow.FlashImg(self.images['回正方向盘'])
                self.last_show="请调整"
                return
            if (border_statu>>6)&0x01==1:
                self.panel_txt.ShowImg(self.images['超宽车辆'])
                self.panel_arrow.ShowImg(self.images['超宽车辆'])
                self.last_show="超宽"
                return
            border=border_statu&0x0f
            if (border in ArrowType.keys()) is False:
                self.panel_txt.ShowImg(self.images['检查杂物'])
                self.panel_arrow.FlashImg(self.images['检查杂物'])
                self.last_show = "检查杂物"
            else:
                if ArrowType[border] == "正确图片":
                    self.panel_arrow.ShowImg(self.images[ArrowType[border]])
                    self.panel_txt.ShowImg(self.images['正确文字'])
                    self.last_show="正确"
                else:
                    self.panel_arrow.FlashImg(self.images[ArrowType[border]])
                    self.panel_txt.ShowImg(self.images['请调整'])
                    self.last_show="请调整"





