# Table.py -- Pamhyr
# Copyright (C) 2023-2026  INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# -*- coding: utf-8 -*-

import logging

from functools import reduce
from tools import trace, timer

from PyQt5.QtCore import (
    Qt, QVariant, QAbstractTableModel,
    QCoreApplication, QModelIndex, pyqtSlot,
    QRect,
)

from PyQt5.QtGui import (
    QColor, QBrush,
)

from PyQt5.QtWidgets import (
    QDialogButtonBox, QPushButton, QLineEdit,
    QFileDialog, QTableView, QAbstractItemView,
    QUndoStack, QShortcut, QAction, QItemDelegate,
    QComboBox,
)

from Modules import Modules
from Checker.Checker import STATUS
from View.Tools.PamhyrTable import PamhyrTableModel

logger = logging.getLogger()


class TableModel(PamhyrTableModel):
    def data(self, index, role):
        row = index.row()
        column = index.column()

        if role == Qt.ForegroundRole:
            if self._headers[column] == "status":
                color = Qt.gray

                if self._data[row].is_ok():
                    color = Qt.green
                elif self._data[row].is_warning():
                    color = QColor("orange")
                elif self._data[row].is_error():
                    color = Qt.red

                return QBrush(color)
            return QVariant()

        if role != Qt.ItemDataRole.DisplayRole:
            return QVariant()

        if self._headers[column] == "name":
            return self._data[row].name
        if self._headers[column] == "status":
            return self._data[row].summary

        return QVariant()


class TabTableModel(PamhyrTableModel):
    def _setup_lst(self):
        self._lst = self._opt_data

    def data(self, index, role):
        row = index.row()
        column = index.column()

        if role == Qt.ForegroundRole:
            if self._headers[column] == "type":
                return QVariant()

            color = Qt.gray
            status, _ = self.compute_status(row, column)

            if status is STATUS.OK:
                color = Qt.green
            elif status is STATUS.WARNING:
                color = QColor("orange")
            elif status is STATUS.ERROR:
                color = Qt.red

            return QBrush(color)

        if role == Qt.ItemDataRole.DisplayRole:
            if self._headers[column] == "type":
                return self.module_display_name(self._opt_data[row])

            value = "UNKNOWN"
            status, _ = self.compute_status(row, column)

            if status is STATUS.OK:
                value = "OK"
            elif status is STATUS.WARNING:
                value = "WARNING"
            elif status is STATUS.ERROR:
                value = "ERROR"

            return value

        return QVariant()

    def module_display_name(self, module):
        return Modules.modelling_display_name()[module]

    def get_checkers(self, row, column):
        module = self._opt_data[row]
        solver = self._headers[column]

        checkers = filter(
            lambda checker: checker._modules is module,
            filter(
                lambda checker: checker._solver is solver,
                self._data
            )
        )

        return checkers

    def get_checkers_from_indexes(self, indexes):
        lst = []

        for index in indexes:
            row = index.row()
            column = index.column()

            lst += list(self.get_checkers(row, column))

        return lst

    def compute_status(self, row, column):
        checkers = self.get_checkers(row, column)

        checkers_status = list(
            map(
                lambda c: c._status,
                checkers
            )
        )

        status = STATUS.UNKNOWN
        if len(checkers_status) > 0:
            status = reduce(lambda acc, c: acc | c, checkers_status)

        logger.debug(f"Checkers: {row}, {column}: {checkers_status} {status}")

        return status, checkers_status
