from qgis.PyQt import QtCore, QtGui

from PreCourlis.core import is_null

from PreCourlis.core.section_utils import check_section


class PointsTableModel(QtCore.QAbstractTableModel):
    _NB_EXTRA_COLS = 3

    def __init__(self, parent=None):
        super().__init__(parent)
        self.section = None
        self.property_list = []
        self.valid_section_values = [[]]

    def set_section(self, section):
        self.beginResetModel()
        self.section = section
        self.valid_section_values = check_section(self.section)
        self.columns = ["abs_lat", "topo_bath", "zfond"] + section.layer_names
        self.endResetModel()

    def set_validation_data(self, valid_section_values):
        self.beginResetModel()
        self.valid_section_values = valid_section_values
        self.endResetModel()

    def rowCount(self, parent=QtCore.QModelIndex()):
        if self.section is None:
            return 0
        return len(self.section.distances)

    def columnCount(self, parent=QtCore.QModelIndex()):
        if self.section is None:
            return 0
        return len(self.columns)

    def headerData(self, section, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole):
        if role == QtCore.Qt.ItemDataRole.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.columns[section]
            if orientation == QtCore.Qt.Vertical:
                return str(section)

    def flags(self, index):
        if index.isValid():
            if index.column() >= 1:
                return (
                    QtCore.Qt.ItemIsEnabled
                    | QtCore.Qt.ItemIsSelectable
                    | QtCore.Qt.ItemIsEditable
                )
            else:
                return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
        else:
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole):
        if role in (
            QtCore.Qt.ItemDataRole.DisplayRole,
            QtCore.Qt.EditRole,
        ):
            column = self.columns[index.column()]
            if column == "abs_lat":
                v = self.section.distances[index.row()]
            elif column == "zfond":
                v = self.section.z[index.row()]
            elif column == "topo_bath":
                v = self.section.topo_bath[index.row()]
            else:
                v = self.section.layers_elev[index.column() - self._NB_EXTRA_COLS][
                    index.row()
                ]

        if role == QtCore.Qt.ItemDataRole.DisplayRole:
            if v is None:
                return None

            if isinstance(v, str):
                return v

            return str(round(v, 3))

        if role == QtCore.Qt.EditRole:
            return v

        if role == QtCore.Qt.BackgroundRole:
            column = self.columns[index.column()]

            if column in ("abs_lat", "topo_bath"):
                return None

            if column == "zfond":
                if self.valid_section_values[0][index.row()]:
                    return None
                else:
                    return QtGui.QBrush(QtGui.QColor(255, 0, 0))

            if index.column() >= self._NB_EXTRA_COLS:
                if self.valid_section_values[index.column() - self._NB_EXTRA_COLS + 1][
                    index.row()
                ]:
                    return None
                else:
                    return QtGui.QBrush(QtGui.QColor(255, 0, 0))

    def setData(self, index, value, role):
        if index.isValid() and role == QtCore.Qt.EditRole:
            v = value if not is_null(value) else None

            column = self.columns[index.column()]
            if column == "abs_lat":
                self.section.distances[index.row()] = v
            elif column == "zfond":
                self.section.z[index.row()] = v
            elif column == "topo_bath":
                self.section.topo_bath[index.row()] = v
            else:
                self.section.layers_elev[index.column() - self._NB_EXTRA_COLS][
                    index.row()
                ] = v

            self.dataChanged.emit(index, index, [QtCore.Qt.EditRole])
            return True

        return False
