# app.py

import sys
import time
import csv
import StringIO
from . import __appname__, __version__, __author__, __organization__
from PySide import QtGui, QtCore
from view.gui_main import Ui_MainWindow
from view.gui_crest import Ui_CrestDialog
from view.gui_tripwire import Ui_TripwireDialog
from view.gui_about import Ui_AboutDialog
from model.navigation import Navigation
from model.navprocessor import NavProcessor
from model.evedb import EveDb
from model.crestprocessor import CrestProcessor
from model.versioncheck import VersionCheck


def dict_from_csvqfile(file_path):
    reader = None

    qfile = QtCore.QFile(file_path)
    if qfile.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text):
        text = qfile.readAll()
        f = StringIO.StringIO(text)
        reader = csv.reader(f, delimiter=';')

    return reader


class CrestDialog(QtGui.QDialog, Ui_CrestDialog):
    """
    CREST Configuration Window
    """
    def __init__(self, implicit, client_id, client_secret, parent=None):
        super(CrestDialog, self).__init__(parent)
        self.setupUi(self)
        # noinspection PyUnresolvedReferences
        self.radioButton_implicit.toggled.connect(self.stuff)
        if implicit:
            self.radioButton_implicit.setChecked(True)
        else:
            self.radioButton_user.setChecked(True)
        self.lineEdit_client_id.setText(client_id)
        self.lineEdit_client_secret.setText(client_secret)
        self._credentials_enable(not self.radioButton_implicit.isChecked())

    def _credentials_enable(self, state):
        if state:
            self.lineEdit_client_id.setEnabled(True)
            self.lineEdit_client_id.setReadOnly(False)
            self.lineEdit_client_secret.setEnabled(True)
            self.lineEdit_client_secret.setReadOnly(False)
        else:
            self.lineEdit_client_id.setEnabled(False)
            self.lineEdit_client_id.setReadOnly(True)
            self.lineEdit_client_secret.setEnabled(False)
            self.lineEdit_client_secret.setReadOnly(True)

    @QtCore.Slot()
    def stuff(self):
        self._credentials_enable(not self.radioButton_implicit.isChecked())


class TripwireDialog(QtGui.QDialog, Ui_TripwireDialog):
    """
    Tripwire Configuration Window
    """
    def __init__(self, trip_url, trip_user, trip_pass, evescout_enable, parent=None):
        super(TripwireDialog, self).__init__(parent)
        self.setupUi(self)
        self.lineEdit_url.setText(trip_url)
        self.lineEdit_user.setText(trip_user)
        self.lineEdit_pass.setText(trip_pass)
        self.checkBox_evescout.setChecked(evescout_enable)
        self.label_evescout_logo.mouseDoubleClickEvent = TripwireDialog.logo_double_click

    @staticmethod
    def logo_double_click(event):
        event.accept()
        QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://www.eve-scout.com/"))


class AboutDialog(QtGui.QDialog, Ui_AboutDialog):
    """
    Tripwire Configuration Window
    """
    def __init__(self, author, version, parent=None):
        super(AboutDialog, self).__init__(parent)
        self.setupUi(self)
        self.label_title.setText("Short Circuit {}".format(version))
        self.label_author.setText("Creator: {}".format(author))
        # noinspection PyUnresolvedReferences
        self.pushButton_o7.clicked.connect(self.close)
        self.label_icon.mouseDoubleClickEvent = AboutDialog.icon_double_click

    @staticmethod
    def icon_double_click(event):
        event.accept()
        QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://github.com/farshield/shortcircuit"))


class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    """
    Main Window GUI
    """

    MSG_OK = 2
    MSG_ERROR = 1
    MSG_INFO = 0

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.settings = QtCore.QSettings(
            QtCore.QSettings.IniFormat,
            QtCore.QSettings.UserScope,
            __organization__,
            __appname__
        )

        self.scene_banner = None
        self.tripwire_url = None
        self.tripwire_user = None
        self.tripwire_pass = None
        self.evescout_enable = None
        self.crest_implicit = None
        self.crest_client_id = None
        self.crest_client_secret = None

        # Table configuration
        self.tableWidget_path.setColumnCount(5)
        self.tableWidget_path.setHorizontalHeaderLabels(
            ["System name", "Class", "Security", "Instructions", "Additional information"]
        )
        self.tableWidget_path.horizontalHeader().setStretchLastSection(True)

        # Read stored settings
        self.read_settings()

        # Read resources
        gates = [[int(rows[0]), int(rows[1])] for rows in dict_from_csvqfile(":database/system_jumps.csv")]
        system_desc = {
            int(rows[0]): [rows[1], rows[2], float(rows[3])]
            for rows in dict_from_csvqfile(":database/system_description.csv")
        }
        wh_codes = {rows[0]: int(rows[1]) for rows in dict_from_csvqfile(":database/statics.csv")}
        self.nav = Navigation(
            gates,
            system_desc,
            wh_codes,
            self.tripwire_url,
            self.tripwire_user,
            self.tripwire_pass
        )

        # Additional GUI setup
        self.additional_gui_setup()
        self.label_status_bar = QtGui.QLabel("Not connected to EvE")
        self.statusBar().addWidget(self.label_status_bar, 1)
        if self.evescout_enable:
            self.label_evescout_status.setText("Eve-Scout: enabled")
        else:
            self.label_evescout_status.setText("Eve-Scout: disabled")

        # Icons
        self.icon_wormhole = QtGui.QIcon(":images/wh_icon.png")

        # Thread initial config
        self.worker_thread = QtCore.QThread()
        self.nav_processor = NavProcessor(self.nav)
        self.nav_processor.moveToThread(self.worker_thread)
        self.nav_processor.finished.connect(self.thread_done)
        # noinspection PyUnresolvedReferences
        self.worker_thread.started.connect(self.nav_processor.process)

        # Version check thread
        self.version_thread = QtCore.QThread()
        self.version_check = VersionCheck()
        self.version_check.moveToThread(self.version_thread)
        self.version_check.finished.connect(self.version_check_done)
        # noinspection PyUnresolvedReferences
        self.version_thread.started.connect(self.version_check.process)

        # CREST
        self.eve_connected = False
        self.crestp = CrestProcessor(
            implicit=self.crest_implicit,
            client_id=self.crest_client_id,
            client_secret=self.crest_client_secret,
        )
        self.crestp.login_response.connect(self.login_handler)
        self.crestp.logout_response.connect(self.logout_handler)
        self.crestp.location_response.connect(self.location_handler)
        self.crestp.destination_response.connect(self.destination_handler)

        # Start version check
        self.version_thread.start()

    # noinspection PyUnresolvedReferences
    def additional_gui_setup(self):
        # Additional GUI setup
        self.graphicsView_banner.mouseDoubleClickEvent = MainWindow.banner_double_click
        self.setWindowTitle(__appname__)
        self.scene_banner = QtGui.QGraphicsScene()
        self.graphicsView_banner.setScene(self.scene_banner)
        self.scene_banner.addPixmap(QtGui.QPixmap(":images/banner.png"))
        self._path_message("", MainWindow.MSG_OK)
        self._avoid_message("", MainWindow.MSG_OK)
        self.lineEdit_source.setFocus()

        # Auto-completion
        system_list = self.nav.eve_db.system_name_list()
        for line_edit_field in [
            self.lineEdit_source,
            self.lineEdit_destination,
            self.lineEdit_avoid_name,
            self.lineEdit_set_dest,
        ]:
            completer = QtGui.QCompleter(system_list, self)
            completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
            line_edit_field.setCompleter(completer)

        # Signals
        self.pushButton_eve_login.clicked.connect(self.btn_eve_login_clicked)
        self.pushButton_player_location.clicked.connect(self.btn_player_location_clicked)
        self.pushButton_find_path.clicked.connect(self.btn_find_path_clicked)
        self.pushButton_crest_config.clicked.connect(self.btn_crest_config_clicked)
        self.pushButton_trip_config.clicked.connect(self.btn_trip_config_clicked)
        self.pushButton_trip_get.clicked.connect(self.btn_trip_get_clicked)
        self.pushButton_avoid_add.clicked.connect(self.btn_avoid_add_clicked)
        self.pushButton_avoid_delete.clicked.connect(self.btn_avoid_delete_clicked)
        self.pushButton_avoid_clear.clicked.connect(self.btn_avoid_clear_clicked)
        self.pushButton_set_dest.clicked.connect(self.btn_set_dest_clicked)
        self.pushButton_reset.clicked.connect(self.btn_reset_clicked)
        self.lineEdit_source.returnPressed.connect(self.line_edit_source_return)
        self.lineEdit_destination.returnPressed.connect(self.line_edit_destination_return)
        self.lineEdit_avoid_name.returnPressed.connect(self.line_edit_avoid_name_return)
        self.lineEdit_set_dest.returnPressed.connect(self.btn_set_dest_clicked)
        self.tableWidget_path.itemSelectionChanged.connect(self.table_item_selection_changed)

    def read_settings(self):
        self.settings.beginGroup("MainWindow")

        # Window state
        win_geometry = self.settings.value("win_geometry")
        if win_geometry:
            self.restoreGeometry(win_geometry)
        win_state = self.settings.value("win_state")
        if win_state:
            self.restoreState(win_state)
        for col_idx, column_width in enumerate(self.settings.value("table_widths", "110,75,75,180").split(',')):
            self.tableWidget_path.setColumnWidth(col_idx, int(column_width))

        # CREST info
        self.crest_implicit = True if self.settings.value("crest_implicit", "true") == "true" else False
        self.crest_client_id = self.settings.value("crest_client_id", "")
        self.crest_client_secret = self.settings.value("crest_client_secret", "")

        # Tripwire info
        self.tripwire_url = self.settings.value("tripwire_url", "https://tripwire.eve-apps.com")
        self.tripwire_user = self.settings.value("tripwire_user", "username")
        self.tripwire_pass = self.settings.value("tripwire_pass", "password")

        # Eve-Scout
        self.evescout_enable = self.settings.value("evescout_enable", "false") == "true"

        # Avoidance list
        self.checkBox_avoid_enabled.setChecked(
            True if self.settings.value("avoidance_enabled", "false") == "true" else False
        )
        for sys_name in self.settings.value("avoidance_list", "").split(','):
            if sys_name != "":
                self._avoid_system_name(sys_name)

        # Restrictions
        self.comboBox_size.setCurrentIndex(
            int(self.settings.value("restrictions_whsize", "0"))
        )
        self.checkBox_eol.setChecked(
            True if self.settings.value("restriction_eol", "false") == "true" else False
        )
        self.checkBox_masscrit.setChecked(
            True if self.settings.value("restriction_masscrit", "false") == "true" else False
        )
        self.checkBox_ignore_old.setChecked(
            True if self.settings.value("restriction_ignore_old", "false") == "true" else False
        )
        self.doubleSpinBox_hours.setValue(
            float(self.settings.value("restriction_hours", "16.0"))
        )

        # Security prioritization
        self.checkBox_security_enabled.setChecked(
            True if self.settings.value("security_enabled", "false") == "true" else False
        )
        self.spinBox_prio_hs.setValue(int(self.settings.value("prio_hs", "1")))
        self.spinBox_prio_ls.setValue(int(self.settings.value("prio_ls", "1")))
        self.spinBox_prio_ns.setValue(int(self.settings.value("prio_ns", "1")))
        self.spinBox_prio_wh.setValue(int(self.settings.value("prio_wh", "1")))

        self.settings.endGroup()

    def write_settings(self):
        self.settings.beginGroup("MainWindow")

        # Window state
        self.settings.setValue("win_geometry", self.saveGeometry())
        self.settings.setValue("win_state", self.saveState())
        self.settings.setValue("table_widths", ",".join([
            str(self.tableWidget_path.columnWidth(0)),
            str(self.tableWidget_path.columnWidth(1)),
            str(self.tableWidget_path.columnWidth(2)),
            str(self.tableWidget_path.columnWidth(3)),
        ]))

        # Crest info
        self.settings.setValue("crest_implicit", self.crest_implicit)
        self.settings.setValue("crest_client_id", self.crest_client_id)
        self.settings.setValue("crest_client_secret", self.crest_client_secret)

        # Tripwire info
        self.settings.setValue("tripwire_url", self.tripwire_url)
        self.settings.setValue("tripwire_user", self.tripwire_user)
        self.settings.setValue("tripwire_pass", self.tripwire_pass)

        # Eve-Scout
        self.settings.setValue("evescout_enable", self.evescout_enable)

        # Avoidance list
        self.settings.setValue(
            "avoidance_enabled",
            self.checkBox_avoid_enabled.isChecked()
        )
        avoidance_list_string = ",".join(self.avoidance_list())
        self.settings.setValue(
            "avoidance_list",
            avoidance_list_string
        )

        # Restrictions
        self.settings.setValue(
            "restrictions_whsize",
            self.comboBox_size.currentIndex()
        )
        self.settings.setValue(
            "restriction_eol",
            self.checkBox_eol.isChecked()
        )
        self.settings.setValue(
            "restriction_masscrit",
            self.checkBox_masscrit.isChecked()
        )
        self.settings.setValue(
            "restriction_ignore_old",
            self.checkBox_ignore_old.isChecked()
        )
        self.settings.setValue(
            "restriction_hours",
            self.doubleSpinBox_hours.value()
        )

        # Security prioritization
        self.settings.setValue(
            "security_enabled",
            self.checkBox_security_enabled.isChecked()
        )
        self.settings.setValue("prio_hs", self.spinBox_prio_hs.value())
        self.settings.setValue("prio_ls", self.spinBox_prio_ls.value())
        self.settings.setValue("prio_ns", self.spinBox_prio_ns.value())
        self.settings.setValue("prio_wh", self.spinBox_prio_wh.value())

        self.settings.endGroup()

    def _message_box(self, title, text):
        msg_box = QtGui.QMessageBox(self)
        msg_box.setWindowTitle(title)
        msg_box.setText(text)
        return msg_box.exec_()

    @staticmethod
    def _label_message(label, message, message_type):
        if message_type == MainWindow.MSG_OK:
            label.setStyleSheet("QLabel {color: green;}")
        elif message_type == MainWindow.MSG_ERROR:
            label.setStyleSheet("QLabel {color: red;}")
        else:
            label.setStyleSheet("QLabel {color: black;}")
        label.setText(message)

    def _avoid_message(self, message, message_type):
        MainWindow._label_message(self.label_avoid_status, message, message_type)

    def _path_message(self, message, message_type):
        MainWindow._label_message(self.label_status, message, message_type)

    def _trip_message(self, message, message_type):
        MainWindow._label_message(self.label_trip_status, message, message_type)

    def _statusbar_message(self, message, message_type):
        MainWindow._label_message(self.label_status_bar, message, message_type)

    def avoidance_enabled(self):
        return self.checkBox_avoid_enabled.isChecked()

    def avoidance_list(self):
        items = []
        for index in xrange(self.listWidget_avoid.count()):
            items.append(self.listWidget_avoid.item(index))
        return [i.text() for i in items]

    def _avoid_system_name(self, sys_name):
        if sys_name:
            if sys_name not in self.avoidance_list():
                QtGui.QListWidgetItem(sys_name, self.listWidget_avoid)
                self._avoid_message("Added", MainWindow.MSG_OK)
            else:
                self._avoid_message("Already in list!", MainWindow.MSG_ERROR)
        else:
            self._avoid_message("Invalid system name :(", MainWindow.MSG_ERROR)

    def avoid_system(self):
        sys_name = self.nav.eve_db.normalize_name(
            self.lineEdit_avoid_name.text()
        )
        self._avoid_system_name(sys_name)

    def add_data_to_table(self, route):
        self.tableWidget_path.setRowCount(len(route))
        for i, row in enumerate(route):
            for j, col in enumerate(row):
                item = QtGui.QTableWidgetItem("{}".format(col))
                self.tableWidget_path.setItem(i, j, item)

                if j in [1, 2]:
                    self.tableWidget_path.item(i, j).setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)

                if row[1] == "HS":
                    color = QtGui.QColor(223, 240, 216)
                elif row[1] == "LS":
                    color = QtGui.QColor(252, 248, 227)
                elif row[1] == "NS":
                    color = QtGui.QColor(242, 222, 222)
                else:
                    color = QtGui.QColor(210, 226, 242)

                if j == 3 and "wormhole" in col:
                    self.tableWidget_path.item(i, j).setIcon(self.icon_wormhole)
                self.tableWidget_path.item(i, j).setBackground(color)
                self.tableWidget_path.item(i, j).setForeground(QtGui.QColor(0, 0, 0))

    def get_restrictions(self):
        size_restriction = []

        combo_index = self.comboBox_size.currentIndex()
        if combo_index < 1:
            size_restriction.append(EveDb.WHSIZE_S)
        if combo_index < 2:
            size_restriction.append(EveDb.WHSIZE_M)
        if combo_index < 3:
            size_restriction.append(EveDb.WHSIZE_L)
        if combo_index < 4:
            size_restriction.append(EveDb.WHSIZE_XL)

        ignore_eol = self.checkBox_eol.isChecked()
        ignore_masscrit = self.checkBox_masscrit.isChecked()
        if self.checkBox_ignore_old.isChecked():
            age_threshold = self.doubleSpinBox_hours.value()
        else:
            age_threshold = 0

        return [size_restriction, ignore_eol, ignore_masscrit, age_threshold]

    def _clear_results(self):
        self.tableWidget_path.setRowCount(0)
        self.lineEdit_short_format.setText("")

    def find_path(self):
        source_sys_name = self.nav.eve_db.normalize_name(
            self.lineEdit_source.text().strip()
        )
        dest_sys_name = self.nav.eve_db.normalize_name(
            self.lineEdit_destination.text().strip()
        )

        if self.avoidance_enabled():
            if dest_sys_name in self.avoidance_list():
                self._path_message("Destination in avoidance list, dummy ;)", MainWindow.MSG_ERROR)
                self._clear_results()
                return

        [size_restriction, ignore_eol, ignore_masscrit, age_threshold] = self.get_restrictions()
        if self.checkBox_security_enabled.isChecked():
            security_prio = [
                self.spinBox_prio_hs.value(),
                self.spinBox_prio_ls.value(),
                self.spinBox_prio_ns.value(),
                self.spinBox_prio_wh.value(),
            ]
        else:
            security_prio = []

        if source_sys_name and dest_sys_name:
            if self.avoidance_enabled():
                [route, short_format] = self.nav.route(
                    source_sys_name,
                    dest_sys_name,
                    self.avoidance_list(),
                    size_restriction,
                    security_prio,
                    ignore_eol,
                    ignore_masscrit,
                    age_threshold
                )
            else:
                [route, short_format] = self.nav.route(
                    source_sys_name,
                    dest_sys_name,
                    [],
                    size_restriction,
                    security_prio,
                    ignore_eol,
                    ignore_masscrit,
                    age_threshold
                )

            if route:
                route_length = len(route)
                if route_length == 1:
                    self._path_message("Set the same source and destination :P", MainWindow.MSG_OK)
                else:
                    self._path_message("Total number of jumps: {}".format(route_length - 1), MainWindow.MSG_OK)

                self.add_data_to_table(route)
                self.lineEdit_short_format.setText(short_format)
            else:
                self._clear_results()
                self._path_message("No path found between the solar systems.", MainWindow.MSG_ERROR)
        else:
            self._clear_results()
            error_msg = []
            if not source_sys_name:
                error_msg.append("source")
            if not dest_sys_name:
                error_msg.append("destination")
            error_msg = "Invalid system name in {}.".format(" and ".join(error_msg))
            self._path_message(error_msg, MainWindow.MSG_ERROR)

    @staticmethod
    def banner_double_click(event):
        event.accept()
        AboutDialog(__author__, __version__).exec_()

    @QtCore.Slot(str)
    def login_handler(self, char_name):
        if char_name:
            self._statusbar_message("Welcome, {}".format(char_name), MainWindow.MSG_OK)
            self.pushButton_eve_login.setText("Logout")
            self.pushButton_player_location.setEnabled(True)
            self.pushButton_set_dest.setEnabled(True)
            self.eve_connected = True
        else:
            self._statusbar_message("Error: Unable to connect with CREST", MainWindow.MSG_ERROR)

    @QtCore.Slot()
    def logout_handler(self):
        self._statusbar_message("Not connected to EvE", MainWindow.MSG_INFO)
        self.pushButton_eve_login.setText("Log in with EvE")
        self.pushButton_player_location.setEnabled(False)
        self.pushButton_set_dest.setEnabled(False)
        self.eve_connected = False

    @QtCore.Slot(str)
    def location_handler(self, location):
        if location:
            self.lineEdit_source.setText(location)
        else:
            self._message_box("Player destination", "Unable to get location (character not online or CREST error)")
        self.pushButton_player_location.setEnabled(True)

    @QtCore.Slot(bool)
    def destination_handler(self, response):
        if not response:
            self._message_box("Player destination", "CREST error when trying to set destination")
        self.pushButton_set_dest.setEnabled(True)

    @QtCore.Slot(int)
    def thread_done(self, connections, evescout_connections):
        self.worker_thread.quit()

        # wait for thread to finish
        while self.worker_thread.isRunning():
            time.sleep(0.01)

        if self.evescout_enable:
            if evescout_connections >= 0:
                self.label_evescout_status.setText("Eve-Scout: {} connections".format(evescout_connections))
            else:
                self.label_evescout_status.setText("Eve-Scout: error :(")
        else:
            self.label_evescout_status.setText("Eve-Scout: disabled")
        if connections > 0:
            self._trip_message(
                "Retrieved {} Tripwire connections!".format(connections),
                MainWindow.MSG_OK
            )
        elif connections == 0:
            self._trip_message(
                "No Tripwire connections exist!",
                MainWindow.MSG_ERROR
            )
        else:
            self._trip_message(
                "Tripwire error. Check url/user/pass.",
                MainWindow.MSG_ERROR
            )

        self.pushButton_trip_get.setEnabled(True)
        self.pushButton_find_path.setEnabled(True)

    @QtCore.Slot()
    def btn_eve_login_clicked(self):
        if not self.eve_connected:
            url = self.crestp.login()
            QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromEncoded(url))
        else:
            self.crestp.logout()

    @QtCore.Slot()
    def btn_player_location_clicked(self):
        self.pushButton_player_location.setEnabled(False)
        self.crestp.get_location()

    @QtCore.Slot()
    def btn_set_dest_clicked(self):
        if self.pushButton_set_dest.isEnabled():
            dest_sys_name = self.nav.eve_db.normalize_name(
                self.lineEdit_set_dest.text().strip()
            )
            sys_id = self.nav.eve_db.name2id(dest_sys_name)
            if sys_id:
                self.pushButton_set_dest.setEnabled(False)
                self.crestp.set_destination(sys_id)
            else:
                if self.lineEdit_set_dest.text().strip() == "":
                    msg_txt = "No system name give as input"
                else:
                    msg_txt = "Invalid system name: '{}'".format(self.lineEdit_set_dest.text())
                self._message_box("Player destination", msg_txt)

    @QtCore.Slot()
    def btn_find_path_clicked(self):
        self.find_path()

    @QtCore.Slot()
    def btn_crest_config_clicked(self):
        crest_dialog = CrestDialog(self.crest_implicit, self.crest_client_id, self.crest_client_secret)
        if crest_dialog.exec_():
            self.crest_implicit = crest_dialog.radioButton_implicit.isChecked()
            self.crest_client_id = crest_dialog.lineEdit_client_id.text()
            self.crest_client_secret = crest_dialog.lineEdit_client_secret.text()
            self.crestp.crest.update_credentials(
                self.crest_implicit,
                self.crest_client_id,
                self.crest_client_secret,
            )

    @QtCore.Slot()
    def btn_trip_config_clicked(self):
        tripwire_dialog = TripwireDialog(
            self.tripwire_url,
            self.tripwire_user,
            self.tripwire_pass,
            self.evescout_enable
        )
        if tripwire_dialog.exec_():
            self.tripwire_url = tripwire_dialog.lineEdit_url.text()
            self.tripwire_user = tripwire_dialog.lineEdit_user.text()
            self.tripwire_pass = tripwire_dialog.lineEdit_pass.text()
            self.nav.tripwire_set_login(
                self.tripwire_url,
                self.tripwire_user,
                self.tripwire_pass
            )
            self.evescout_enable = tripwire_dialog.checkBox_evescout.isChecked()
            if self.evescout_enable:
                self.label_evescout_status.setText("Eve-Scout: enabled")
            else:
                self.label_evescout_status.setText("Eve-Scout: disabled")

    @QtCore.Slot()
    def btn_trip_get_clicked(self):
        if not self.worker_thread.isRunning():
            self.pushButton_trip_get.setEnabled(False)
            self.pushButton_find_path.setEnabled(False)
            self.nav_processor.evescout_enable = self.evescout_enable
            self.worker_thread.start()
        else:
            self._trip_message("Error! Process already running", MainWindow.MSG_ERROR)

    @QtCore.Slot()
    def btn_avoid_add_clicked(self):
        self.avoid_system()

    @QtCore.Slot()
    def btn_avoid_delete_clicked(self):
        for item in self.listWidget_avoid.selectedItems():
            self.listWidget_avoid.takeItem(self.listWidget_avoid.row(item))

    @QtCore.Slot()
    def btn_avoid_clear_clicked(self):
        self.listWidget_avoid.clear()

    @QtCore.Slot()
    def btn_reset_clicked(self):
        msg_box = QtGui.QMessageBox(self)
        msg_box.setWindowTitle("Reset chain")
        msg_box.setText("Are you sure you want to clear all Tripwire data?")
        msg_box.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        msg_box.setDefaultButton(QtGui.QMessageBox.No)
        ret = msg_box.exec_()

        if ret == QtGui.QMessageBox.Yes:
            self.nav.reset_chain()
            self._trip_message("Not connected to Tripwire, yet", MainWindow.MSG_INFO)

    @QtCore.Slot()
    def line_edit_avoid_name_return(self):
        self.avoid_system()

    @QtCore.Slot()
    def line_edit_source_return(self):
        self.lineEdit_destination.setFocus()

    @QtCore.Slot()
    def line_edit_destination_return(self):
        self.find_path()

    def _table_style(self, red_value, green_value, blue_value):
        self.tableWidget_path.setStyleSheet(
            "selection-color: black; selection-background-color: rgb({}, {}, {});".format(
                red_value,
                green_value,
                blue_value,
            )
        )

    @QtCore.Slot()
    def table_item_selection_changed(self):
        selection = self.tableWidget_path.selectedItems()
        if selection:
            sys_class = selection[1].text()
            if sys_class == "HS":
                self._table_style(193, 210, 186)
            elif sys_class == "LS":
                self._table_style(222, 218, 197)
            elif sys_class == "NS":
                self._table_style(212, 192, 192)
            else:
                self._table_style(180, 196, 212)

            self.lineEdit_set_dest.setText(selection[0].text())

    @QtCore.Slot(str)
    def version_check_done(self, version):
        self.version_thread.quit()

        if version and __version__ != version:
            version_box = QtGui.QMessageBox(self)
            version_box.setWindowTitle("New version available!")
            version_box.setText(
                "You have version '{}', but there's a new version available: '{}'.".format(__version__, version)
            )
            version_box.addButton("Download now", QtGui.QMessageBox.AcceptRole)
            version_box.addButton("Remind me later", QtGui.QMessageBox.RejectRole)
            ret = version_box.exec_()

            if ret == QtGui.QMessageBox.AcceptRole:
                QtGui.QDesktopServices.openUrl(
                    QtCore.QUrl("https://github.com/farshield/shortcircuit/releases/tag/{}".format(version))
                )

    # event: QCloseEvent
    def closeEvent(self, event):
        self.write_settings()
        event.accept()


def run():
    appl = QtGui.QApplication(sys.argv)
    form = MainWindow()
    form.show()
    appl.exec_()