# Copyright (c) 2025, UChicago Argonne, LLC
# BSD OPEN SOURCE LICENSE. Full license can be found in LICENSE
# Copyright (c) 2025, UChicago Argonne, LLC
# BSD OPEN SOURCE LICENSE. Full license can be found in LICENSE
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QCursor
from qgis.core import QgsSpatialIndex, QgsGeometry
from qgis.gui import QgsMapToolDigitizeFeature

from .net_editor import NetEditor


class LinkAdder(NetEditor):
    def __init__(self, qgis_proj):
        super().__init__(qgis_proj)

        self.linkTool = QgsMapToolDigitizeFeature(self.canvas, self.iface.cadDockWidget())
        self.linkTool.setAutoSnapEnabled(True)
        self.stdCursor = QCursor(Qt.ArrowCursor)
        self.attempts = 0
        self.link_layer = self._PQgis.layers["link"][0]

    def do_add_link_with_template(self):
        link_layer = self._PQgis.layers["link"][0]
        self.reference_feature = list(link_layer.selectedFeatures())
        if len(self.reference_feature) != 1:
            self.do_identify_link()
        else:
            self.reference_feature = self.reference_feature[0]
            self.set_tool()

    def identified_template(self):
        link_layer = self._PQgis.layers["link"][0]
        lindex = QgsSpatialIndex(self.link_layer.getFeatures())
        point = self.clickTool.toLayerCoordinates(self.link_layer, self.clickTool.point)
        nearest = lindex.nearestNeighbor(point, 1)
        pnt = QgsGeometry().fromPointXY(point)
        distances = [link_layer.getFeature(i).geometry().distance(pnt) for i in nearest]
        self.reference_feature = link_layer.getFeature(nearest[distances.index(min(distances))])
        self.set_tool()

    def set_tool(self):
        if isinstance(self.linkTool, QgsMapToolDigitizeFeature):
            self.canvas.setMapTool(self.linkTool)
        self.linkTool.digitizingCompleted.connect(self.do_build_link)

    def do_identify_link(self):
        self.canvas.setCursor(QCursor(Qt.CrossCursor))
        self.canvas.setMapTool(self.clickTool)
        self.clickTool.clicked.connect(self.identified_template)

    def do_build_link(self, nfeat):
        self.link_layer.beginEditCommand("break it")
        self.attempts = 0
        layer_fields = self.link_layer.fields()
        all_fields = [x.name() for x in layer_fields]
        provider = self.link_layer.dataProvider()

        feat = self.reference_feature

        lid = self.link_layer.maximumValue(all_fields.index("link")) + 1

        # There seems to be a precision issue with the digitizer, so we make sure things are precise
        node_layer = self._PQgis.layers["node"][0]
        nindex = QgsSpatialIndex(node_layer.getFeatures())
        points = nfeat.geometry().asPolyline()
        start, finish = [node_layer.getFeature(nindex.nearestNeighbor(points[i], 1)[0]) for i in [0, -1]]

        if start.geometry().distance(QgsGeometry().fromPointXY(points[0])) < 0.1:
            points[0] = start.geometry().asPoint()

        if finish.geometry().distance(QgsGeometry().fromPointXY(points[-1])) < 0.1:
            points[-1] = finish.geometry().asPoint()

        geo = QgsGeometry().fromPolylineXY(points)
        # We begin again because there is something weird
        # Can remove this new feature when we figure out what is the issue
        # nfeat = QgsFeature(layer_fields)

        for f in layer_fields:
            if f.name() == "link":
                nfeat.setAttribute(f.name(), lid)
            elif f.name() in ["bearing_a", "bearing_b", "length", "node_a", "node_b", "setback_a", "setback_b"]:
                nfeat.setAttribute(f.name(), 0)
            else:
                nfeat.setAttribute(f.name(), feat[f.name()])

        nfeat.setGeometry(geo)
        provider.addFeature(nfeat)
        self.link_layer.commitChanges()
        self.link_layer.endEditCommand()
        self.editing()
