class DataPlot(QSplitter):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.setOrientation(Qt.Vertical)

        self.plots = pg.GraphicsLayoutWidget()

        self.addWidget(self.plots)

        self.bottom = QSplitter()
        self.bottom.setOrientation(Qt.Horizontal)

        self.addWidget(self.bottom)

        self.h5_path_shown = None

    def update_from_h5(self, h5_path):
        if self.h5_path_shown != h5_path or self.data_extractor.local_data_changed:
            self.h5_path_shown = h5_path
            self.update(*self.data_extractor.extract_data(h5_path))


class QuickDataPlot(DataPlot):
    def __init__(self, ap, **kwargs):

        super().__init__(**kwargs)

        self.plot = self.plots.addPlot()

        for key in self.plot.axes:
            ax = self.plot.getAxis(key)
            # Fix Z value making the grid on top of the image
            ax.setZValue(1)
        self.ap = ap
        self.h5_paths_shown = []

        self.table = QTableWidget()
        self.table.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)

        self.bottom.addWidget(self.table)

        self.plot_setting = PlotSettings(self.plot)

        self.bottom.addWidget(self.plot_setting)

    def update_from_h5(self, h5_path=None):
        self.update_data_extractor()
        if self.data_extractor.local_data_changed or collections.Counter(self.h5_paths_shown) != collections.Counter(
                self.ap.h5_paths_selected):
            self.h5_paths_shown = self.ap.h5_paths_selected
            self.update()


class ExtendedCombo(QComboBox):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())

        self.setCompleter(self.completer)

        self.lineEdit().textEdited[str].connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setModel(self, model):
        super().setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super().setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)


class PlotSettings(QTableWidget):
    def __init__(self, plot, **kwargs):
        super().__init__(**kwargs)

        self.plot = plot
        self.setColumnCount(3)
        self.setColumnWidth(0, 100)
        self.setColumnWidth(1, 100)

        self.setHorizontalHeaderLabels(['parameter', 'setting', 'units'])

        self.setRowCount(4)

        # title
        i = 0
        self.le_title = QLineEdit()

        self.setCellWidget(i, 0, QLabel('title'))
        self.setCellWidget(i, 1, self.le_title)

        self.le_title.textChanged[str].connect(self.set_title)

        # xlabel
        i += 1
        self.le_xlabel = QLineEdit()
        self.le_xlabel_unit = QLineEdit()

        self.setCellWidget(i, 0, QLabel('xlabel'))
        self.setCellWidget(i, 1, self.le_xlabel)
        self.setCellWidget(i, 2, self.le_xlabel_unit)

        self.le_xlabel.textChanged[str].connect(self.set_xlabel)
        self.le_xlabel_unit.textChanged[str].connect(self.set_xlabel)

        # ylabel
        i += 1
        self.le_ylabel = QLineEdit()
        self.le_ylabel_unit = QLineEdit()

        self.setCellWidget(i, 0, QLabel('ylabel'))
        self.setCellWidget(i, 1, self.le_ylabel)
        self.setCellWidget(i, 2, self.le_ylabel_unit)

        self.le_ylabel.textChanged[str].connect(self.set_ylabel)
        self.le_ylabel_unit.textChanged[str].connect(self.set_ylabel)

        # grid
        i += 1
        self.cb_grid = QCheckBox()
        self.setCellWidget(i, 0, QLabel('grid'))
        self.setCellWidget(i, 1, self.cb_grid)

        self.cb_grid.stateChanged.connect(self.set_grid)

    def set_title(self):
        self.plot.setTitle(self.le_title.text())

    def set_xlabel(self):
        self.plot.setLabel('bottom', self.le_xlabel.text(), units=self.le_xlabel_unit.text())

    def set_ylabel(self):
        self.plot.setLabel('left', self.le_ylabel.text(), units=self.le_ylabel_unit.text())

    def set_grid(self):
        self.plot.showGrid(x=self.cb_grid.isChecked(), y=self.cb_grid.isChecked(), alpha=0.3)


class NumericDataCombo(ExtendedCombo):

    def __init__(self, df, **kwargs):

        super().__init__(**kwargs)
        self.update_model(df)

    def update_model(self, df):
        model = QtGui.QStandardItemModel()

        item = QtGui.QStandardItem('shot number')
        model.setItem(0, 0, item)

        i = 1
        for midx in df.columns:
            if is_numeric_dtype(df.dtypes[midx]):
                column_name = ','.join([x for x in midx if x])
                item = QtGui.QStandardItem(column_name)
                model.setItem(i, 0, item)
                i += 1

        self.setModel(model)

    def get_idx(self):
        return tuple(str(self.currentText()).split(','))