import os, sys
if 'SUMO_HOME' in os.environ:
    tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
    sys.path.append(tools)
else:
    print("please declare environment variable 'SUMO_HOME'")

from PySide6.QtCore import Qt, QTimer, QElapsedTimer, QThread, Slot, Signal, QPointF
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QFileDialog
from PySide6.QtGui import QSurfaceFormat, QAction
from window import Ui_MainWindow

from mainLoop import mainLoop

class MainWindow(QMainWindow):
    stopMainLoopTimer = Signal()
    startMainLoop = Signal()
    setPhTimerInterval = Signal(int)
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setFocus()

        self.updateThread = QThread()

        self.mainLoop = mainLoop(self)

        self.mainLoop.moveToThread(self.updateThread)
        self.updateThread.started.connect(self.mainLoop.start)

        fileMenu = self.menuBar().addMenu("&File")
        openMenu = fileMenu.addMenu("&Open")

        openNet = QAction("&Open Network",self)
        openNet.setStatusTip("Open Network file (.net.xml)")
        openNet.triggered.connect(self.openNetwork)
        openMenu.addAction(openNet)

        openVeh = QAction("&Open Vehicles",self)
        openVeh.setStatusTip("Open Vehicle description (.rou.xml)")
        openVeh.triggered.connect(self.openVehicles)
        openMenu.addAction(openVeh)

        self.drawTimer = QTimer(self)
        self.drawTimer.timeout.connect(self.ui.mainSurf.update)
        self.drawTimer.timeout.connect(self.updateFPS)
        self.drawTimer.start(1000/60)

        self.ui.startButton.clicked.connect(self.mainLoop.startTimer)
        self.ui.stopButton.clicked.connect(self.mainLoop.stopTimer)

        self.startMainLoop.connect(self.mainLoop.startTimer)
        self.setPhTimerInterval.connect(self.mainLoop.setTimerInterval)

        self.stopMainLoopTimer.connect(self.mainLoop.stopTimer)

        self.ui.mainFPS_set.valueChanged.connect(self.drawTimer.setInterval)
        self.ui.physicsFPS_set.valueChanged.connect(self.mainLoop.setTimerInterval)

        self.fpsTimer = QElapsedTimer()
        self.fpsTimer.start()
        self.fpsAverage = 0

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape or e.key() == Qt.Key_Q:
            self.close()
        elif e.key() == Qt.Key_V:
            self.mainLoop.controller.vroomEnable = not self.mainLoop.controller.vroomEnable
        elif e.key() == Qt.Key_G:
            self.startMainLoop.emit()
        elif e.key() == Qt.Key_E:
            self.setPhTimerInterval.emit(0)
        elif e.key() == Qt.Key_D:
            self.setPhTimerInterval.emit(17)
        elif e.key() == Qt.Key_F:
            self.setPhTimerInterval.emit(500)
        elif e.key() == Qt.Key_C:
            self.mainLoop.controller.dt = 0.3
        elif e.key() == Qt.Key_P:
            self.mainLoop.controller.dt = 1/60
        else:
            self.mainLoop.quickLoad(e.key())

    def mousePressEvent(self, QMouseEvent):
        tran = self.ui.mainSurf.transform.inverted()[0]
        worldPoint = tran.map(QMouseEvent.position() - QPointF(5, 30))
        self.mainLoop.controller.selectClosest(worldPoint)
        self.ui.mainSurf.debugPoint = worldPoint

    def updateFPS(self):
        self.fpsAverage += 1
        if(self.fpsAverage != 32):
            return
        self.fpsAverage = 0
        widget = self.findChild(QLabel,"mainFps")
        t = self.fpsTimer.restart()/32
        if(t == 0):
            return
        widget.setText(f"fps : {1000/t:.1f}")
        widget.update()

        widget = self.findChild(QLabel, "timeStopped")
        controller = self.mainLoop.controller
        if controller.carsDestroyed==0:
            return
        averageTimeStopped = controller.totalStopped / controller.carsDestroyed
        speedPercentage = controller.speedPercentageTotal / controller.carsDestroyed
        newline = '\n'
        widget.setText(f"temps : {controller.t} \ntemps d'arrêt : {averageTimeStopped:.2f}s/voiture \n<vitesse/vitesse max>T : {speedPercentage:.2f} \nbacklog total : {controller.getFlowBacklog():.2f} \n{newline.join(f'{f.id} : {f.backlog(controller.t):.2f}' for f in controller.flows)}")

    @Slot(int)
    def updatePhysicsFps(self,t):
        widget = self.findChild(QLabel,"physicsFPS")
        if(t == 0):
            return
        dt = self.mainLoop.controller.dt
        widget.setText(f"ph fps : {1000/t:.1f}, speedup : {1000/t * dt:.1f}")

    def openNetwork(self):
        filename = QFileDialog.getOpenFileName(self,"Open Network", "./", "Network File (*.net.xml)")
        self.mainLoop.openNetwork(filename[0])

    def openVehicles(self):
        filename = QFileDialog.getOpenFileName(self,"Open Vehicle trip description", "./", "Route File (*.rou.xml)")
        self.mainLoop.openVehicles(filename[0])

    def close(self):
        self.stopMainLoopTimer.emit()
        self.updateThread.quit()
        self.updateThread.wait()
        super().close()



if __name__ == "__main__":
    app = QApplication()

    f = QSurfaceFormat()
    f.setDepthBufferSize(24)
    f.setVersion(3, 2)
    f.setSamples(4)
    f.setProfile(QSurfaceFormat.CoreProfile)
    QSurfaceFormat.setDefaultFormat(f)

    window = MainWindow()
    window.show()
    window.updateThread.start()
    
    sys.exit(app.exec())
