from nmreval.io.hdfreader import HdfReader

from ..Qt import QtGui, QtCore, QtWidgets
from .._py.hdftree import Ui_Hdf_Dialog


class QHdfViewer(QtWidgets.QDialog, Ui_Hdf_Dialog):
    data_read = QtCore.pyqtSignal(list)
    file_ext = ['.h5', '.hdf', '.hdf5']

    def __init__(self, fname: str = None, parent=None):
        super().__init__(parent=parent)
        self.setupUi(self)

        self.treewidget = HDFTreeWidget(self)
        self.verticalLayout_3.addWidget(self.treewidget)

        self.variables = VarTable(self)
        self.widget_2.addWidget(self.variables)
        self.widget_2.setText('Variables')

        self._reader = HdfReader()

        if fname is not None:
            self.__call__(fname)

    def __call__(self, fname, *args, **kwargs):
        self.treewidget.clear()
        for cb in [self.comboBox, self.comboBox_2]:
            cb.clear()
            cb.addItem('Automatic for the people')
            cb.show()

        self._reader(filename=fname)
        self._fill_boxes()
        self._populate_tree(self._reader, self.treewidget.invisibleRootItem())

        if self.comboBox.count() == 1:
            self.comboBox.hide()
            self.comboBox_2.hide()

        self.treewidget.expandToDepth(0)
        self.treewidget.resizeColumnToContents(1)

        return self

    def _populate_tree(self, node, item):
        self.treewidget.blockSignals(True)

        # add varied parameter to comboboxes
        for key, value in node.title_parameter[1].items():
            if isinstance(value, list):
                idx = self.comboBox.findText(key)
                if idx == -1:
                    self.comboBox.addItem(key)
                    self.comboBox_2.addItem(key)

        if node.children is not None:
            for child in node.children.values():
                label_item = QtWidgets.QTreeWidgetItem([child.name])
                label_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsSelectable)
                label_item.setCheckState(0, QtCore.Qt.Unchecked)
                if child.type == 'signal':
                    label_item.setBackground(0, QtGui.QBrush(QtGui.QColor(31, 119, 180)))
                    label_item.setCheckState(1, QtCore.Qt.Unchecked)
                elif child.type == 'points':
                    label_item.setBackground(0, QtGui.QBrush(QtGui.QColor(255, 127, 14)))
                item.addChild(label_item)
                self._populate_tree(child, label_item)

        self.treewidget.blockSignals(False)

    def _fill_boxes(self):
        for k, v in self._reader.parameter.items():
            if isinstance(v, list):
                idx = self.comboBox.findText(k)
                if idx == -1:
                    self.comboBox.addItem(k)
                    self.comboBox_2.addItem(k)

        self.variables.populate(self._reader.parameter)

    @QtCore.pyqtSlot()
    def get_selected(self):

        if self.comboBox.currentIndex() == 0:
            value = None
        else:
            value = self.comboBox.currentText()

        if self.comboBox_2.currentIndex() == 0:
            group = None
        else:
            group = self.comboBox_2.currentText()

        iterator = QtWidgets.QTreeWidgetItemIterator(self.treewidget, QtWidgets.QTreeWidgetItemIterator.NoChildren)
        selected = []
        while iterator.value():
            item = iterator.value()
            iterator += 1
            if item.checkState(0) == QtCore.Qt.Checked:
                path = item.text(0)
                parent = item.parent()
                while parent is not None:
                    path = parent.text(0) + '/' + path
                    parent = parent.parent()

                if item.checkState(1) == QtCore.Qt.Checked:
                    selected.extend(self._reader.get_selected(path, flag='spectrum', value=value, group=group))
                else:
                    selected.extend(self._reader.get_selected(path, value=value, group=group))

        self.data_read.emit(selected)

    def accept(self):
        self.get_selected()
        self.close()


class VarTable(QtWidgets.QTableWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self.setColumnCount(2)
        self.setHorizontalHeaderLabels(['Key', 'Value'])
        self.horizontalHeader().setStretchLastSection(True)
        self.verticalHeader().setVisible(False)
        self.horizontalHeader().setVisible(True)

    def populate(self, vars: dict):
        self.setHorizontalHeaderLabels(['Key', 'Value'])
        self.setRowCount(len(vars))
        for i, (k, v) in enumerate(vars.items()):
            key_item = QtWidgets.QTableWidgetItem(k)
            key_item.setFlags(QtCore.Qt.NoItemFlags)
            key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
            if isinstance(v, list):
                val = f'<{len(v)} values>'
                if len(v) < 40:
                    tip = '\n'.join(str(p) for p in v)
                else:
                    tip = '\n'.join(str(p) for p in v[:40])
                    tip += '\n...'
            else:
                val = str(v)
                tip = val
            value_item = QtWidgets.QTableWidgetItem(val)
            value_item.setFlags(QtCore.Qt.NoItemFlags)
            value_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
            value_item.setToolTip(tip)
            self.setItem(i, 0, key_item)
            self.setItem(i, 1, value_item)


class HDFTreeWidget(QtWidgets.QTreeWidget):
    def __init__(self, parent):
        super().__init__(parent=parent)

        self.setHeaderLabels(['Data', 'Spectrum?'])
        self.header().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
        self.header().setSectionResizeMode(1, QtWidgets.QHeaderView.Fixed)
        self.header().setStretchLastSection(False)
        self.header().setCascadingSectionResizes(True)
        self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)

        self.itemChanged.connect(self.change_item)

    def keyPressEvent(self, evt: QtGui.QKeyEvent):
        if evt.key() == QtCore.Qt.Key_Space:
            for idx in self.selectedIndexes():
                item = self.itemFromIndex(idx)
                col = idx.column()
                cs = item.checkState(col)
                item.setCheckState(col, QtCore.Qt.Unchecked if cs == QtCore.Qt.Checked else QtCore.Qt.Checked)
        else:
            super().keyPressEvent(evt)

    @staticmethod
    def change_item(item: QtWidgets.QTreeWidgetItem, column: int):
        state = item.checkState(column)
        for i in range(item.childCount()):
            child = item.child(i)
            child.setCheckState(column, state)
