"""
Rectangle Map Tool for QPredict

Custom map tool for drawing rectangular selection on QGIS canvas.
Used for defining inference extent in 'Selection (Draw)' mode.
"""

from qgis.PyQt.QtCore import Qt, pyqtSignal
from qgis.PyQt.QtGui import QColor
from qgis.gui import QgsMapTool, QgsRubberBand
from qgis.core import QgsWkbTypes, QgsRectangle, QgsPointXY


class RectangleMapTool(QgsMapTool):
    """
    Map tool for drawing rectangles on canvas.
    
    User clicks to set first corner, then drags to define rectangle,
    and clicks again to finalize.
    
    Signals:
        rectangle_created(QgsRectangle): Emitted when rectangle is finalized
        
    Example:
        >>> tool = RectangleMapTool(canvas)
        >>> tool.rectangle_created.connect(on_rectangle_drawn)
        >>> canvas.setMapTool(tool)
    """
    
    rectangle_created = pyqtSignal(QgsRectangle)
    
    def __init__(self, canvas):
        """
        Initialize rectangle map tool.
        
        Args:
            canvas: QgsMapCanvas instance
        """
        super().__init__(canvas)
        self.canvas = canvas
        
        # Rubber band for visual feedback
        self.rubber_band = QgsRubberBand(
            self.canvas,
            QgsWkbTypes.PolygonGeometry
        )
        
        # Style: transparent fill with blue border
        self.rubber_band.setColor(QColor(0, 0, 255, 50))
        self.rubber_band.setWidth(2)
        self.rubber_band.setLineStyle(Qt.SolidLine)
        
        # State
        self.start_point = None
        self.end_point = None
        self.is_drawing = False
    
    def canvasPressEvent(self, event):
        """
        Handle mouse press event.
        
        Args:
            event: QgsMapMouseEvent
        """
        if event.button() == Qt.LeftButton:
            # Get click position in map coordinates
            point = self.toMapCoordinates(event.pos())
            
            if not self.is_drawing:
                # First click: start drawing
                self.start_point = point
                self.is_drawing = True
                self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
            else:
                # Second click: finalize rectangle
                self.end_point = point
                self._finalize_rectangle()
    
    def canvasMoveEvent(self, event):
        """
        Handle mouse move event.
        
        Args:
            event: QgsMapMouseEvent
        """
        if self.is_drawing and self.start_point:
            # Update rubber band to show current rectangle
            current_point = self.toMapCoordinates(event.pos())
            self._update_rubber_band(self.start_point, current_point)
    
    def canvasReleaseEvent(self, event):
        """
        Handle mouse release event (not used, but required).
        
        Args:
            event: QgsMapMouseEvent
        """
        pass
    
    def keyPressEvent(self, event):
        """
        Handle key press event.
        
        Args:
            event: QKeyEvent
        """
        # Allow ESC to cancel drawing
        if event.key() == Qt.Key_Escape:
            self.reset()
    
    def _update_rubber_band(self, start_point, end_point):
        """
        Update rubber band to show rectangle.
        
        Args:
            start_point: QgsPointXY - first corner
            end_point: QgsPointXY - opposite corner
        """
        self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
        
        # Create rectangle corners
        x_min = min(start_point.x(), end_point.x())
        x_max = max(start_point.x(), end_point.x())
        y_min = min(start_point.y(), end_point.y())
        y_max = max(start_point.y(), end_point.y())
        
        # Add points to rubber band (rectangle)
        self.rubber_band.addPoint(QgsPointXY(x_min, y_min))
        self.rubber_band.addPoint(QgsPointXY(x_max, y_min))
        self.rubber_band.addPoint(QgsPointXY(x_max, y_max))
        self.rubber_band.addPoint(QgsPointXY(x_min, y_max))
        self.rubber_band.addPoint(QgsPointXY(x_min, y_min)) 
        
        self.rubber_band.show()
    
    def _finalize_rectangle(self):
        """
        Finalize rectangle and emit signal.
        """
        if self.start_point and self.end_point:
            # Create QgsRectangle
            rectangle = QgsRectangle(self.start_point, self.end_point)
            
            # Emit signal
            self.rectangle_created.emit(rectangle)
            
            # DON'T reset - keep rubber band visible
            # Just reset drawing state
            self.start_point = None
            self.end_point = None
            self.is_drawing = False

    def clear_rectangle(self):
        """
        Clear the rectangle from canvas.
        """
        self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
    
    def reset(self):
        """
        Reset tool state and clear rubber band.
        """
        self.start_point = None
        self.end_point = None
        self.is_drawing = False
        self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
    
    def deactivate(self):
        """
        Called when tool is deactivated.
        """
        self.reset()
        super().deactivate()