
from qgis.core import QgsPointXY, QgsWkbTypes
from qgis.gui import *

from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *


class MapDigitizeTool(QgsMapTool):

    moved = pyqtSignal(dict)
    leftClicked = pyqtSignal(dict)
    rightClicked = pyqtSignal(dict)

    def __init__(self, canvas):

        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        #self.cursor = QCursor(Qt.CrossCursor)

    def canvasMoveEvent(self, event):

        self.moved.emit({'x': event.pos().x(), 'y': event.pos().y()})

    def canvasReleaseEvent(self, event):

        if event.button() == Qt.MouseButton.RightButton:
            self.rightClicked.emit({'x': event.pos().x(), 'y': event.pos().y()})
        elif event.button() == Qt.MouseButton.LeftButton:
            self.leftClicked.emit({'x': event.pos().x(), 'y': event.pos().y()})
        else:
            return

    def activate(self):

        QgsMapTool.activate(self)
        #self.canvas.setCursor(self.cursor)

    def deactivate(self):

        QgsMapTool.deactivate(self)

    def isZoomTool(self):

        return False

    def setCursor(self, cursor):

        self.cursor = QCursor(cursor)

"""
Modified from: profiletool, script: tools/ptmaptool.py

#-----------------------------------------------------------
# 
# Profile
# Copyright (C) 2008  Borys Jurgiel
# Copyright (C) 2012  Patrice Verchere
#-----------------------------------------------------------
# 
# licensed under the terms of GNU GPL 2
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program; if not, print to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#---------------------------------------------------------------------
"""


class EmitPointFromCanvas(QgsMapToolEmitPoint):

    def __init__(self, canvas, button):
        super().__init__(canvas)
        self.canvas = canvas
        self.button = button
        super().setCursor(QCursor(Qt.CursorShape.CrossCursor))  # applica davvero

    def setCursor(self, cursor):

        # applica davvero sul tool (non solo salva in un attributo)
        super().setCursor(QCursor(cursor))


class RectangleMapTool(QgsMapTool):
    """
    Canvas tool to draw a rectangle (drag out from a corner) and then, once
    defined, pan/translate it at fixed size by dragging inside it.
    Emits (xmin, ymin, xmax, ymax) tuples in canvas/project CRS.
    """

    rectangleDefined = pyqtSignal(tuple)
    rectangleMoving = pyqtSignal(tuple)
    rectangleMoved = pyqtSignal(tuple)

    def __init__(self, canvas):

        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas

        self.rubberband = QgsRubberBand(self.canvas, QgsWkbTypes.GeometryType.PolygonGeometry)
        self.rubberband.setWidth(2)
        self.rubberband.setColor(QColor(255, 0, 0, 80))
        self.rubberband.setFillColor(QColor(255, 0, 0, 40))

        self._mode = "drawing"
        self._anchor = None
        self._rect = None
        self._drag_start = None
        self._rect_at_drag_start = None

    @staticmethod
    def _normalized_rect(pt_a, pt_b):

        x0, y0 = pt_a
        x1, y1 = pt_b
        return min(x0, x1), min(y0, y1), max(x0, x1), max(y0, y1)

    @staticmethod
    def _translated_rect(rect, dx, dy):

        xmin, ymin, xmax, ymax = rect
        return xmin + dx, ymin + dy, xmax + dx, ymax + dy

    def _update_rubberband(self, rect):

        xmin, ymin, xmax, ymax = rect

        self.rubberband.reset(QgsWkbTypes.GeometryType.PolygonGeometry)
        self.rubberband.addPoint(QgsPointXY(xmin, ymin))
        self.rubberband.addPoint(QgsPointXY(xmax, ymin))
        self.rubberband.addPoint(QgsPointXY(xmax, ymax))
        self.rubberband.addPoint(QgsPointXY(xmin, ymax))
        self.rubberband.addPoint(QgsPointXY(xmin, ymin))

    def redefine(self):

        self._mode = "drawing"
        self._anchor = None
        self._rect = None
        self._drag_start = None
        self._rect_at_drag_start = None
        self.rubberband.reset(QgsWkbTypes.GeometryType.PolygonGeometry)

    def canvasPressEvent(self, event):

        if event.button() != Qt.MouseButton.LeftButton:
            return

        pt = self.toMapCoordinates(event.pos())

        if self._mode == "drawing":
            self._anchor = (pt.x(), pt.y())
        elif self._mode == "moving" and self._rect is not None:
            self._drag_start = (pt.x(), pt.y())
            self._rect_at_drag_start = self._rect

    def canvasMoveEvent(self, event):

        pt = self.toMapCoordinates(event.pos())

        if self._mode == "drawing" and self._anchor is not None:

            rect = self._normalized_rect(self._anchor, (pt.x(), pt.y()))
            self._update_rubberband(rect)

        elif self._mode == "moving" and self._drag_start is not None:

            dx = pt.x() - self._drag_start[0]
            dy = pt.y() - self._drag_start[1]
            rect = self._translated_rect(self._rect_at_drag_start, dx, dy)
            self._update_rubberband(rect)
            self.rectangleMoving.emit(rect)

    def canvasReleaseEvent(self, event):

        if event.button() != Qt.MouseButton.LeftButton:
            return

        pt = self.toMapCoordinates(event.pos())

        if self._mode == "drawing" and self._anchor is not None:

            rect = self._normalized_rect(self._anchor, (pt.x(), pt.y()))
            self._update_rubberband(rect)
            self._rect = rect
            self._anchor = None
            self._mode = "moving"
            self.rectangleDefined.emit(rect)

        elif self._mode == "moving" and self._drag_start is not None:

            dx = pt.x() - self._drag_start[0]
            dy = pt.y() - self._drag_start[1]
            rect = self._translated_rect(self._rect_at_drag_start, dx, dy)
            self._update_rubberband(rect)
            self._rect = rect
            self._drag_start = None
            self._rect_at_drag_start = None
            self.rectangleMoved.emit(rect)

    def activate(self):

        QgsMapTool.activate(self)
        self.canvas.setCursor(QCursor(Qt.CursorShape.CrossCursor))

    def deactivate(self):

        self.rubberband.reset(QgsWkbTypes.GeometryType.PolygonGeometry)
        QgsMapTool.deactivate(self)

    def isZoomTool(self):

        return False


def xy_from_canvas(
        canvas,
        position
):
    """
    Convert canvas pixel coordinates to map coordinates.
    Uses QGIS 3.x modern API instead of deprecated getCoordinateTransform().
    """
    # Use mapSettings() to convert pixel coordinates to map coordinates
    map_settings = canvas.mapSettings()
    # mapToPixel() provides the transform, toMapCoordinates() converts pixel to map coords
    map_point = map_settings.mapToPixel().toMapCoordinates(position["x"], position["y"])
    
    return map_point.x(), map_point.y()


