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

import os
import pathlib
import sys
import csv
import time

from tools import timer

from PyQt5 import QtWidgets
from PyQt5.QtCore import (
    QModelIndex, Qt, QSettings, pyqtSlot,
    QItemSelectionModel, QCoreApplication, QSize
)
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QFileDialog, QCheckBox
)

from View.Geometry.mainwindow_ui_reach import Ui_MainWindow
from View.Geometry import qtableview_reach
from View.Geometry import window_profileXYZ
from View.ASubWindow import WindowToolKit


_translate = QCoreApplication.translate

class GeometryWindow(QMainWindow, WindowToolKit):
    def __init__(self, model=None, parent=None):
        self.parent = parent
        super(GeometryWindow, self).__init__(parent=parent)

        self._model = model
        self._reach = model.river.current_reach().reach

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.tableView = self.ui.tableView
        self.tableView_header = self.ui.tableView_header

        self._tablemodel = None

        self.setup_window()
        self.setup_model()
        self.setup_connections()
        self.setup_plot()
        self.changed_slider_value()

    def setup_window(self):
        self.setWindowTitle(f"{self.ui.mainwindow_title} - {self._reach.name}")

    def setup_model(self):
        self._tablemodel = qtableview_reach.PandasModelEditable(
            headers = self.ui.tableView_header,
            reach = self._reach
        )
        self.tableView.setModel(self._tablemodel)
        self.tableView.setItemDelegate(qtableview_reach.Delegate())

    def setup_plot(self):
        if self._reach.number_profiles != 0:
            self.graphic_1()
            self.graphic_2()
            self.graphic_3()

    def setup_connections(self):
        self.ui.btn_open.clicked.connect(self.open_file_dialog)
        self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)
        self.ui.btn_sort_desc.clicked.connect(self.sort_descending)
        self.ui.btn_move_up.clicked.connect(self.move_row_up)
        self.ui.btn_move_down.clicked.connect(self.move_row_down)
        self.ui.btn_end_editing.clicked.connect(self.handleSave)
        self.ui.btn_add.clicked.connect(self.insert_row)
        self.ui.btn_delete.clicked.connect(self.delete_row)
        self.ui.btn_edit.clicked.connect(self.edit_profile)
        self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value)
        # self.tableView.selectionModel().selectionChanged.connect(self.changed_slider_value_2)
        self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider)
        self.ui.btn_slider_down.clicked.connect(self.increment_value_slider)
        self.ui.btn_move_up.clicked.connect(self.changed_profile_slot)

        # Profile selection when line change in table
        self.tableView.selectionModel()\
                      .selectionChanged\
                      .connect(self.select_current_profile)

        # Update plot when profile data change
        self._tablemodel.dataChanged.connect(self.update_graphic_1)
        self._tablemodel.dataChanged.connect(self.update_graphic_2)
        self.tableView.selectionModel()\
                      .selectionChanged\
                      .connect(self.update_graphic_1)
        self.tableView.selectionModel()\
                      .selectionChanged\
                      .connect(self.update_graphic_2)

    def open_file_dialog(self):
        options = QFileDialog.Options()
        DEFAULT_DIRECTORY = os.getenv("HOME")
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
        current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
        options |= QFileDialog.DontUseNativeDialog

        filename, _ = QtWidgets.QFileDialog.getOpenFileName(
            self,
            _translate("MainWindow_reach", "Ouvrir un fichier"),
            current_dir,
            _translate("MainWindow_reach", "Fichiers .ST (*.ST)") +
            ";; " +
            _translate("MainWindow_reach", "Fichiers textes (*.txt)") +
            ";; " +
            _translate("MainWindow_reach", "Tous les fichiers (*)"),
            options=options
        )

        current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
        if filename != "":
            size = os.stat(filename).st_size
            self._reach.import_geometry(filename)
            self._tablemodel.layoutChanged.emit()

            self.update_profile_windows()
            self.graphic_1()
            self.graphic_2()
            self.graphic_3()



    def messagebox_profile_editing(self):
        msg_box = QtWidgets.QMessageBox()
        msg_box.setIcon(QtWidgets.QMessageBox.Information)
        msg_box.setWindowTitle(_translate("MainWindow_reach",
                                          "Édition des profils sélectionnés"))
        msg_box.setText(_translate("MainWindow_reach",
                                   "Vous avez sélectionné plus de 5 profils."
                                   " \nSeuls les 5 premiers seront édités."))
        msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok)

        return_value = msg_box.exec()
        if return_value == QtWidgets.QMessageBox.Ok:
            print('OK clicked')

    def edit_profile(self):
        list_selected_row = list(
            set([index.row() for index in self.tableView.selectedIndexes()])
        )

        self.tableView.model().blockSignals(True)

        if len(list_selected_row) > 5:
            self.messagebox_profile_editing()

        for selected_row in list_selected_row[:5]:
            selected_row = int(selected_row)
            profile_identifier = self._reach.get_profile_selected_identifier(selected_row)
            kp = self._reach.profile(selected_row).kp
            profile_name = self._reach.get_profile_name(selected_row)

            if len(self.list_second_window) == 0:
                self.second_window = window_profileXYZ.View(
                    selected_row + 1,
                    self._reach.get_profile_via_identifier(profile_identifier),
                    kp=kp, profile_name="", parent=self
                )
                self.second_window.window_title(
                    kp=kp,
                    profile_name=profile_name,
                    profile_selected_num=selected_row
                )
                self.second_window.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
                self.list_second_window.append(self.second_window)
                self.second_window.show()
                self.list_row.append(profile_identifier)

            else:
                if profile_identifier in self.list_row:
                    self.list_second_window[self.list_row.index(profile_identifier)]\
                        .window_title(
                            kp=kp, profile_name=profile_name,
                            profile_selected_num=selected_row
                        )

                    self.list_second_window[
                        self.list_row.index(profile_identifier)
                    ].setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)

                    self.list_second_window[
                        self.list_row.index(profile_identifier)
                    ].show()
                else:
                    second_window1 = window_profileXYZ.View(
                        selected_row + 1,
                        self._reach.get_profile_via_identifier(profile_identifier),
                        kp=kp, profile_name="", parent=self
                    )
                    second_window1.window_title(
                        kp=kp, profile_name=profile_name,
                        profile_selected_num=selected_row
                    )

                    second_window1.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
                    second_window1.show()
                    self.list_row.append(profile_identifier)
                    self.list_second_window.append(second_window1)

        widgetList = QApplication.topLevelWidgets()
        numWindows = len(widgetList)
        self.tableView.model().blockSignals(False)

    def wind_profile_changed(self):
        self.second_window\
            .datachanged_signal[bool]\
            .connect(self.changed_profile_slot)

    pyqtSlot(bool)

    def changed_profile_slot(self, status):
        self.update_view1 = status

    def update_profile_windows(self):
        self.list_second_window = []
        self.list_row = []

    @timer
    def graphic_1(self):
        self.ui.canvas_1.axes.cla()
        self.ui.canvas_1.axes.grid(color='grey', linestyle='--', linewidth=0.5)

        # Axes
        self.ui.canvas_1.axes.set_xlabel(
            _translate("MainWindow_reach", "X (m)"), color='green', fontsize=12
        )
        self.ui.canvas_1.axes.set_ylabel(
            _translate("MainWindow_reach", "Y (m)"), color='green', fontsize=12
        )

        # Draw line for each profile
        self.line_xy = [
            self.ui.canvas_1.axes.plot(
                x, y,
                color='r', lw=1.,
                markersize=3, marker='+'
            )
            for x, y in zip(self._reach.get_x(), self._reach.get_y())
        ]

        # Guide lines
        self.x_complete = self._reach.get_guidelines_x()
        self.y_complete = self._reach.get_guidelines_y()

        self.line_gl_1 = self.ui.canvas_1.axes.plot(
            self.x_complete,
            self.y_complete
        )

        self.plot_selected_1, = self.ui.canvas_1.axes.plot(
            self._reach.profile(0).x(),
            self._reach.profile(0).y(),
            lw=1., markersize=3,
            marker='+', color="b"
        )

        self.plot_selected_1.set_visible(False)
        self.before_plot_selected_1, = self.ui.canvas_1.axes.plot(
            self._reach.profile(0).x(),
            self._reach.profile(0).y(),
            lw=1., markersize=3,
            marker='+', color="k", linestyle="--"
        )

        self.before_plot_selected_1.set_visible(False)

        self.after_plot_selected_1, = self.ui.canvas_1.axes.plot(
            self._reach.profile(0).x(),
            self._reach.profile(0).y(),
            lw=1., markersize=3,
            marker='+', color="m", linestyle='--'
        )

        self.after_plot_selected_1.set_visible(False)

        self.ui.canvas_1.figure.tight_layout()
        self.ui.canvas_1.figure.canvas.draw_idle()
        self.ui.toolbar_1.update()

    def graphic_2(self):
        self.tableView.model().blockSignals(True)

        self.ui.canvas_2.axes.cla()
        self.ui.canvas_2.axes.grid(color='grey', linestyle='--', linewidth=0.5)
        self.ui.canvas_2.axes.set_xlabel(
            _translate("MainWindow_reach", "Kp (m)"), color='green', fontsize=12
        )
        self.ui.canvas_2.axes.set_ylabel(
            _translate("MainWindow_reach", "Cote (m)"), color='green', fontsize=12
        )

        kp = self._reach.get_kp()
        z_min = self._reach.get_z_min()
        z_max = self._reach.get_z_max()

        self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines(
            x=kp,
            ymin=z_min, ymax=z_max,
            color='r', lw=1.
        )

        self.plot_selected_2, = self.ui.canvas_2.axes.plot(
            (kp[0], kp[0]),
            (z_min[0], z_max[0]),
            color='b', lw=1.8
        )
        self.plot_selected_2.set_visible(False)

        self.before_plot_selected_2, = self.ui.canvas_2.axes.plot(
            (kp[0], kp[0]),
            (z_min[0], z_max[0]),
            color='k', lw=1.6, linestyle='--'
        )
        self.before_plot_selected_2.set_visible(False)

        self.after_plot_selected_2, = self.ui.canvas_2.axes.plot(
            (kp[0], kp[0]),
            (z_min[0], z_max[0]),
            color='m', lw=1.6, linestyle='--'
        )
        self.after_plot_selected_2.set_visible(False)

        kp = self._reach.get_kp()
        self.line_kp_zgl = []
        for z in self._reach.get_guidelines_z():
            # Is incomplete guideline?
            if len(z) != len(kp):
                continue

            self.line_kp_zgl.append(
                self.ui.canvas_2.axes.plot(
                    kp, z, lw=1.
                )
            )

        self.line_kp_zmin, = self.ui.canvas_2.axes.plot(
            kp, z_min,
            linestyle=":", lw=1.8,
            color='lightgrey'
        )

        self.tableView.model().blockSignals(False)

        self.ui.canvas_2.figure.tight_layout()
        self.ui.canvas_2.figure.canvas.draw_idle()
        self.ui.toolbar_2.update()

    def update_graphic_1(self):
        self.tableView.model().blockSignals(True)

        for ind in range(self._tablemodel.rowCount()):
            self.line_xy[ind][0].set_data(
                self._reach.profile(ind).x(),
                self._reach.profile(ind).y()
            )

        for i in range(len(self.line_gl_1)):
            self.line_gl_1[i].set_data(
                [x[i] for x in self.x_complete],
                [y[i] for y in self.y_complete]
            )

        self.tableView.model().blockSignals(False)
        self.ui.canvas_1.figure.canvas.draw_idle()

    def update_graphic_2(self):
        self.tableView.model().blockSignals(True)

        kp = self._reach.get_kp()
        z_min = self._reach.get_z_min()
        z_max = self._reach.get_z_max()

        self.line_kp_zmin.set_data(kp, z_min)

        self.line_kp_zmin_zmax.remove()
        self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines(
            x=kp,
            ymin=z_min, ymax=z_max,
            color='r', lw=1.
        )

        try:
            for i in range(len(self.line_kp_zgl)):
                self.line_kp_zgl[i][0].set_data(
                    kp, self._tablemodel.z_complete_guideline()[i]
                )
        except Exception as e:
            print(f"Failed to update graphic 2: {e}")

        self.tableView.model().blockSignals(False)
        self.ui.canvas_2.axes.autoscale_view(True, True, True)
        self.ui.canvas_2.figure.canvas.draw_idle()

    def graphic_3(self):
        self.tableView.model().blockSignals(True)

        selected_profile = 0
        station = self._reach.profile(selected_profile).get_station()
        station_plus_1 = self._reach.profile(selected_profile + 1).get_station()
        elevation = self._reach.profile(selected_profile).z()
        elevation_i_plus_1 = self._reach.profile(selected_profile + 1).z()
        gl = self._reach.profile(selected_profile).name

        self.ui.canvas_3.axes.cla()
        self.ui.canvas_3.axes.grid(color='grey', linestyle='--', linewidth=0.5)
        self.ui.canvas_3.axes.set_xlabel(
            _translate("MainWindow_reach", "Abscisse en travers (m)"),
            color='green', fontsize=12
        )
        self.ui.canvas_3.axes.set_ylabel(
            _translate("MainWindow_reach", "Cote (m)"),
            color='green', fontsize=12
        )
        self.ui.canvas_3.figure.tight_layout()

        label_profile_i_minus_1 = _translate("MainWindow_reach", "Profil précédent")
        label_profile_i = _translate("MainWindow_reach", "Profil sélectionné")
        label_profile_i_plus_1 = _translate("MainWindow_reach", "Profil suivant")
        color_profile_i_minus_1 = "k"  # 'grey'
        color_profile_i = 'b'
        color_profile_i_plus_1 = 'm'

        self.profile_i_minus_1, = self.ui.canvas_3.axes.plot(
            [], [], label=label_profile_i_minus_1, lw=1.8,
            linestyle='--', color=color_profile_i_minus_1
        )
        self.profile_i, = self.ui.canvas_3.axes.plot(
            station, elevation, label=label_profile_i,
            color=color_profile_i, lw=1.8
        )

        self.profile_i_plus_1, = self.ui.canvas_3.axes.plot(
            station_plus_1, elevation_i_plus_1,
            label=label_profile_i_plus_1,
            color=color_profile_i_plus_1, lw=1.6, linestyle='--'
        )
        self.annotation_3 = []
        self.complete_gl, self.incomplete_gl = self._reach.compute_guidelines()

        line_2d = [[line_2D] for line_2D in self.line_gl_1]
        self.color_complete_gl = self.get_line_gl_colors(line_2d)
        self.color_incomplete_gl = 2 * ["#000000"]

        x_gl_complete = []
        y_gl_complete = []
        color_scat_complete_gl = []
        x_gl_incomplete = []
        y_gl_incomplete = []
        color_scat_incomplete_gl = []

        for i, txt in enumerate(list(gl)):
            if txt.strip() in self.complete_gl:
                annotation_3 = self.ui.canvas_3.axes.annotate(
                    txt, (station[i], elevation[i]),
                    horizontalalignment='left',
                    verticalalignment='top', annotation_clip=True,
                    fontsize=10,
                    color=self.color_complete_gl[
                        self.complete_gl.index(txt)
                    ]
                )

                annotation_3.set_position((station[i] + 0., elevation[i] + 0.))
                self.annotation_3.append(annotation_3)

                x_gl_complete.append(station[i])
                y_gl_complete.append(elevation[i])
                color_scat_complete_gl.append(self.color_complete_gl[self.complete_gl.index(txt)])
            elif txt.strip() in self.incomplete_gl:
                annotate = self.ui.canvas_3.axes.annotate(
                    txt, (station[i], elevation[i]), horizontalalignment='left',
                    verticalalignment='top', annotation_clip=True, fontsize=11,
                    color=self.color_incomplete_gl[
                        self.incomplete_gl.index(txt)
                    ],
                    size=10
                )

                self.annotation_3.append(annotate)

                x_gl_incomplete.append(station[i])
                y_gl_incomplete.append(elevation[i])
                color_scat_incomplete_gl.append(
                    self.color_incomplete_gl[self.incomplete_gl.index(txt)]
                )

        self.tableView.model().blockSignals(False)

        self.ui.canvas_3.axes.legend(fancybox=True, shadow=True, fontsize=8)
        self.ui.canvas_3.figure.tight_layout()

        self.ui.canvas_3.figure.canvas.draw_idle()
        self.ui.toolbar_3.update()

    def update_annotate_3(self, ind: int):
        self.tableView.model().blockSignals(True)

        for a in self.annotation_3:
            a.remove()

        self.annotation_3[:] = []

        x = self._reach.profile(ind).get_station()
        y = self._reach.profile(ind).z()
        gl = self._reach.profile(ind).name
        complete, incomplete = self._reach.compute_guidelines()

        self.x_complete = []
        color_scat_complete = []
        self.x_incomplete = []
        color_scat_incomplete = []

        try:
            for i, txt in enumerate(list(gl)):
                if txt in complete:
                    annotate = self.ui.canvas_3.axes.annotate(
                        txt, (x[i], y[i]), horizontalalignment='left',
                        verticalalignment='top', annotation_clip=True,
                        fontsize=11,
                        color=self.color_complete[
                            complete.index(txt)
                        ],
                        size=10
                    )
                    self.annotation_3.append(annotate)
                    self.x_complete.append([x[i], y[i]])
                    color_scat_complete.append(
                        self.color_complete[self.complete.index(txt)]
                    )
                elif txt in incomplete:
                    annotate = self.ui.canvas_3.axes.annotate(
                        txt, (x[i], y[i]), horizontalalignment='left',
                        verticalalignment='top', annotation_clip=True,
                        fontsize=11,
                        color=self.color_incomplete[
                            incomplete.index(txt)
                        ],
                        size=10
                    )
                    self.annotation_3.append(annotate)
                    self.x_incomplete.append([x[i], y[i]])
                    color_scat_incomplete.append(
                        self.color_incomplete[incomplete.index(txt)]
                    )
        except:
            print("FIXME")

        self.tableView.model().blockSignals(False)
        self.ui.canvas_3.figure.canvas.draw_idle()

    def get_line_gl_colors(self, line_2d):
        colors = []

        for line in line_2d:
            colors.append(line[0].get_color())

        return colors

    def get_station(self, ind: int):
        return self._reach.profile(ind).get_station()

    def get_elevation(self, ind: int):
        return self._reach.profile(ind).z()

    def update_graphic_3(self, ind: int):
        self.tableView.model().blockSignals(True)

        # ind - 1
        if ind != 0:
            self.profile_i_minus_1.set_data(
                self.get_station(ind - 1),
                self.get_elevation(ind - 1)
            )
        else:
            self.profile_i_minus_1.set_data([], [])

        # ind
        self.profile_i.set_data(
            self.get_station(ind),
            self.get_elevation(ind)
        )

        # ind + 1
        if ind != self._tablemodel.rowCount() - 1:
            self.profile_i_plus_1.set_data(
                self.get_station(ind + 1),
                self.get_elevation(ind + 1)
            )
        else:
            self.profile_i_plus_1.set_data([], [])

        self.tableView.model().blockSignals(False)

        # Update graphic 3
        self.update_annotate_3(ind)
        self.ui.canvas_3.axes.relim()
        self.ui.canvas_3.axes.autoscale_view()
        self.ui.canvas_3.figure.canvas.draw_idle()

    def select_plot_graphic_1(self, ind: int):
        self.tableView.model().blockSignals(True)

        if 0 <= ind < self._tablemodel.rowCount():
            self.plot_selected_1.set_data(self._reach.profile(ind).x(),
                                          self._reach.profile(ind).y())
            self.plot_selected_1.set_visible(True)

        self.tableView.model().blockSignals(False)

    def select_plot_graphic_2(self, ind: int):
        kp_i = self._reach.profile(ind).kp
        z_min_i = self._reach.profile(ind).z_min()
        z_max_i = self._reach.profile(ind).z_max()

        if 0 <= ind < self._tablemodel.rowCount():
            self.plot_selected_2.set_data((kp_i, kp_i),
                                          (z_min_i, z_max_i))
            self.plot_selected_2.set_visible(True)

    def select_before_plot_selected_1(self, ind: int):
        if 0 <= ind < self._tablemodel.rowCount():
            self.before_plot_selected_1.set_data(
                self._reach.profile(ind).x(),
                self._reach.profile(ind).y()
            )

            self.before_plot_selected_1.set_visible(True)
            self.ui.canvas_1.figure.canvas.draw_idle()

    def select_after_plot_selected_1(self, ind: int):
        if 0 <= ind < self._tablemodel.rowCount():
            self.after_plot_selected_1.set_data(
                self._reach.profile(ind).x(),
                self._reach.profile(ind).y()
            )

            self.after_plot_selected_1.set_visible(True)
            self.ui.canvas_1.figure.canvas.draw_idle()

    def select_before_plot_selected_2(self, ind: int):
        if 0 <= ind < self._tablemodel.rowCount():
            kp_i = self._reach.profile(ind).kp
            z_min_i = self._reach.profile(ind).z_min()
            z_max_i = self._reach.profile(ind).z_max()

            self.before_plot_selected_2.set_data(
                (kp_i, kp_i),
                (z_min_i, z_max_i)
            )

            self.before_plot_selected_2.set_visible(True)
            self.ui.canvas_2.figure.canvas.draw_idle()

    def select_after_plot_selected_2(self, ind: int):
        if 0 <= ind < self._tablemodel.rowCount():
            kp_i = self._reach.profile(ind).kp
            z_min_i = self._reach.profile(ind).z_min()
            z_max_i = self._reach.profile(ind).z_max()

            self.after_plot_selected_2.set_data(
                (kp_i, kp_i),
                (z_min_i, z_max_i)
            )

            self.after_plot_selected_2.set_visible(True)
            self.ui.canvas_2.figure.canvas.draw_idle()

    def select_row_profile_slider(self, ind: int = 0):
        if self.tableView is not None:
            selectionModel = self.tableView.selectionModel()
            index = self.tableView.model().index(ind, 0)

            selectionModel.select(
                index,
                QItemSelectionModel.Rows |
                QItemSelectionModel.ClearAndSelect |
                QItemSelectionModel.Select
            )

            self.tableView.scrollTo(index)

    def select_current_profile(self):
        self.tableView.model().blockSignals(True)

        if len(self.tableView.selectedIndexes()) > 0:
            row = self.index_selected_row()

            self.ui.verticalSlider.setValue(row)
            self.select_plot_graphic_1(row)
            self.select_plot_graphic_2(row)

            if row == 0:
                self.before_plot_selected_1.set_visible(False)
                self.select_after_plot_selected_1(row + 1)
                self.before_plot_selected_2.set_visible(False)
                self.select_after_plot_selected_2(row + 1)
            elif 0 < row < self._tablemodel.rowCount() - 1:
                self.select_before_plot_selected_1(row - 1)
                self.select_after_plot_selected_1(row + 1)
                self.select_before_plot_selected_2(row - 1)
                self.select_after_plot_selected_2(row + 1)
            elif row == self._tablemodel.rowCount() - 1:
                self.after_plot_selected_1.set_visible(False)
                self.select_before_plot_selected_1(row - 1)
                self.after_plot_selected_2.set_visible(False)
                self.select_before_plot_selected_2(row - 1)

            self.tableView.model().blockSignals(False)
            self.update_graphic_3(row)
            self.ui.canvas_1.figure.canvas.draw_idle()
            self.ui.canvas_2.figure.canvas.draw_idle()

    def changed_slider_value(self):
        self.tableView.model().blockSignals(True)

        if self._tablemodel.rowCount() != 0:
            self.ui.verticalSlider.setMaximum(self._tablemodel.rowCount() - 1)

            slider_value = self.ui.verticalSlider.value()
            kp = self._reach.profile(slider_value).kp

            self.ui.vertical_slider_label.setText(
                _translate("MainWindow_reach", "Kp : ") +
                f"{kp}" + "\n" +
                _translate("MainWindow_reach",
                           "Profil N° : ") +
                f"{slider_value + 1}"
            )

            self.select_plot_graphic_1(slider_value)
            self.select_plot_graphic_2(slider_value)
            self.select_row_profile_slider(slider_value)

        self.tableView.model().blockSignals(False)

    def increment_value_slider(self):
        if 0 <= self.ui.verticalSlider.value() < self._tablemodel.rowCount() - 1:
            self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1)

    def decrement_value_slider(self):
        if 0 < self.ui.verticalSlider.value() < self._tablemodel.rowCount():
            self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1)

    def insert_row(self):
        if len(self.tableView.selectedIndexes()) == 0:
            self._tablemodel.insertRows(self._tablemodel.rowCount(), 1)
        else:
            row = self.index_selected_row()
            self._tablemodel.insertRows(row + 1, 1)

        if self.filename is not None:
            self.graphic_1()
            self.graphic_2()
            self.select_current_profile()

    def delete_row(self):
        rows = list(set(
            [index.row() for index in self.tableView.selectedIndexes()]
        ))

        if len(rows) > 0:
            self._tablemodel.remove_rows(rows)

        self.update_graphic_1()
        self.select_current_profile()

        self.graphic_2()
        self.changed_slider_value()


    def index_selected_row(self):
        return self.tableView\
                   .selectionModel()\
                   .selectedRows()[0]\
                   .row()

    def sort_ascending(self):
        self._tablemodel.sort_profiles(True)
        self.select_current_profile()
        self.changed_slider_value()

        self.update_graphic_2()
        self.update_graphic_3(self.index_selected_row())

    def sort_descending(self):
        self._tablemodel.sort_profiles(False)

        self.select_current_profile()
        self.changed_slider_value()

        self.update_graphic_2()
        self.update_graphic_3(self.index_selected_row())

    def move_row_down(self):
        row = self.index_selected_row()

        if row < self._tablemodel.rowCount() - 1:
            self._tablemodel.moveRowDown(row)
            self.update_graphic_3(row + 1)
            self.ui.canvas_3.axes.relim()
            self.ui.canvas_3.axes.autoscale_view()

            if row < self._tablemodel.rowCount() - 2:
                self.select_before_plot_selected_1(row)
                self.select_after_plot_selected_1(row + 2)
                self.select_before_plot_selected_2(row)
                self.select_after_plot_selected_2(row + 2)

            if row == self._tablemodel.rowCount() - 2:
                self.select_before_plot_selected_1(self._tablemodel.rowCount() - 2)
                self.after_plot_selected_1.set_visible(False)
                self.select_before_plot_selected_2(self._tablemodel.rowCount() - 2)
                self.after_plot_selected_2.set_visible(False)

            self.update_graphic_2()

    def move_row_up(self):
        row = self.index_selected_row()

        if 0 < row <= self._tablemodel.rowCount() - 1:
            self._tablemodel.moveRowUp(row)

            if row == 1:
                self.select_after_plot_selected_1(row)
                self.before_plot_selected_1.set_visible(False)
                self.select_after_plot_selected_2(row)
                self.before_plot_selected_2.set_visible(False)

            elif row == self._tablemodel.rowCount() - 1:
                self.select_before_plot_selected_1(row - 2)
                self.select_after_plot_selected_1(row)
                self.select_before_plot_selected_2(row - 2)
                self.select_after_plot_selected_2(row)

            else:
                self.select_before_plot_selected_1(row - 2)
                self.select_after_plot_selected_1(row)
                self.select_before_plot_selected_2(row - 2)
                self.select_after_plot_selected_2(row)

            self.update_graphic_2()
            self.update_graphic_3(row - 1)
            self.ui.canvas_3.axes.relim()
            self.ui.canvas_3.axes.autoscale_view()

    def handleSave(self):
        options = QFileDialog.Options()
        DEFAULT_DIRECTORY = '/home/'
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
        current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
        options |= QFileDialog.DontUseNativeDialog

        filename, filters = QFileDialog.getSaveFileName(
            self,
            filter=_translate("MainWindow_reach",
                              "Files .ST(*.ST or *.st)")
            + ";; " +
            _translate("MainWindow_reach", "All files "
                       "(*)"),
            options=options
        )

        current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY

        if filename != '':
            self._tablemodel.export_reach(filename)

    def handleOpen(self):
        filename, filterName = QFileDialog.getOpenFileName(self)

        if filename != '':
            with open(filename, 'r') as f:
                reader = csv.reader(f, delimiter='\t')
                header = next(reader)
                buf = []
                for row in reader:
                    row[0] = QCheckBox("-")
                    buf.append(row)

                self._tablemodel = None
                self._tablemodel = qtableview_reach.PandasModelEditable(buf)
                self.tableView.setModel(self._tablemodel)
                filename = ''