class MainWidget(QMainWindow):
    def __init__(self ,parent=None):
        super(MainWidget ,self).__init__(parent)
        self.raw_img = np.array([])
        self.play_flag = 0
        self.demo_path = './demoVideo/Demo.avi'
        # 设置主窗口
        self.setWindowIcon(QIcon('./icons/windowIcon.png'))
        self.showFullScreen()
        self.setWindowTitle(self.tr("位姿估计"))
        self.imageLabel=QLabel()
        #self.img = QPixmap.fromImage(QImage("640_4800.jpg"))
        #te.setPixmap(self.img)
        self.imageLabel.setMaximumSize(480, 360)
        self.imageLabel.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(self.imageLabel)

        # 设置工具栏
        self.toolbar()

        # 设置菜单栏
        self.menu()

        # 停靠窗口1
        dock1= QDockWidget(self.tr("进行位姿测量的帧"),self)
        dock1.setFeatures(QDockWidget.DockWidgetMovable)
        dock1.setAllowedAreas(Qt.LeftDockWidgetArea|Qt. RightDockWidgetArea)

        self.te1 = QLabel()
        dock1.setWidget(self.te1)
        dock1.setMaximumSize(320, 240)
        dock1.setMinimumSize(320, 240)
        self.addDockWidget(Qt.RightDockWidgetArea,dock1)

        # 停靠窗口2
        dock2=QDockWidget ( self.tr("位姿测量结果"),self)
        dock2.setFeatures(QDockWidget.DockWidgetFloatable|QDockWidget . DockWidgetClosable)
        self.te2=QTextEdit( self.tr("本窗口将显示位姿处理结果"))
        dock2.setWidget(self.te2)
        dock2.setMinimumSize(320, 240)
        self.addDockWidget(Qt.RightDockWidgetArea,dock2)
     

    def toolbar(self):
        # 定义开始,停止,估计位姿和退出,这四种动作
        quitAction = QAction(QIcon('./icons/quit.png'), u'退出', self)
        quitAction.triggered.connect(self.quit)

        startAction = QAction(QIcon('./icons/start.png'), u'开始采集', self)
        startAction.triggered.connect(self.start)

        stopAction = QAction(QIcon('./icons/stop.png'), u'停止采集', self)
        stopAction.triggered.connect(self.stop)

        estimateAction = QAction(QIcon('./icons/estimate.png'), u'估计位姿', self)
        estimateAction.triggered.connect(self.estimate)

        # 动作: 拍摄标定用的图片
        calibCaptureAction = QAction(QIcon('./icons/camera.png'), u'拍照', self)
        self.connect(calibCaptureAction, SIGNAL("triggered()"), self.calibCapture)

        # 动作: 录制视频
        recordVideoAction = QAction(QIcon('./icons/record.png'), u'录像', self)
        self.connect(recordVideoAction, SIGNAL("triggered()"), self.recordVideo)

        # 把按钮和动作连接到一起
        toolBar = self.addToolBar("开始")
        toolBar.addAction(startAction)

        toolBar = self.addToolBar("停止")
        toolBar.addAction(stopAction)

        toolBar = self.addToolBar("退出")
        toolBar.addAction(quitAction)

        toolBar = self.addToolBar("估计")
        toolBar.addAction(estimateAction)

        toolBar = self.addToolBar("拍照")
        toolBar.addAction(calibCaptureAction)
        
        toolBar = self.addToolBar("录像")
        toolBar.addAction(recordVideoAction)

    def menu(self):
        # 定义动作:
        # 动作: 标定
        calibAction = QAction(self.tr("标定相机"), self)
        calibAction.setStatusTip(self.tr("标定相机"))
        self.connect(calibAction, SIGNAL("triggered()"), self.calib_Cam)

        # 动作: 播放白天演示视频
        dayDemoAction = QAction(self.tr("演示1"), self)
        self.connect(dayDemoAction, SIGNAL("triggered()"), self.dayDemo)


        # 动作: 打开位姿测量设置窗口
        estimateSettingAction = QAction(self.tr("位姿测量设置"), self)
        self.connect(estimateSettingAction, SIGNAL("triggered()"), self.estimateSetting)

        # Action: Select demo_path
        demoPathSettingAction = QAction(self.tr("演示路径设置"), self)
        self.connect(demoPathSettingAction, SIGNAL("triggered()"), self.setDemoPath)

        
        menubar = self.menuBar()
        calibMenu = menubar.addMenu(u'&标定')
        demoMenu = menubar.addMenu(u'&演示视频')
        settingMenu = menubar.addMenu(u'&设置')
        
        calibMenu.addAction(calibAction)
        demoMenu.addAction(dayDemoAction)
        demoMenu.addAction(demoPathSettingAction)
        settingMenu.addAction( estimateSettingAction)
        
    def start(self):
        self.play_flag = 1
        self.video = Video()
        self._timer1 = QTimer(self)
        try:
            self._timer1.timeout.connect(self.play)
        finally:
            self._timer1.start(0)
            self.update()

    def play(self):
        try:
            self.video.captureRawFrame()
            self.imageLabel.setPixmap(self.video.convertFrame())

        except TypeError:
            print "No frame"

    def playAndRecord(self):
        try:
            self.rec_video.captureRawFrame()
            self.rec_video.record()
            self.imageLabel.setPixmap(self.rec_video.convertFrame())
        except TypeError:
            print "No frame"

    def stop(self):
        if self.play_flag ==1:
            self._timer1.stop()
            self.video.vs.stop()
        elif self.play_flag == 2:
            self._timer1.stop()
            self.video.capture.release()
        elif self.play_flag == 3:
            self._timer1.stop()            
            self.rec_video.vs.stop()
            self.rec_video.writer.release()
        self.play_flag = 0


    def quit(self):
        try:
            self._timer1.stop()
        finally:
            sys.exit(0)

    def estimate(self):
        img = self.video.raw_img
        try:
            chessboard_h = self.settingDialog.height
            chessboard_w = self.settingDialog.width
            chessboard_size = self.settingDialog.size
            cmxDir = self.settingDialog.cmxDir
        except:
            self.settingDialog = settingDlg()
            self.settingDialog.show()
        pos = poseEstimate(img,chessboard_h, chessboard_w, chessboard_size, cmxDir)
        img = pos.solvePnP()

        # Save result to txt file in experiment_data
        self.saveData('test',pos.rvec_str,pos.tvec_str, pos.err_str)
        
        try:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            height, width = img.shape[:2]
            img = QImage(img,
                               width,
                               height,
                               QImage.Format_RGB888)
            img = QPixmap.fromImage(img)
        except:
            return None
        img = img.scaledToHeight(320)
        img = img.scaledToWidth(240)
        self.te1.setPixmap(img)
        if pos.ret ==1:
            self.te2.setText(self.tr("旋转向量为:"))
            #self.te2.append('')
            self.te2.append(pos.rvec_str)
            
            self.te2.append(self.tr("平移向量为:"))
            #self.te2.append('')
            self.te2.append(pos.tvec_str)
            self.te2.append('')
            self.te2.append(self.tr("重投影误差是:")+pos.err_str)
        else:
            self.te2.setText(self.tr("No Chessboard!"))

    def calib_Cam(self):
        '''
        打开标定对话框,并输入相关参数进行标定,标定结果被保存在./calibFile/calib.npz
        '''
        self.inputDialog = InputDlg()
        self.inputDialog.show()

    def calibCapture(self):
        '''
        每隔3秒拍摄一张照片,并保存在一个单独的文件夹中,一共拍摄15张
        与此同时用户应该手持标定板,不断摆出不同的位置和角度让相机拍摄。
        最后程序还应该输出一个包含了图片路径的list,用于calib_Cam的标定
        '''
        img = self.video.raw_img
        cv2.imwrite('./calibFile/calibImages/'+str(int(time.time()))+'.jpg', img)
        
    def recordVideo(self):
        self.play_flag = 3
        self.rec_video = recordVideo()
        self.rec_video.initRecord()
        self._timer1 = QTimer(self)
        try:
            self._timer1.timeout.connect(self.playAndRecord)
        finally:
            self._timer1.start(100)
            self.update()
    
    
    def dayDemo(self):
        '''
        播放提前录制好的白天标定板不断运动的图像
        '''
        self.startDemo(self.demo_path)

    def nightDemo(self):
        '''
        播放提前录制好的夜间标定板不断运动的视频
        '''
        pass

    def startDemo(self,file):
        self.play_flag = 2
        self.video = playDemoVideo(file)
        self._timer1 = QTimer(self)
        try:
            self._timer1.timeout.connect(self.play)
        finally:
            self._timer1.start(100)
            self.update()
            
    def saveData(self,experiment_name,rvec, tvec, error):
        f = open('./experiment_data/'+str(experiment_name)+'.txt','a')
        f.writelines(rvec+","+tvec+","+error+'\n')
        f.close()
    
    def estimateSetting(self):
        self.settingDialog=settingDlg()
        self.settingDialog.show()

    def setDemoPath(self):
        demo_QStringList = QFileDialog.getOpenFileNames(self,
                                             "多文件选择",
                                             "./demoVideo",
                                             "All Files (*);;AVI Files (*.avi)")
        self.demo_path = str(demo_QStringList.join("<join>")).split("<join>")[0]