#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：MainController.py
@Description：
@Author：XSH
@Time：2025/12/5 9:03
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import sys
import os
from PyQt5                                              import Qt                            #
from AppSettings.Settings                               import *                             #
from AppInterfaces.utils                                import *                             #
from AppCore.Levels                                     import *                             #
from AppUtils.UiUtils                                   import UiUtils                       #
from AppCore.DBModels                                   import *                             #
from AppUtils.utils                                     import *                             #
from AppInterfaces.UiInterface                          import UiInterface, AppUiProperty    #
from AppBackEnd.AppBusinessInterface                    import AppBusinessInterface          #
from AppHeadEnd.ControllerViews.CameraController        import CameraController              #
from AppHeadEnd.ControllerViews.MainOperationView       import MainOperationView             #
from AppHeadEnd.ControllerFrames.ControlFrameInterface  import ControlFrameInterface         #
from AppHeadEnd.ControlWindows.OperationControllerWidget   import OperationControllerWidget        #
from AppHeadEnd.ControllerViews.ChamberDropTrayDialog   import ChamberDropTrayDialog         #
class MainController(Qt.QWidget, ControlFrameInterface, SingletonInterface):
    Locker: Qt.QMutex = Qt.QMutex()

    @classmethod
    def GetInstance(cls, business: AppBusinessInterface, parent: Qt.QObject = None, *args) -> 'MainController':
        return super(MainController, cls).GetInstance(*args, **{'business': business, 'parent': parent})

    Camera              : CameraController                      # 相机画面
    Operation           : MainOperationView                     # 操作按钮
    Controller          : OperationControllerWidget                # 调试界面
    Tray                : Qt.QSystemTrayIcon                    # 系统托盘
    Menu                : Qt.QMenu                              # 托盘菜单
    IconStartScanning   : Qt.QIcon                              # 开始扫描图标
    IconStopScanning    : Qt.QIcon                              # 停止扫描图标
    IconPauseScanning   : Qt.QIcon                              # 暂停扫描图标
    IconShowScanningUi  : Qt.QIcon                              # 显示界面图标
    IconShowDebugUi     : Qt.QIcon                              # 显示调试界面
    IconQuitScanning    : Qt.QIcon                              # 退出程序图标
    StatusTimer         : Qt.QTimer                             # 状态定时模块
    InterVal            : int               = 1000              # 定时时间间隔
    OilSwitchStatus     : bool                                  # 油泵状态
    YoutubeStatus       : bool                                  # 油管状态
    def __init__(self, business: AppBusinessInterface, parent: Qt.QObject = None, *args):
        super(MainController, self).__init__(parent=parent)
        self.Business = business
        self.Initialization("玻片扫描系统", self, parent)
        self.initWindowIcon()
        self.initWidgetStyle()

    def __del__(self):
        if self.oil_status:
            self.SlotOilSwitchButton()
        if self.hasStatusTimer and self.StatusTimer.isActive():
            self.StatusTimer.stop()

    def initValue(self):
        self.InterVal           = 1000
        self.OilSwitchStatus    = False
        self.YoutubeStatus      = False
        self.initCamera              ()
        self.initOperation           ()
        self.initController          ()
        self.initIconStartScanning   ()
        self.initIconStopScanning    ()
        self.initIconPauseScanning   ()
        self.initIconShowScanningUi  ()
        self.initIconShowDebugUi     ()
        self.initIconQuitScanning    ()
        self.initMenu                ()
        self.initTray                ()
        self.initStatusTimer         ()
        self.StatusTimer.start()
        self.Tray.setContextMenu(self.Menu)

    def initProperty(self):
        super(MainController, self).initProperty()
        self.setWindowTitle("医学显微图像扫描系统")
        HeadEndShowMode['DEBUG_SHOW'] = False
        if self.hasBusiness:
            self.business.UpdateDeviceStatus()
        self.Tray.show()
        self.setVisible(False)



    def initConnect(self):
        super(MainController, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        AppSlot.SlideTableNotEmptySignal.connect(slot=self.SlotSlideTableNotEmptySignal, type=TYPE)
        self.Tray.activated.connect(slot=self.SlotTrayActivated, type=TYPE)
        self.Operation.InitButton          .clicked.connect(slot=self.SlotInitButton          , type=TYPE)
        self.Operation.ClearErrorButton    .clicked.connect(slot=self.SlotClearErrorButton    , type=TYPE)
        self.Operation.OilSwitchButton     .clicked.connect(slot=self.SlotOilSwitchButton     , type=TYPE)
        self.Operation.YouTubeButton       .clicked.connect(slot=self.SlotYouTubeButton       , type=TYPE)
        self.Operation.PickTrayButton      .clicked.connect(slot=self.SlotPickTrayButton      , type=TYPE)
        self.Operation.DropTrayButton      .clicked.connect(slot=self.SlotDropTrayButton      , type=TYPE)
        self.Operation.ControllerButton    .clicked.connect(slot=self.SlotShowDebugUi         , type=TYPE)
        self.Operation.StartButton         .clicked.connect(slot=self.SlotStartScanning       , type=TYPE)
        self.Operation.PauseButton         .clicked.connect(slot=self.SlotPauseScanning       , type=TYPE)
        self.Operation.StopButton          .clicked.connect(slot=self.SlotStopScanning        , type=TYPE)
        self.Operation.JumpButton          .clicked.connect(slot=self.SlotJumpButton          , type=TYPE)

    def SlotSlideTableNotEmptySignal(self):
        if not self.isAvailable():
            return
        if HeadEndShowMode.get('DEBUG_SHOW', False):
            dialog: ChamberDropTrayDialog = ChamberDropTrayDialog()

            dialog.exec()

    def SlotInitButton(self):
        if not self.isAvailable():
            return
        if not self.business.hasDevices:
            return
        self.business.devices.waitForDeviceHome()

    def SlotClearErrorButton(self):
        if not self.hasBusiness:
            return
        self.business.clearWarning()

    def SlotOilSwitchButton(self):
        if not self.isAvailable():
            return
        if not self.hasDetection:
            return
        from AppCore.AppDBModels.ConfigModels.AnointingModel import AnointingModel
        Anointing: AnointingModel = AnointingModel.getConfig(ObjectiveLevel.Objective1)
        if self.oil_status:
            self.OilSwitchStatus = False
        else:
            self.OilSwitchStatus = True
            self.detection.set_oil_speed(Anointing.OilDropingSpeed)
        self.detection.oil_switch(self.oil_status)

    def SlotYouTubeButton(self):
        if not self.isAvailable():
            return
        if not self.hasDetection:
            return
        self.YoutubeStatus = self.detection.get_oil_status()
        self.Operation.setYouTubeStatus(self.YoutubeStatus)

    def SlotPickTrayButton(self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        if self.business.status.isPause or self.business.status.isRunning:
            return
        tray_status: bool = self.axis_h.get_tray_place_status()
        if tray_status:
            self.axis_h.waitmove_to_back()
        tray_status = self.axis_h.get_tray_place_status()
        if tray_status:
            return
        self.business.status.setRunning(True)
        chamber_number: int = int(self.Operation.EditChamberNumber.value())
        self.business.PickChamberSlide(chamber_number, False, False)
        self.business.status.setRunning(False)

        pass
    def SlotDropTrayButton(self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        if self.business.status.isPause or self.business.status.isRunning:
            return
        self.business.status.setRunning(True)
        chamber_number: int = int(self.Operation.EditChamberNumber.value())
        isWrong = self.business.DropChamberSlide(chamber_number, False, False)
        if RECODE_SUCCEED == isWrong:
            self.axis_h.wait_empty_hook_return()

        self.business.status.setRunning(False)


    def initWidgetStyle(self):
        self.setStyleSheet(UiUtils.getWidgetStyle())

    def closeEvent(self, ev: Qt.QCloseEvent) -> None:
        ev.ignore()
        self.hide()
        isVisible = False
        HeadEndShowMode['DEBUG_SHOW'] = isVisible
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        try:
            if isVisible:
                AppSlot.CameraUiSignal.connect(slot=self.Camera.SlotCameraUiSignal, type=TYPE)
            else:
                AppSlot.CameraUiSignal.disconnect(self.Camera.SlotCameraUiSignal)
        except Exception as e:
            AppUtils.print_Exception(e)

    def show(self) -> None:
        try:
            if not self.hasTray:
                self.initValue()
            self.Tray.show()
        except Exception as e:
            AppUtils.print_Exception(e)

    def SlotTrayActivated(self, reason: Qt.QSystemTrayIcon.ActivationReason):
        pass

    def SlotShowScanningUi    (self):
        """显示扫描界面"""
        isVisible: bool = self.isVisible()
        isVisible = not isVisible
        HeadEndShowMode['DEBUG_SHOW'] = isVisible
        self.setVisible(isVisible)
        UiUtils.center_on_screen(self)
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        try:
            if isVisible:
                AppSlot.CameraUiSignal.connect(slot=self.Camera.SlotCameraUiSignal, type=TYPE)
            else:
                AppSlot.CameraUiSignal.disconnect(self.Camera.SlotCameraUiSignal)
        except Exception as e:
            AppUtils.print_Exception(e)

    def SlotStartScanning     (self):
        """开始扫描"""
        self.initBusiness()
        status: int = self.business.status.getRunStatus()
        if status == 0:
            CustomScanningModel.initAutoScanCode()
            AppSlot.StartScanningSignal.emit({'isAuto': True})
            AppTimeLoop.processGlobalEvents(3000)
            self.SlotUpdateStatus()
            return






    def SlotStopScanning      (self):
        """停止扫描"""
        self.initBusiness()
        self.business.status.setExit(True)
        self.SlotUpdateStatus()

    def SlotPauseScanning     (self):
        """界停扫描"""
        self.initBusiness()
        isPause = self.business.status.isPause
        isPause = not isPause
        if not isPause:
            self.business.clearWarning()
        else:
            self.business.status.setPause(isPause)
        self.SlotUpdateStatus()

    def SlotJumpButton(self):
        """跳过扫描"""
        self.initBusiness()
        isJumpScanning = self.business.status.isJumpScanning
        if not isJumpScanning:
            self.business.status.setJumpScanning(True)

        self.SlotUpdateStatus()

    def SlotShowDebugUi(self):
        """调试界面巾"""
        self.initController()
        isVisible: bool = self.Controller.isVisible()
        isVisible = not isVisible
        self.Controller.setVisible(isVisible)
        UiUtils.center_on_screen(self.Controller)

    def SlotQuitScanning(self):
        """退出系统"""
        AppSlot.ApplicationSignal.emit('', '')
        if self.hasTray:
            self.Tray.hide()
        if AppSlot.Application is not None:
            AppSlot.Application.quit()
        sys.exit(0)

    def initLayouts(self):
        if self.hasWindowLayouts:
            return
        main_layout: Qt.QGridLayout = Qt.QGridLayout()
        main_layout.setSpacing(2)
        main_layout.setContentsMargins(2, 2, 2, 2)
        left_layout: Qt.QVBoxLayout = Qt.QVBoxLayout()
        left_layout.setSpacing(2)
        left_layout.setContentsMargins(2, 2, 2, 2)
        right_layout: Qt.QVBoxLayout = Qt.QVBoxLayout()
        right_layout.setSpacing(2)
        right_layout.setContentsMargins(2, 2, 2, 2)
        right_layout.setAlignment(Qt.Qt.AlignTop)
        left_layout.addWidget(self.Camera   )
        right_layout.addWidget(self.Operation)

        main_layout.addLayout(left_layout, 0, 0, -1, 1)
        main_layout.addLayout(right_layout, 0, 1, -1, 1)
        self.setLayout(main_layout)




    def initCamera              (self):
        if not self.hasCamera              :
            self.Camera               = CameraController(self)

    def initOperation           (self):
        if not self.hasOperation           :
            self.Operation            = MainOperationView(self)

    def initController(self):
        if not self.hasController:
            self.Controller = OperationControllerWidget.GetInstance(self.business, parent=None)
            self.Controller.setVisible(False)

    def initTray(self):
        if not self.hasTray:
            self.initWindowIcon()
            self.Tray = Qt.QSystemTrayIcon(self)
            self.Tray.setIcon(self.WindowIcon)
            self.Tray.setToolTip("医学显微图像扫描系统")

    def initMenu(self):
        if not self.hasMenu:
            self.Menu = Qt.QMenu        (self)
            self.initIcons()
            show_action : Qt.QAction = Qt.QAction(self.IconShowScanningUi , '扫描界面', self.Menu)
            scan_action : Qt.QAction = Qt.QAction(self.IconStartScanning  , '开始扫描', self.Menu)
            exit_action : Qt.QAction = Qt.QAction(self.IconStopScanning   , '停止扫描', self.Menu)
            pause_action: Qt.QAction = Qt.QAction(self.IconPauseScanning  , '暂停扫描', self.Menu)
            debug_action: Qt.QAction = Qt.QAction(self.IconShowDebugUi    , '调试界面', self.Menu)
            quit_action : Qt.QAction = Qt.QAction(self.IconQuitScanning   , '退出系统', self.Menu)
            TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
            show_action  .triggered.connect(slot=self.SlotShowScanningUi    , type=TYPE)
            scan_action  .triggered.connect(slot=self.SlotStartScanning     , type=TYPE)
            exit_action  .triggered.connect(slot=self.SlotStopScanning      , type=TYPE)
            pause_action .triggered.connect(slot=self.SlotPauseScanning     , type=TYPE)
            debug_action .triggered.connect(slot=self.SlotShowDebugUi       , type=TYPE)
            quit_action  .triggered.connect(slot=self.SlotQuitScanning      , type=TYPE)
            self.Menu.addActions([show_action  ,scan_action  ,exit_action  ,pause_action ,debug_action ,quit_action  ])

    def initIconStartScanning   (self):
        if not self.hasIconStartScanning   :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/start.png')
            self.IconStartScanning    = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIconStopScanning    (self):
        if not self.hasIconStopScanning    :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/stop.png')
            self.IconStopScanning     = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIconPauseScanning   (self):
        if not self.hasIconPauseScanning   :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/Pause.png')
            self.IconPauseScanning    = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIconShowScanningUi  (self):
        if not self.hasIconShowScanningUi  :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/show.png')
            self.IconShowScanningUi   = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIconShowDebugUi     (self):
        if not self.hasIconShowDebugUi     :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/debug.png')
            self.IconShowDebugUi      = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIconQuitScanning    (self):
        if not self.hasIconQuitScanning    :
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/quit.png')
            self.IconQuitScanning     = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))

    def initIcons(self):
        self.initIconShowScanningUi ()
        self.initIconStartScanning  ()
        self.initIconStopScanning   ()
        self.initIconPauseScanning  ()
        self.initIconShowDebugUi    ()
        self.initIconQuitScanning   ()

    def SlotUpdateStatus(self):
        if not self.hasBusiness:
            return

        status: int = self.business.status.getRunStatus()
        if status == RunStatusLevel.PauseRunning:
            self.Operation.PauseButton.setText('继续扫描')
        else:
            self.Operation.PauseButton.setText('暂停扫描')

        if status == RunStatusLevel.Running:
            self.Operation.StartButton.setEnabled(False)
            self.Operation.StopButton.setEnabled(True)
        elif status == RunStatusLevel.ExitRunning:
            self.Operation.StartButton.setEnabled(True)
            self.Operation.StopButton.setEnabled(False)
        elif status == RunStatusLevel.PauseRunning:
            self.Operation.StartButton.setEnabled(False)
            self.Operation.StopButton.setEnabled(True)
        else:
            self.Operation.StartButton.setEnabled(True)
            self.Operation.StopButton.setEnabled(True)
        if self.hasDetection:
            self.OilSwitchStatus    = self.detection.get_oil_switch()
            self.YoutubeStatus      = self.detection.get_oil_status()
            self.Operation.setOilSwitchStatus(self.OilSwitchStatus)
            self.Operation.setYouTubeStatus  (self.YoutubeStatus)
        isJumpScanning = self.business.status.isJumpScanning
        if isJumpScanning:
            self.Operation.JumpButton.setEnabled(False)
        else:
            self.Operation.JumpButton.setEnabled(True)


    def initStatusTimer(self):
        if not self.hasStatusTimer:
            if not self.hasInterVal:
                self.InterVal = 1000
            self.StatusTimer = Qt.QTimer()
            self.StatusTimer.setInterval(self.InterVal)
            TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
            self.StatusTimer.timeout.connect(slot=self.SlotUpdateStatus, type=TYPE)

    def loadWindowIcon(self):
        if not self.has_WindowIcon:
            import sys
            info: Qt.QFileInfo = Qt.QFileInfo(f'{Qt.QFileInfo(sys.argv[0]).absolutePath()}/Resource/Icon/eraser.png')
            self.WindowIcon = Qt.QIcon(Qt.QPixmap(info.absoluteFilePath()))


    @property
    def hasCamera              (self) -> bool:
        return hasattr(self, 'Camera'             ) and isinstance(self.Camera              , CameraController      )

    @property
    def hasOperation           (self) -> bool:
        return hasattr(self, 'Operation'          ) and isinstance(self.Operation           , MainOperationView     )

    @property
    def hasController          (self) -> bool:
        return hasattr(self, 'Controller'         ) and isinstance(self.Controller          , OperationControllerWidget)

    @property
    def hasTray                (self) -> bool:
        return hasattr(self, 'Tray'               ) and isinstance(self.Tray                , Qt.QSystemTrayIcon    )

    @property
    def hasMenu                (self) -> bool:
        return hasattr(self, 'Menu'               ) and isinstance(self.Menu                , Qt.QMenu              )

    @property
    def hasIconStartScanning   (self) -> bool:
        return hasattr(self, 'IconStartScanning'  ) and isinstance(self.IconStartScanning   , Qt.QIcon              )

    @property
    def hasIconStopScanning    (self) -> bool:
        return hasattr(self, 'IconStopScanning'   ) and isinstance(self.IconStopScanning    , Qt.QIcon              )

    @property
    def hasIconPauseScanning   (self) -> bool:
        return hasattr(self, 'IconPauseScanning'  ) and isinstance(self.IconPauseScanning   , Qt.QIcon              )

    @property
    def hasIconShowScanningUi  (self) -> bool:
        return hasattr(self, 'IconShowScanningUi' ) and isinstance(self.IconShowScanningUi  , Qt.QIcon              )

    @property
    def hasIconShowDebugUi     (self) -> bool:
        return hasattr(self, 'IconShowDebugUi'    ) and isinstance(self.IconShowDebugUi     , Qt.QIcon              )

    @property
    def hasIconQuitScanning    (self) -> bool:
        return hasattr(self, 'IconQuitScanning'   ) and isinstance(self.IconQuitScanning    , Qt.QIcon              )

    @property
    def hasStatusTimer          (self) -> bool:
        return hasattr(self, 'StatusTimer'         ) and isinstance(self.StatusTimer         , Qt.QTimer             )


    @property
    def hasInterVal(self) -> bool:
        return hasattr(self, 'InterVal'         ) and isinstance(self.InterVal         , (int, float))

    @property
    def hasOilSwitchStatus (self) -> bool:
        return hasattr(self, 'OilSwitchStatus' ) and isinstance(self.OilSwitchStatus , (int, bool))

    @property
    def hasYoutubeStatus   (self) -> bool:
        return hasattr(self, 'YoutubeStatus'   ) and isinstance(self.YoutubeStatus   , (int, bool))


    @property
    def oil_status(self) -> bool:
        return self.OilSwitchStatus if self.hasOilSwitchStatus else False