# -*- coding: utf-8 -*-
# gui/components/model_view/contour/contour_preview_contour_component.py

# -*- coding: utf-8 -*-
# gui/components/model_view/_mv_grid_preview_contour.py
# Восстановление/загрузка контура, задание размеров и помощники запроса выбранного объёма.
from __future__ import annotations
from typing import TYPE_CHECKING

from error_logger import log_exception

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

class ContourPreviewContourComponent:
    def set_selected_volume_dimensions(
        self: "ModelViewWidget",
        dim_x: float, dim_y: float, dim_z: float,
    ) -> None:
        """Изменить разметку по значениям из панели свойств зоны."""
        if not self._grid_cells or not self._selected_cells:
            return

        step = max(1.0, float(self._current_zone_size))
        z_step = max(1.0, float(getattr(self, "_current_zone_z_size", self._current_zone_size)))
        max_height = self._get_max_height_for_start_z()
        dim_z = min(float(dim_z), float(max_height))
        cells_z = max(1, int(round(max(z_step, dim_z) / z_step)))

        # Контурный или заблокированный режим — меняем только высоту.
        if (
            self.is_scenario_active("contour_edit")
            or getattr(self, "_contour_points", None)
            or getattr(self, "_volume_locked_from_contour", False)
        ):
            self._selected_height = float(max(0, min(
                (cells_z - 1) * z_step, self._get_max_height_for_start_z() - z_step
            )))
            self._update_selection_visualization()
            return

        if not self._zone_selection_mode:
            return

        cells_x = max(1, int(round(max(step, dim_x) / step)))
        cells_y = max(1, int(round(max(step, dim_y) / step)))

        anchor = self._selection_anchor or self._resolve_selection_anchor()
        if not anchor:
            return
        anchor_x, anchor_y = anchor
        target_max_x = anchor_x + cells_x * step
        target_max_y = anchor_y + cells_y * step

        new_selected = set()
        eps = 1e-6
        for cid, (c_mn_x, c_mx_x, c_mn_y, c_mx_y) in self._grid_cells.items():
            if (
                c_mn_x >= anchor_x - eps and c_mx_x <= target_max_x + eps
                and c_mn_y >= anchor_y - eps and c_mx_y <= target_max_y + eps
            ):
                new_selected.add(cid)

        if new_selected:
            self._selected_cells = new_selected
        self._selected_height = float(max(0, min(
            (cells_z - 1) * z_step, self._get_max_height_for_start_z() - z_step
        )))
        self._selection_anchor = (anchor_x, anchor_y)
        self._update_selection_visualization()

    def restore_contour_definition_from_final(self: "ModelViewWidget") -> bool:
        """Восстановить режим редактирования контура из финализированных точек контура."""
        final_points = list(getattr(self, "_final_contour_points", []) or [])
        if len(final_points) < 4:
            return False
        if not self._grid_cells:
            return False
        try:
            self._zone_selection_mode = True
            self._volume_locked_from_contour = False
            self._contour_points = [(float(x), float(y)) for x, y in final_points]
            if (
                getattr(self, "_contour_zone_overlay_enabled", False)
                and getattr(self, "_contour_zone_mode", None) == "overlay"
                and getattr(self, "_contour_zone_id", None)
            ):
                try:
                    self._hide_grid_actors()
                    self._build_surface_grid_on_zone(str(self._contour_zone_id))
                except Exception as e:
                    log_exception(__name__, "restore_contour_definition_from_final", e)
            else:
                try:
                    self._show_grid_actors()
                except Exception as e:
                    log_exception(__name__, "restore_contour_definition_from_final", e)
            self._update_selected_cells_from_contour()
            self._update_contour_visualization()
            self._update_selection_visualization()
            emit_ready = getattr(self, "_emit_contour_ready_state", None)
            if callable(emit_ready):
                emit_ready()
            return True
        except Exception as e:
            log_exception(__name__, "restore_contour_definition_from_final", e)
            return False

    def load_contour_definition(self: "ModelViewWidget", points: list[tuple[float, float]]) -> bool:
        """Загрузить существующие точки контура в активный режим редактирования контура."""
        src_points = list(points or [])
        if len(src_points) < 4 or not self._grid_cells:
            return False
        try:
            normalized: list[tuple[float, float]] = []
            for px, py in src_points:
                nx = float(px)
                ny = float(py)
                node = self._nearest_grid_node(nx, ny)
                if node is not None:
                    normalized.append((float(node[0]), float(node[1])))
                else:
                    normalized.append((nx, ny))
            normalized = self._dedupe_contour_points(normalized)
            normalized = self._simplify_collinear_contour_points(normalized, closed=True)
            if len(normalized) < 4:
                return False
            self._zone_selection_mode = True
            self._volume_locked_from_contour = False
            self._selected_height = 0
            self._contour_points = [(float(x), float(y)) for x, y in normalized]
            self._final_contour_points = list(self._contour_points)
            self._update_selected_cells_from_contour()
            self._update_contour_visualization()
            self._update_selection_visualization()
            emit_ready = getattr(self, "_emit_contour_ready_state", None)
            if callable(emit_ready):
                emit_ready()
            return bool(self._selected_cells)
        except Exception as e:
            log_exception(__name__, "load_contour_definition", e)
            return False

    def get_selected_volume_points(self: "ModelViewWidget") -> list[tuple[float, float]]:
        """Вернуть точки контура выбранного объёма (XY)."""
        if getattr(self, "_final_contour_points", None):
            return [(float(x), float(y)) for x, y in self._final_contour_points]
        polygon = self._extract_orthogonal_polygon() if hasattr(self, "_extract_orthogonal_polygon") else None
        if polygon:
            return [(float(x), float(y)) for x, y in polygon]
        if not self._selected_cells:
            return []
        cells = [self._grid_cells[cid] for cid in self._selected_cells]
        mn_x = min(c[0] for c in cells)
        mx_x = max(c[1] for c in cells)
        mn_y = min(c[2] for c in cells)
        mx_y = max(c[3] for c in cells)
        return [
            (float(mn_x), float(mn_y)),
            (float(mx_x), float(mn_y)),
            (float(mx_x), float(mx_y)),
            (float(mn_x), float(mx_y)),
        ]

    def get_selected_volume_start_height(self: "ModelViewWidget") -> float:
        """Получить начальную высоту выбранного объёма (Z)."""
        return float(getattr(self, "_last_volume_start_height", 0.0))

    def get_selected_volume_height(self: "ModelViewWidget") -> float:
        """Получить полную высоту выбранного объёма."""
        z_step = max(1.0, float(getattr(self, "_current_zone_z_size", self._current_zone_size)))
        height = max(z_step, z_step + float(self._selected_height))
        max_height = self._get_max_height_for_start_z()
        return float(min(height, max_height))
