class RemotesDialog(QDialog):
    def __init__(self, parent, repo):
        QDialog.__init__(self, parent,
                         Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.changed = False
        self.repo = repo
        self.remotes = repo.remotes()
        self.setupUi()

    def setupUi(self):
        self.resize(500, 350)
        self.setWindowTitle("Remotes manager")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setSpacing(2)
        self.horizontalLayout.setMargin(0)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Vertical)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
        self.table = QTableWidget()
        self.table.verticalHeader().setVisible(False)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.addRowButton = QPushButton()
        self.addRowButton.setText("Add remote")
        self.editRowButton = QPushButton()
        self.editRowButton.setText("Edit remote")
        self.removeRowButton = QPushButton()
        self.removeRowButton.setText("Remove remote")
        self.buttonBox.addButton(self.addRowButton,
                                 QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.editRowButton,
                                 QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.removeRowButton,
                                 QDialogButtonBox.ActionRole)
        self.setTableContent()
        self.horizontalLayout.addWidget(self.table)
        self.horizontalLayout.addWidget(self.buttonBox)
        self.setLayout(self.horizontalLayout)

        self.buttonBox.rejected.connect(self.close)
        self.editRowButton.clicked.connect(self.editRow)
        self.addRowButton.clicked.connect(self.addRow)
        self.removeRowButton.clicked.connect(self.removeRow)

        QMetaObject.connectSlotsByName(self)
        self.editRowButton.setEnabled(False)
        self.removeRowButton.setEnabled(False)

    def setTableContent(self):
        self.table.clear()
        self.table.setColumnCount(2)
        self.table.setColumnWidth(0, 200)
        self.table.setColumnWidth(1, 200)
        self.table.setHorizontalHeaderLabels(["Name", "URL"])
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.table.setRowCount(len(self.remotes))
        for i, name in enumerate(self.remotes):
            url = self.remotes[name]
            self.table.setRowHeight(i, 22)
            item = QTableWidgetItem(name, 0)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.table.setItem(i, 0, item)
            item = QTableWidgetItem(url, 0)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.table.setItem(i, 1, item)

        self.table.itemSelectionChanged.connect(self.selectionChanged)

    def selectionChanged(self):
        enabled = len(self.table.selectedItems()) > 0
        self.editRowButton.setEnabled(enabled)
        self.removeRowButton.setEnabled(enabled)

    def editRow(self):
        item = self.table.item(self.table.currentRow(), 0)
        if item is not None:
            name = item.text()
            url = self.table.item(self.table.currentRow(), 1).text()
            dlg = NewRemoteDialog(name, url, self)
            dlg.exec_()
            if dlg.ok:
                self.repo.removeremote(name)
                self.repo.addremote(dlg.name, dlg.url)
                del self.remotes[name]
                self.remotes[dlg.name] = dlg.url
                self.setTableContent()
                self.changed = True

    def removeRow(self):
        item = self.table.item(self.table.currentRow(), 0)
        if item is not None:
            name = item.text()
            self.repo.removeremote(name)
            del self.remotes[name]
            self.setTableContent()
            self.changed = True

    def addRow(self):
        dlg = NewRemoteDialog(parent=self)
        dlg.exec_()
        if dlg.ok:
            self.repo.addremote(dlg.name, dlg.url)
            self.remotes[dlg.name] = dlg.url
            self.setTableContent()
            self.changed = True
class LinzValidationResultsDockWidget(QgsDockWidget):
    """
    LINZ Specific validation results dock widget
    """
    def __init__(self, _iface=None):
        """
        Constructor for LINZ redistricting dock
        :param context: initial dock context
        :param iface: QGIS interface
        """
        super().__init__()

        if _iface is not None:
            self.iface = _iface
        else:
            self.iface = iface

        dock_contents = QWidget()
        grid = QGridLayout(dock_contents)
        grid.setContentsMargins(0, 0, 0, 0)

        self.setWidget(dock_contents)

        self.setObjectName('LinzValidationResultsDock')
        self.setWindowTitle(self.tr('Validation Results'))
        self.table = None

    def zoom_to_extent(self, geom: QgsGeometry):
        """
        Zooms the canvas to the given extent
        :param geom: extent to zoom to
        """
        self.iface.mapCanvas().zoomToFeatureExtent(geom.boundingBox())

    def clear(self):
        """
        Clears existing validation results from the dock
        """
        if self.table is not None:
            self.table.deleteLater()
            self.table = None

    def show_validation_results(self, results):
        """
        Shows the results of a validation run
        :param results: validation results
        """
        self.clear()

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(['', 'Electorate', 'Error'])

        def create_zoom_button(geom: QgsGeometry):
            """
            Creates a zoom to electorate button
            :param geom: extent to zoom to
            """
            button = QToolButton()
            if geom.isEmpty():
                button.setEnabled(False)
                button.setToolTip('Electorate has no meshblocks assigned')
            else:
                button.setToolTip('Zoom to Electorate')
            button.setIcon(GuiUtils.get_icon('zoom_selected.svg'))
            button.clicked.connect(partial(self.zoom_to_extent, geom))
            return button

        self.table.setRowCount(0)

        def add_electorate(
                electorate_id,
                name: str,
                error: str,  # pylint: disable=unused-argument
                geom: QgsGeometry):
            """
            Adds an electorate to the results table
            :param electorate_id: electorate ID
            :param name: electorate name
            :param error: error string
            :param geom: electorate geometry
            """
            flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
            name_item = QTableWidgetItem(name)
            name_item.setFlags(flags)
            error_item = QTableWidgetItem(error)
            error_item.setFlags(flags)

            row = self.table.rowCount()
            self.table.setRowCount(row + 1)

            self.table.setItem(row, 1, name_item)
            self.table.setItem(row, 2, error_item)
            self.table.setCellWidget(row, 0, create_zoom_button(geom))

        for result in results:
            add_electorate(electorate_id=result[ValidationTask.ELECTORATE_ID],
                           name=result[ValidationTask.ELECTORATE_NAME],
                           error=result[ValidationTask.ERROR],
                           geom=result[ValidationTask.ELECTORATE_GEOMETRY])

        self.table.setColumnWidth(0, 30)
        self.widget().layout().addWidget(self.table, 1, 0, 1, 1)
class RemotesDialog(QDialog):
    def __init__(self, parent, repo):
        QDialog.__init__(self, parent, Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.changed = False
        self.repo = repo
        self.remotes = repo.remotes()
        self.setupUi()

    def setupUi(self):
        self.resize(500, 350)
        self.setWindowTitle("Remote connections manager")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setSpacing(2)
        self.horizontalLayout.setMargin(0)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Vertical)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
        self.table = QTableWidget()
        self.table.verticalHeader().setVisible(False)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.addRowButton = QPushButton()
        self.addRowButton.setText("Add connection")
        self.editRowButton = QPushButton()
        self.editRowButton.setText("Edit connection")
        self.removeRowButton = QPushButton()
        self.removeRowButton.setText("Remove connection")
        self.buttonBox.addButton(self.addRowButton, QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.editRowButton, QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.removeRowButton, QDialogButtonBox.ActionRole)
        self.setTableContent()
        self.horizontalLayout.addWidget(self.table)
        self.horizontalLayout.addWidget(self.buttonBox)
        self.setLayout(self.horizontalLayout)

        self.buttonBox.rejected.connect(self.close)
        self.editRowButton.clicked.connect(self.editRow)
        self.addRowButton.clicked.connect(self.addRow)
        self.removeRowButton.clicked.connect(self.removeRow)

        QMetaObject.connectSlotsByName(self)
        self.editRowButton.setEnabled(False)
        self.removeRowButton.setEnabled(False)

    def setTableContent(self):
        self.table.clear()
        self.table.setColumnCount(2)
        self.table.setColumnWidth(0, 200)
        self.table.setColumnWidth(1, 200)
        self.table.setHorizontalHeaderLabels(["Name", "URL"])
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.table.setRowCount(len(self.remotes))
        for i, name in enumerate(self.remotes):
            url = self.remotes[name]
            self.table.setRowHeight(i, 22)
            item = QTableWidgetItem(name, 0)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.table.setItem(i, 0, item)
            item = QTableWidgetItem(url, 0)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.table.setItem(i, 1, item)

        self.table.itemSelectionChanged.connect(self.selectionChanged)

    def selectionChanged(self):
        enabled = len(self.table.selectedItems()) > 0
        self.editRowButton.setEnabled(enabled)
        self.removeRowButton.setEnabled(enabled)

    def editRow(self):
        item = self.table.item(self.table.currentRow(), 0)
        if item is not None:
            name = item.text()
            url = self.table.item(self.table.currentRow(), 1).text()
            dlg = NewRemoteDialog(name, url, self)
            dlg.exec_()
            if dlg.ok:
                self.repo.removeremote(name)
                self.repo.addremote(dlg.name, dlg.url)
                del self.remotes[name]
                self.remotes[dlg.name] = dlg.url
                self.setTableContent()
                self.changed = True



    def removeRow(self):
        item = self.table.item(self.table.currentRow(), 0)
        if item is not None:
            name = item.text()
            self.repo.removeremote(name)
            del self.remotes[name]
            self.setTableContent()
            self.changed = True

    def addRow(self):
        dlg = NewRemoteDialog(parent = self)
        dlg.exec_()
        if dlg.ok:
            try:
                self.repo.addremote(dlg.name, dlg.url)                
                self.remotes[dlg.name] = dlg.url
                self.setTableContent()
                self.changed = True
            except HTTPError:
                QMessageBox.warning(self, 'Cannot add remote connection',
                "Remote connection could not be added.\n"
                "Ensure that the entered data is correct and the geogig server is running.",
                QMessageBox.Ok)