#!D:/IDE/anaconda3/envs python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName：SlideModelView.py\n
 @DateTime: 2025/7/26 10:46\n
 @Author  ：xsh
"""
from PyQt5 import Qt
from AppSettings.Settings import SIGNAL_CONNECTION_TYPE
from AppCore.Levels import *
from AppCore.DBModels import *
from AppUtils.UiUtils import UiUtils
from AppInterfaces.UiInterface import UiInterface, AppUiProperty, AppUtils, AppConvert
from AppHeadEnd.Commons.ActionMenuBar import ActionMenuBar

class SlideModelView(Qt.QTableWidget, UiInterface):
    ActionMovesSignal   : Qt.pyqtSignal = Qt.pyqtSignal(object)
    Model               : SlideModelInterface   #
    MenuBar             : ActionMenuBar         #
    def __init__(self, data_model: SlideModelInterface = None, parent: Qt.QWidget = None):
        super(SlideModelView, self).__init__(parent=parent)
        self.Model = data_model if isinstance(data_model, SlideModelInterface) else None
        self.Initialization('SlideModelView', self, parent)
        self.initWidgetStyle()
        # self.flushFrame()

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

    def initConnect(self):
        super(SlideModelView, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        self.MenuBar       .ActionSignal.connect(slot=self.ActionSignalSlot             , type=TYPE)
        self.cellChanged                .connect(slot=self.cellChangedSlot              , type=TYPE)

    def ActionSignalSlot (self, signal: str):
        if not isinstance(signal, str):
            return
        self.initModel()
        # '刷新', '移动', '添加', '保存', '删除', '清空'
        if '刷新' == signal:
            self.flushFrame()
            return
        if '添加' == signal:
            model = self.Model.getMaxPrimaryItem()
            if not model:
                return
            self.append_new_action(model)
            return
        if '清空' == signal:
            self.clearTable()
            return

        item: Qt.QTableWidgetItem = self.currentItem()
        if not item:
            return
        row = self.row(item)
        if '保存' == signal:
            self.update_row_action(row)
            return
        if '删除' == signal:
            self.remove_row_action(row)
            return
        request: SlideModelInterface = self.get_row_action(row)
        if not isinstance(request, SlideModelInterface):
            return
        if '移动' == signal:
            self.ActionMovesSignal.emit(request)
            return

    def cellChangedSlot  (self, row: int, column: int):
        self.initModel()
        self.update_row_action(row)

    def ActionChangedSlot(self, widget: Qt.QWidget, row_number: int, slide: SlideModelInterface):
        if id(self) != id(widget):
            return
        if not isinstance(slide, SlideModelInterface):
            return
        model: SlideModelInterface = self.get_row_action(row_number)
        if not model:
            return
        model.as_field(slide.to_field(False))
        if not model or not model.has_ID:
            return
        model.model_update(model.to_field(False), self.Model.__class__.ID == model.ID)
        self.updateTableData()
        pass

    def mousePressEvent(self, e: Qt.QMouseEvent) -> None:
        if e.button() == Qt.Qt.RightButton:
            self.IsPress = True
        super(SlideModelView, self).mousePressEvent(e)

    def mouseReleaseEvent(self, e: Qt.QMouseEvent) -> None:
        if e.button() == Qt.Qt.RightButton:
            if self.IsPress:
                self.MenuBar.draw(e.globalPos())
                self.IsPress = False
        super(SlideModelView, self).mouseReleaseEvent(e)

    """刷新"""
    def flushFrame(self):
        self.updateTableData()

    """删除"""
    def remove_row_action(self, row: int):
        model = self.get_row_action(row)
        if not model or not model.has_ID:
            return
        model.remove(self.Model.__class__.ID ==model.ID)
        self.updateTableData()
    """清空"""
    def clearTable(self):
        self.initModel()
        self.Model.clear()
        self.updateTableData()
    """添加"""
    def append_new_action(self, slide: SlideModelInterface):
        if isinstance(slide, SlideModelInterface):
            model = self.Model.copy()
            model.as_field(slide.to_field(False))
            self.Model.append_all([model])
            self.updateTableData()

    """保存"""
    def update_row_action(self, row: int):
        model = self.get_row_action(row)
        if not model or not model.has_ID:
            return
        model.model_update(model.to_field(False), self.Model.__class__.ID == model.ID)
        self.updateTableData()

    def updateTableData(self):
        self.initModel()
        model_type = self.Model.__class__
        models: list[model_type] = self.Model.all()
        if models is None:
            return
        self.blockSignals(True)
        self.setRowCount(len(models))
        for row, action in enumerate(models):
            self.append_row_action(row, action)
            Qt.QCoreApplication.processEvents(Qt.QEventLoop.AllEvents, 50)
        self.blockSignals(False)

    def append_row_action(self, row: int, slide: SlideModelInterface):
        buffer: object
        item: Qt.QTableWidgetItem
        box: Qt.QComboBox
        for col, _property in enumerate(self.Model.__field__):
            buffer = getattr(slide, _property, None)
            item = Qt.QTableWidgetItem()
            item.setData(Qt.Qt.UserRole, buffer)
            if isinstance(buffer, float):
                item.setData(Qt.Qt.DisplayRole, buffer)
            else:
                item.setData(Qt.Qt.DisplayRole, buffer)
            if buffer is not None:
                item.setFlags(item.flags() | Qt.Qt.ItemIsEditable)
            else:
                item.setFlags(item.flags() & (~Qt.Qt.ItemIsEditable))
            self.setTableWidgetItem(row, col, self, item)

    def get_row_action(self, row: int) -> SlideModelInterface:
        self.initModel()
        model_type = self.Model.__class__
        model: model_type = self.Model.copy()

        item: Qt.QTableWidgetItem
        box: Qt.QComboBox
        for col, _property in enumerate(self.Model.__field__):
            item = self.item(row, col)
            self.update_item(row, col, item, model)

        return model
        pass

    def refresh_row_col_action(self, row: int, col: int, model: SlideModelInterface):
        if not isinstance(model, SlideModelInterface):
            return
        if 0 <= col < len(self.Model.__field__):
            item: Qt.QTableWidgetItem
            box: Qt.QComboBox
            _property: str = self.Model.__field__[col]
            item = self.item(row, col)
            self.update_item(row, col, item, model)


    def update_item(self, row: int, col: int, item: Qt.QTableWidgetItem, model: SlideModelInterface):
        if not isinstance(item, Qt.QTableWidgetItem) or not isinstance(model, SlideModelInterface):
            return
        if not isinstance(row, int) or not isinstance(col, int):
            return
        if  0 <= col < len(self.Model.__field__):
            _property: str = self.Model.__field__[col]
            buffer = item.data(Qt.Qt.DisplayRole)
            setattr(model, _property, buffer)

    @staticmethod
    def setTableWidgetComboBox(row: int, column: int, table: Qt.QTableWidget, box: Qt.QComboBox):
        if not isinstance(row, int) or not isinstance(column, int):
            return
        if not isinstance(table, Qt.QTableWidget) or not isinstance(box, Qt.QComboBox):
            return
        table.setCellWidget(row, column, box)

    @staticmethod
    def setTableWidgetItem(row: int, column: int, table: Qt.QTableWidget, item: Qt.QTableWidgetItem):
        if not isinstance(row, int) or not isinstance(column, int):
            return
        if not isinstance(table, Qt.QTableWidget) or not isinstance(item, Qt.QTableWidgetItem):
            return
        table.setItem(row, column, item)

    def initValue(self):
        super(SlideModelView, self).initValue()
        self.initMenuBar    ()

    def initProperty(self):
        super(SlideModelView, self).initProperty()
        if not self.hasModel:
            self.initModel()
        # 设置全部单元格可编辑
        max_length: int = len(self.Model.__field__)
        self.setColumnCount(max_length)
        self.setHorizontalHeaderLabels(self.Model.__field__)
        header = self.horizontalHeader()
        header.setSectionResizeMode(Qt.QHeaderView.Stretch)  # Make columns stretch to fill width
        header.setSectionResizeMode(0, Qt.QHeaderView.Interactive)
        header.setStretchLastSection(True)  # Stretch last column
        header.setSectionResizeMode(Qt.QHeaderView.Custom)
        # 设置表头字体大小
        headerFont = header.font()
        headerFont.setPixelSize(10)
        header.setFont(headerFont)

        self.setHorizontalHeader(header)
        for index, _property in enumerate(self.Model.__field__):
            self.setColumnWidth(index, 150)
        self.setMinimumWidth(800)
        self.setMinimumHeight(200)
        # Set fixed row height
        self.verticalHeader().setDefaultSectionSize(40)
        # Set table properties
        self.setSelectionBehavior(Qt.QTableWidget.SelectRows)  # Select entire rows
        self.setSelectionMode(Qt.QTableWidget.SingleSelection)  # Single row selection
        self.setEditTriggers(Qt.QTableWidget.CurrentChanged)  # Read-only
        self.setAlternatingRowColors(False)  # 禁用隔行变色
        self.setShowGrid(True)  # Show grid lines
        self.verticalHeader().setVisible(False)  # Hide row numbers
        header.setSectionResizeMode(Qt.QHeaderView.Interactive)


    def initModel   (self):
        if not self.hasModel  :
            self.Model   = SlideModel()
    def initMenuBar (self):
        if not self.hasMenuBar:
            self.MenuBar = ActionMenuBar(signals=['刷新', '移动', '添加', '保存', '删除', '清空'])

    @property
    def hasModel   (self) -> bool:
        return hasattr(self, 'Model'    ) and isinstance(self.Model   , SlideModelInterface  )

    @property
    def hasMenuBar (self) -> bool:
        return hasattr(self, 'MenuBar'  ) and isinstance(self.MenuBar , ActionMenuBar        )
