from PyQt5 import QtGui, QtWidgets, uic, QtCore
from functools import wraps
try:
    from importlib.resources import files
except ImportError:
    from importlib_resources import files
from ...Framework.VisualizationBaseObject import VisualizationObject

_roisd_ui = files('phybers.fibervis.ui') / 'Segmentations' / 'ROIsSegmentationDialog.ui'


# MUST DELETE
def identifyNumberRecursively(item, number):
    root = item

    if item.parent() != None:
        root = identifyNumberRecursively(item.parent(), number)
        number.append(item.parent().indexOfChild(item))
    else:
        return item
    return root


def retrieveItemIteratively(root, index):
    item = root

    for i in index:
        if hasattr(item, 'children'):
            item = item.children[i]
        else:
            item = item[i]

    return item
    ###########


def detectAlways(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)

        if args[0].ui.alwaysBox.isChecked():
            args[0].segmentSubject()
    return wrapper


class ROIsSegmentationDialog(QtWidgets.QDialog):
    updateObject = QtCore.pyqtSignal(dict)


    def __init__(self, segmentation, parent):
        super().__init__(parent)
        self.ui = uic.loadUi(str(_roisd_ui), self)

        self.segmentationRef = segmentation

        self.ui.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.ui.tableWidget.horizontalHeader().setStretchLastSection(True)

        self.ui.addROIButton.clicked.connect(self.addROI)
        self.ui.removeROIButton.clicked.connect(self.removeROI)

        self.ui.detectButton.clicked.connect(self.segmentSubject)

        self.ui.exportButton.clicked.connect(self.exportBundle)

        self.ui.alphaSlider.valueChanged.connect(self.alphaChanged)

        self.ui.tableWidget.cellChanged.connect(self.cellChanged)

        self.ui.logicLineEdit.editingFinished.connect(self.logicLineEditEdited)

        self.show()




    # // Actualiza dibujo al clickear checkbox de la tabla
    # this.connect(this.ui.tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(itemtoggle(int,int)));


    @detectAlways
    @QtCore.pyqtSlot()
    def addROI(self):
        treeWidgetItems = self.parentWidget().ui.treeWidget.selectedItems()
        if len(treeWidgetItems) == 0:
            return
        elif treeWidgetItems[0].identifier != VisualizationObject.ROI:
            QtWidgets.QMessageBox.question(self, "Invalid ROI", 'Must select a ROI from the visualization tool dialog.', QtWidgets.QMessageBox.Ok)
            return

        # Bad practice
        ##############
        number = []
        root = identifyNumberRecursively(treeWidgetItems[0], number)

        if root.text(0) == 'Bundles':
            reference = self.parentWidget().bundleReference
        elif root.text(0) == 'Meshes':
            reference = self.parentWidget().meshReference
        elif root.text(0) == 'MRIs':
            reference = self.parentWidget().mriReference
        elif root.text(0) == 'ROIs':
            reference = self.parentWidget().roisReference
        else:
            reference = None

        refObj = retrieveItemIteratively(reference, number)
        if isinstance(refObj, list):
            QtWidgets.QMessageBox.question(self, "Too many ROIs", 'Please select one ROI.', QtWidgets.QMessageBox.Ok)
            return
        ##############

        options = {     'reference' : self.segmentationRef,
                                'attributes': {'addROI' : [refObj]},
                                'updateViewingObjects' : True}

        self.updateObject.emit(options)


    @detectAlways
    @QtCore.pyqtSlot()
    def removeROI(self):
        index = self.ui.tableWidget.currentRow()

        # self.ui.tableWidget.removeRow(index)
        options = {     'reference' : self.segmentationRef,
                                'attributes': {'removeROIFromIndex' : [index]},
                                'updateViewingObjects' : True}

        self.updateObject.emit(options)


    @QtCore.pyqtSlot()
    def segmentSubject(self):
        options = {     'reference' : self.segmentationRef,
                                'segmentSubject' : True}

        self.updateObject.emit(options)


    @QtCore.pyqtSlot()
    def alphaChanged(self):
        alpha = self.alphaSlider.value()/(self.alphaSlider.maximum()+1)

        options = {     'reference' : self.segmentationRef,
                                'attributes': {'setAlpha' : [alpha]}}

        self.updateObject.emit(options)


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

        # Gets direction of bundle files
        outFile, fileType = QtWidgets.QFileDialog.getSaveFileName(self, "Save Bundle file", "", "Bundle (*.bundles)")#;;Trk file (*.trk)")

        options = {     'reference' : self.segmentationRef,
                                'attributes' : {'exportFile' : [outFile]}}

        self.updateObject.emit(options)


    @detectAlways
    @QtCore.pyqtSlot(int, int)
    def cellChanged(self, row, column):
        if column == 0:
            checked = self.ui.tableWidget.item(row, column).checkState() == QtCore.Qt.Checked

            options = {     'reference' : self.segmentationRef,
                                    'attributes' : {'setValidatorAtIndex' : [row, checked]}}

            self.updateObject.emit(options)


    @detectAlways
    @QtCore.pyqtSlot()
    def logicLineEditEdited(self):
        options = {     'reference' : self.segmentationRef,
                                'attributes': {'updateLogic' : [str(self.ui.logicLineEdit.text()),
                                                                                        self.ui.logicLineEdit.setText]}}

        self.updateObject.emit(options)


    def update(self):
        while self.ui.tableWidget.rowCount():
            self.ui.tableWidget.removeRow(0)

        for i in range(len(self.segmentationRef.children)):
            self.insertItemInTable(self.segmentationRef.children[i], self.segmentationRef.roiValidator[i])

    def objectsChanged(self, objects):
        if self.ui.alwaysBox.isChecked():
            for obj in objects:
                if obj in self.segmentationRef.children or obj is self.segmentationRef:
                    self.segmentSubject()
                    return


    def insertItemInTable(self, objRef, checked):
        self.ui.tableWidget.cellChanged.disconnect(self.cellChanged)

        row = self.ui.tableWidget.rowCount()
        self.ui.tableWidget.insertRow(row)

        tag = QtWidgets.QTableWidgetItem(str(row))
        tag.setCheckState(QtCore.Qt.Checked if checked else QtCore.Qt.Unchecked)
        tag.setTextAlignment(QtCore.Qt.AlignHCenter)
        tag.setFlags(tag.flags() & ~QtCore.Qt.ItemIsEditable)

        bg = QtWidgets.QTableWidgetItem()
        bg.setBackground(QtGui.QBrush(QtGui.QColor(
                                        int(objRef.getRGB256()[0]),
                                        int(objRef.getRGB256()[1]),
                                        int(objRef.getRGB256()[2]))))
        bg.setFlags(bg.flags() & ~QtCore.Qt.ItemIsEditable)

        roiType = QtWidgets.QTableWidgetItem(str(objRef.roiType))
        roiType.setTextAlignment(QtCore.Qt.AlignHCenter)
        roiType.setFlags(roiType.flags() & ~QtCore.Qt.ItemIsEditable)

        self.ui.tableWidget.setItem(row, 0, tag)
        self.ui.tableWidget.setItem(row, 1, bg)
        self.ui.tableWidget.setItem(row, 2, roiType)

        self.ui.tableWidget.selectRow(row)

        self.ui.tableWidget.cellChanged.connect(self.cellChanged)
