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

from queue import Queue
from tools import trace, timer

from View.ASubWindow import ASubWindow, ASubMainWindow
from View.ListedSubWindow import ListedSubWindow

from PyQt5.QtGui import (
    QKeySequence,
)

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

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

_translate = QCoreApplication.translate

class SelectSolverWindow(ASubWindow, ListedSubWindow):
    def __init__(self, title="Select solver",
                 study=None, config=None,
                 parent=None):
        self._title = title

        self._study = study
        self._config = config
        self._solver = None

        super(SelectSolverWindow, self).__init__(
            name=self._title, ui="SelectSolver", parent=parent
        )
        self.ui.setWindowTitle(self._title)

        self.setup_combobox()
        self.setup_connections()

    def setup_combobox(self):
        solvers = self._config.solvers
        solvers_name = list(map(lambda s: s.name, solvers))

        self.combobox_add_items("comboBox", solvers_name)

    def setup_connections(self):
        self.find(QPushButton, "pushButton_run").clicked.connect(self.accept)
        self.find(QPushButton, "pushButton_cancel").clicked.connect(self.reject)
    @property
    def solver(self):
        return self._solver

    def accept(self):
        solver_name = self.get_combobox_text("comboBox")
        self._solver = next(
            filter(
                lambda s: s.name == solver_name,
                self._config.solvers
            )
        )

        super(SelectSolverWindow, self).accept()


class SolverLogWindow(ASubMainWindow, ListedSubWindow):
    def __init__(self, title="Solver logs",
                 study=None, config=None,
                 solver=None, parent=None):
        self._title = title

        self._study = study
        self._config = config
        self._solver = solver
        self._process = QProcess(parent)

        super(SolverLogWindow, self).__init__(
            name=self._title, ui="SolverLog", parent=parent
        )
        self.ui.setWindowTitle(self._title)

        self.setup_action()
        self.setup_alarm()
        self.setup_connections()

        self._alarm.start(500)
        self._output = Queue()

        self._log(f" *** Run solver {self._solver.name}")
        self._solver.run(self._process, self._output)

    def setup_action(self):
        self.find(QAction, "action_start").setEnabled(False)
        self.find(QAction, "action_pause").setEnabled(True)
        self.find(QAction, "action_stop").setEnabled(True)

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

    def setup_connections(self):
        self.find(QAction, "action_start").triggered.connect(self.start)
        self.find(QAction, "action_pause").triggered.connect(self.pause)
        self.find(QAction, "action_stop").triggered.connect(self.stop)

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

    def _log(self, msg):
        if type(msg) == str:
            msg = msg.rsplit('\n')[0]
            self.find(QTextEdit, "textEdit").append(msg)
        elif type(msg) == int:
            self.find(QTextEdit, "textEdit")\
                .append(f" *** Solver finished with code {msg}")

    def update(self):
        while self._output.qsize() != 0:
            s = self._output.get()
            self._log(s)

    def start(self):
        self._log(" *** Start")

        self._solver.start()

        self.find(QAction, "action_start").setEnabled(False)
        self.find(QAction, "action_pause").setEnabled(True)
        self.find(QAction, "action_stop").setEnabled(True)

    def pause(self):
        self._log(" *** Pause")

        self._solver.pause()

        self.find(QAction, "action_start").setEnabled(True)
        self.find(QAction, "action_pause").setEnabled(False)
        self.find(QAction, "action_stop").setEnabled(True)

    def stop(self):
        self._log(" *** Stop")

        self._solver.kill()

        self.find(QAction, "action_start").setEnabled(True)
        self.find(QAction, "action_pause").setEnabled(False)
        self.find(QAction, "action_stop").setEnabled(False)