# -*- coding: utf-8 -*-
# gui/components/model_view/_scenario_camera.py
"""Камерный сценарий — базовый слой, всегда активен.

Обрабатывает ПКМ (вращение), СКМ (панорамирование), подавление ЛКМ drag.
Политика камеры текущего доменного сценария определяет, работает ли этот слой.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from PySide6.QtCore import Qt
from PySide6.QtGui import QGuiApplication

from gui.components.model_view._interaction_scenario import (
    CameraPolicy,
    InteractionScenario,
)
from error_logger import log_exception

if TYPE_CHECKING:  # pragma: no cover
    from gui.components.model_view_widget import ModelViewWidget


class CameraScenario(InteractionScenario):
    """Базовый камерный слой: вращение (ПКМ), панорамирование (СКМ)."""

    name = "camera"
    camera_policy = CameraPolicy.FREE

    def on_mouse_press(self, mv: "ModelViewWidget", event) -> bool:
        if event.button() == Qt.MouseButton.RightButton:
            # В режиме контура ПКМ передаётся PyVista (remove point)
            if mv._zone_selection_mode and mv.is_scenario_active("contour_edit"):
                return False
            mv._cam_rotate_active = True
            mv._cam_last_pos = (event.position().x(), event.position().y())
            return True

        if event.button() == Qt.MouseButton.MiddleButton:
            mv._cam_pan_active = True
            mv._cam_last_pos = (event.position().x(), event.position().y())
            return True
        return False

    def on_mouse_move(self, mv: "ModelViewWidget", event) -> bool:
        # Safeguard: если release-событие потерялось (после модалок/фокуса),
        # синхронизируем drag-флаги с реальным состоянием кнопок мыши.
        try:
            real_buttons = QGuiApplication.mouseButtons()
        except Exception as _exc:
            real_buttons = Qt.MouseButton.NoButton
        if mv._cam_rotate_active and not (real_buttons & Qt.MouseButton.RightButton):
            mv._cam_rotate_active = False
            mv._cam_last_pos = None
        if mv._cam_pan_active and not (real_buttons & Qt.MouseButton.MiddleButton):
            mv._cam_pan_active = False
            mv._cam_last_pos = None

        # Подавление ЛКМ drag (не конфликтует с click-сценариями)
        if hasattr(event, "buttons") and (event.buttons() & Qt.MouseButton.LeftButton):
            return True

        # ПКМ drag → вращение камеры
        if (
            mv._cam_rotate_active
            and hasattr(event, "buttons")
            and (event.buttons() & Qt.MouseButton.RightButton)
        ):
            cx, cy = mv._cam_last_pos or (event.position().x(), event.position().y())
            nx, ny = event.position().x(), event.position().y()
            dx, dy = float(nx - cx), float(ny - cy)
            mv._cam_last_pos = (nx, ny)
            try:
                cam = mv._plotter.camera
                cam.Azimuth(-dx * 0.35)
                cam.Elevation(dy * 0.35)
                cam.OrthogonalizeViewUp()
                if hasattr(mv, "_reset_camera_clipping_range"):
                    mv._reset_camera_clipping_range()
                mv._safe_render(min_interval_s=1.0 / 75.0)
            except Exception as _exc:
                log_exception(__name__, "on_mouse_move", _exc)
            return True

        # СКМ drag → панорамирование
        if (
            mv._cam_pan_active
            and hasattr(event, "buttons")
            and (event.buttons() & Qt.MouseButton.MiddleButton)
        ):
            cx, cy = mv._cam_last_pos or (event.position().x(), event.position().y())
            nx, ny = event.position().x(), event.position().y()
            dx, dy = float(nx - cx), float(ny - cy)
            mv._cam_last_pos = (nx, ny)
            mv._pan_camera_by_pixels(dx, dy)
            try:
                if hasattr(mv, "_reset_camera_clipping_range"):
                    mv._reset_camera_clipping_range()
                mv._safe_render(min_interval_s=1.0 / 75.0)
            except Exception as _exc:
                log_exception(__name__, "on_mouse_move", _exc)
            return True
        return False

    def on_mouse_release(self, mv: "ModelViewWidget", event) -> bool:
        if event.button() == Qt.MouseButton.RightButton:
            mv._cam_rotate_active = False
            mv._cam_last_pos = None
            return True
        if event.button() == Qt.MouseButton.MiddleButton:
            mv._cam_pan_active = False
            mv._cam_last_pos = None
            return True
        return False
