# -*- coding: utf-8 -*-
"""
LVT4U — Flycam Photos: Map Click Tool.

QgsMapTool that handles clicking on photo points in the map canvas
to trigger the Photo Viewer.

Author: Lộc Vũ Trung (LVT) / Slow Forest
License: GPL-3.0

Based on ImportPhotos plugin (GPL-2.0+) by KIOS Research Center.
"""

from qgis.PyQt.QtCore import Qt, pyqtSignal
from qgis.core import (
    QgsMapLayer,
    QgsProject,
    QgsRectangle,
    Qgis,
)
from qgis.gui import QgsMapTool

import os


class FlycamClickTool(QgsMapTool):
    """Map tool for clicking on photo points and emitting photo info.

    Signals:
        photoClicked(str, dict): Emitted with (photo_path, feature_attrs)
                                 when user clicks a photo point.
    """

    photoClicked = pyqtSignal(str, dict)

    def __init__(self, canvas, iface, layer_name=None):
        """Initialize the click tool.

        Args:
            canvas: QgsMapCanvas instance.
            iface: QgisInterface instance.
            layer_name: Optional name of the photo layer to query.
        """
        super().__init__(canvas)
        self.iface = iface
        self.canvas = canvas
        self.layer_name = layer_name

        # Set cursor to crosshair
        self.setCursor(Qt.CrossCursor)

    def set_layer_name(self, name):
        """Update the target layer name."""
        self.layer_name = name

    def canvasPressEvent(self, event):
        """Handle mouse press — identify nearest photo point."""
        if event.button() != Qt.LeftButton:
            return

        # Get click position in map coordinates
        point = self.toMapCoordinates(event.pos())

        # Find the target layer
        layer = self._find_layer()
        if not layer:
            self.iface.messageBar().pushWarning(
                "LVT4U — Flycam",
                "No photo layer found. Import photos first."
            )
            return

        # Build a small search rectangle around the click point
        # Scale the tolerance based on current map scale
        scale = self.canvas.mapUnitsPerPixel()
        tolerance = scale * 15  # 15 pixels tolerance

        search_rect = QgsRectangle(
            point.x() - tolerance, point.y() - tolerance,
            point.x() + tolerance, point.y() + tolerance
        )

        # Query features in the rectangle
        layer.selectByRect(search_rect, Qgis.SelectBehavior.SetSelection)
        selected = layer.selectedFeatures()

        if not selected:
            return

        # Find the closest feature
        closest = None
        min_dist = float('inf')
        for feat in selected:
            geom = feat.geometry()
            if geom.isNull():
                continue
            dist = geom.distance(
                __import__('qgis.core', fromlist=['QgsGeometry'])
                .QgsGeometry.fromPointXY(point)
            )
            if dist < min_dist:
                min_dist = dist
                closest = feat

        if closest is None:
            return

        # Extract photo path from feature
        attrs = {}
        field_names = [f.name() for f in layer.fields()]
        for i, name in enumerate(field_names):
            attrs[name] = closest.attribute(i)

        photo_path = attrs.get('Path', '')

        # Check if photo file exists
        if photo_path and os.path.isfile(photo_path):
            self.photoClicked.emit(photo_path, attrs)
        else:
            self.iface.messageBar().pushWarning(
                "LVT4U — Flycam",
                f"Photo not found: {photo_path}"
            )

        # Deselect
        layer.removeSelection()

    def _find_layer(self):
        """Find the photo layer by name.

        Returns:
            QgsVectorLayer or None.
        """
        if not self.layer_name:
            return None

        layers = QgsProject.instance().mapLayersByName(self.layer_name)
        for lyr in layers:
            if lyr.type() == QgsMapLayer.VectorLayer:
                return lyr
        return None
