# Window.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
import traceback

from tools import trace, timer

from View.Tools.PamhyrWindow import PamhyrWindow
from View.Tools.PamhyrPythonEditor import PamhyrPythonEditor
from View.Debug.Table import TableModel

from PyQt5.QtGui import (
    QKeySequence,
)

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

from PyQt5.QtWidgets import (
    QDialogButtonBox, QPushButton, QLineEdit,
    QFileDialog, QTableView, QAbstractItemView,
    QUndoStack, QShortcut, QAction, QItemDelegate,
    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
    QProgressBar, QLabel, QTextEdit, QHBoxLayout,
)

from PyQt5.Qsci import QsciScintilla, QsciLexerPython

logger = logging.getLogger()

_translate = QCoreApplication.translate


class ReplWindow(PamhyrWindow):
    _pamhyr_ui = "DebugRepl"
    _pamhyr_name = "Debug REPL"

    def __init__(self, study=None, config=None,
                 solver=None, parent=None):
        title = _translate("Debug", "Debug REPL")

        super(ReplWindow, self).__init__(
            title=title,
            study=study,
            config=config,
            options=[],
            parent=parent
        )

        self.__debug_exec_result__ = None
        self._history = []
        self._history_ind = 0

        self.setup_editor()
        self.setup_connections()

    def setup_editor(self):
        layout = self.find(QHBoxLayout, "horizontalLayout")
        self._editor = PamhyrPythonEditor()
        layout.insertWidget(0, self._editor)

    def setup_connections(self):
        self.find(QPushButton, "pushButton").clicked.connect(self.eval_python)

    def eval_python(self):
        code = self._editor.text()

        # Code to rich_code
        rich_code = code.strip().split("\n")
        # Add return variable for results display at last row
        rich_code[-1] = "self.__debug_exec_result__ = " + rich_code[-1]
        rich_code = "\n".join(rich_code)
        logger.debug(f"User debug command : \n{rich_code}")
        try:
            value = exec(rich_code)
            value = self.__debug_exec_result__
        except Exception as e:
            value = f"<font color=\"red\">" + str(e) + "</font>\n"
            value += f"<font color=\"grey\">{traceback.format_exc()}</font>"

        # Display code
        msg = f"<font color=\"grey\"> # " + code + " #</font>"
        self.find(QTextEdit, "textEdit").append(msg)
        # Display results
        self.find(QTextEdit, "textEdit").append(str(value))


class TimerWindow(PamhyrWindow):
    _pamhyr_ui = "DebugTimer"
    _pamhyr_name = "Debug Timer"

    def __init__(self, study=None, config=None,
                 solver=None, parent=None):
        title = _translate("Debug", "Debug Timer")

        super(TimerWindow, self).__init__(
            title=title,
            study=study,
            config=config,
            options=[],
            parent=parent
        )

        self.setup_table()
        self.setup_alarm()
        self.setup_connections()

    def setup_table(self):
        table = self.find(QTableView, f"tableView")
        self._table = TableModel(
            table_view=table,
            table_headers={
                "name": "Function name",
                "time": "Time (sec)",
                "calls": "Number of calls"
            },
            data=None,
        )

    def setup_alarm(self):
        self._alarm = QTimer()
        self._alarm.start(2000)

    def setup_connections(self):
        # self.find(QAction, "action_reset").triggered.connect(self.reset)
        self.find(QAction, "action_export").triggered.connect(self.export)

        self._alarm.timeout.connect(self.update)

    def update(self):
        self._table.update_lst()

    # def reset(self):
    #     self._table.reset_timers()

    def export(self):
        self.file_dialog(
            select_file="AnyFile",
            callback=lambda f: self.export_to(f[0]),
            default_suffix=".csv",
            file_filter=["CSV file (*.csv)"],
        )

    def export_to(self, filename):
        csv = self._table.to_csv()

        with open(filename, 'w', newline='') as csvfile:
            csvfile.write(csv)
