from nmreval.distributions import ColeDavidson, HavriliakNegami, KWW, LogGaussian

from ..Qt import QtWidgets, QtCore
from .._py.meandialog import Ui_calc_means_dialog
from ..lib.forms import Widget


class QMeanTimes(QtWidgets.QDialog, Ui_calc_means_dialog):
    newValues = QtCore.pyqtSignal(tuple, dict, str)

    def __init__(self, tree: dict, parent=None):
        super().__init__(parent=parent)
        self.setupUi(self)

        self._tree = tree

        self.distributions = [ColeDavidson, HavriliakNegami, KWW, LogGaussian]
        for s in self.distributions:
            self.dist_combobox.addItem(s.name)

        self.update_graphs(self._tree)
        self.change_distribution(0)

        self.dist_combobox.currentIndexChanged.connect(self.change_distribution)
        self.from_combobox.currentIndexChanged.connect(lambda idx: self.calculate_means())
        self.to_combobox.currentIndexChanged.connect(lambda idx: self.calculate_means())

    def update_graphs(self, graph: dict):
        graph_id = self.graph_combobox.currentData(QtCore.Qt.UserRole)

        self.graph_combobox.clear()
        for key, (name, _) in graph.items():
            self.graph_combobox.addItem(name, userData=key)
        if graph_id is not None:
            self.graph_combobox.setCurrentIndex(self.graph_combobox.findData(graph_id, QtCore.Qt.UserRole))
        else:
            self.graph_combobox.setCurrentIndex(0)

    @QtCore.pyqtSlot(int)
    def change_distribution(self, idx):
        dist = self.distributions[idx]

        while self.verticalLayout.count():
            item = self.verticalLayout.takeAt(0)
            item.widget().deleteLater()

        for i, p in enumerate([r'\tau'] + dist.parameter):
            w = Widget(p, self._tree, collapsing=True, parent=self)
            w.valueChanged.connect(lambda: self.calculate_means())
            self.verticalLayout.addWidget(w)

        self.calculate_means()

    def calculate_means(self):
        parameter = []
        for i in range(self.verticalLayout.count()):
            w = self.verticalLayout.itemAt(i).widget()
            try:
                parameter.append(float(w.lineEdit.text()))
            except ValueError:
                parameter = None
                break

        if parameter is not None:
            dist, direction = self.get_conversions()

            self.label.setText(f'{self.to_combobox.currentText()}: '
                               f'{dist.convert(*parameter, **direction):.8g}')

    @QtCore.pyqtSlot()
    def get_parameter(self):
        parameter = []
        for i in range(self.verticalLayout.count()):
            w = self.verticalLayout.itemAt(i).widget()

            p = w.value
            if p is not None:
                parameter.append(p)
            else:
                QtWidgets.QMessageBox.warning(self, 'Invalid input',
                                              f'Invalid input for parameter {w.label.text()}')
                return

        dist, direction = self.get_conversions()

        graph_destination = ''
        if not self.checkBox.isChecked():
            graph_destination = self.graph_combobox.currentData()

        self.newValues.emit((dist, parameter), direction, graph_destination)

    def get_conversions(self):
        mode = ['raw', 'peak', 'mean', 'logmean']
        mode_to = mode[self.to_combobox.currentIndex()]
        mode_from = mode[self.from_combobox.currentIndex()]

        dist = self.distributions[self.dist_combobox.currentIndex()]

        return dist, {'from_': mode_from, 'to_': mode_to}

    @QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonBox_clicked')
    def button_clicked(self, bttn: QtWidgets.QAbstractButton):
        role = self.buttonBox.buttonRole(bttn)

        if role == QtWidgets.QDialogButtonBox.RejectRole:
            self.close()
        elif role == QtWidgets.QDialogButtonBox.AcceptRole:
            self.get_parameter()
            self.close()
        elif role == QtWidgets.QDialogButtonBox.ApplyRole:
            self.get_parameter()
        else:
            print('Unknown role')
