# -*- coding: utf-8 -*-
# gui/components/model_view/_mv_scene_modes.py
"""Высокоуровневые переходы между режимами сцены для ModelViewWidget."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from gui.components.model_view_widget import ModelViewWidget


class SceneModesMixin:
    """Фасад переходов между режимами facility/zone."""

    def _apply_facility_shell_visibility(self: "ModelViewWidget") -> None:
        """Профиль оболочки уровня facility: активен только пол, остальные слои отключены."""
        layer_defaults = (
            ("floor", True),
            ("walls", False),
            ("ceiling", False),
            ("truss", False),
        )
        for key, should_show in layer_defaults:
            is_available = bool(self.has_model(key)) if hasattr(self, "has_model") else True
            self.set_model_visibility(key, bool(should_show and is_available))

    def set_zone_pick_mode(self: "ModelViewWidget", enabled: bool) -> None:
        """Переключить режим выбора зоны с обновлением сцены."""
        self.set_zone_pick_enabled(bool(enabled))
        self.update_scene()

    def enter_facility_overview(self: "ModelViewWidget") -> None:
        """Сбросить сцену к обзору уровня facility."""
        self.stop_select_rack_mode()
        if hasattr(self, "stop_shelf_placement"):
            self.stop_shelf_placement(clear_selection=True)
        self.show_all_zones()
        self.show_all_racks()
        self._apply_facility_shell_visibility()
        self.stop_rack_placement(clear_preview=True)
        self.set_zone_pick_enabled(True)
        self.update_scene()

    def enter_zone_overview(self: "ModelViewWidget", zone_id: str, *, focus: bool = True) -> None:
        """Переключить сцену в режим контура зоны + выбор стеллажей."""
        zid = str(zone_id or "")
        if not zid:
            return
        self.clear_selected_zone_highlight()
        self.set_zone_pick_enabled(False)
        if hasattr(self, "stop_shelf_placement"):
            self.stop_shelf_placement(clear_selection=True)
        self.show_zone_contour(zid)
        self.show_only_zone_racks(zid)
        self.stop_rack_placement(clear_preview=True)
        self.start_select_rack_mode(zid)
        if focus and hasattr(self, "focus_on_zone_isometric"):
            self.focus_on_zone_isometric(zid)
        self.update_scene()

    def prepare_rack_placement(self: "ModelViewWidget") -> None:
        """Выйти из режима выбора стеллажа перед началом размещения."""
        self.stop_select_rack_mode()
        self.update_scene()

    def restore_zone_rack_selection(
        self: "ModelViewWidget",
        zone_id: str | None,
        *,
        zone_view_active: bool,
    ) -> None:
        """Остановить превью размещения и восстановить режим выбора стеллажей."""
        self.stop_rack_placement(clear_preview=True)
        zid = str(zone_id or "")
        if zone_view_active and zid:
            self.start_select_rack_mode(zid)
        else:
            self.stop_select_rack_mode()
        self.update_scene()

    def apply_zone_edit_visibility(self: "ModelViewWidget") -> None:
        """Скрыть слои сцены/стеллажи для упрощения редактирования контура зоны."""
        for key in ("floor", "walls", "ceiling", "truss"):
            self.set_model_visibility(key, False)
        self.stop_select_rack_mode()
        self.show_only_zone_racks(None)
        self.update_scene()

    def restore_zone_edit_visibility(
        self: "ModelViewWidget",
        *,
        model_visibility: dict[str, bool] | None,
        view_level: str,
        zone_id: str | None,
        rack_id: str | None,
    ) -> None:
        """Восстановить состояние сцены, сохранённое перед режимом редактирования зоны."""
        state = dict(model_visibility or {})
        for key in ("floor", "walls", "ceiling", "truss"):
            self.set_model_visibility(key, bool(state.get(key, True)))

        zid = str(zone_id or "")
        rid = str(rack_id or "")
        level = str(view_level or "facility")
        if level == "rack" and zid and rid and hasattr(self, "show_only_rack"):
            self.show_only_rack(rid, zid)
        elif level == "zone" and zid:
            self.show_only_zone_racks(zid)
        else:
            self.show_all_racks()
        self.update_scene()


# ---------------------------------------------------------------------------
# Module workflow notes
# ---------------------------------------------------------------------------
# 1) Задача модуля:
#    Переключение режимов сцены и правил видимости между facility, zone и rack.
#
# 2) Последовательность действий и вызовов:
#    A. Класс SceneModesMixin: точки входа
#       Публичные методы сценария:
#       - SceneModesMixin.set_zone_pick_mode(...)
#       - SceneModesMixin.enter_facility_overview(...)
#       - SceneModesMixin.enter_zone_overview(...)
#       - SceneModesMixin.prepare_rack_placement(...)
#       - SceneModesMixin.restore_zone_rack_selection(...)
#       - SceneModesMixin.apply_zone_edit_visibility(...)
#       - SceneModesMixin.restore_zone_edit_visibility(...)
#
#    B. SceneModesMixin: запуск и настройка:
#       SceneModesMixin.set_zone_pick_mode(...)
#         Назначение: Переключить режим выбора зоны с обновлением сцены.
#       SceneModesMixin.enter_facility_overview(...)
#         Назначение: Сбросить сцену к обзору уровня facility.
#         Последовательность внутренних вызовов:
#         -> SceneModesMixin._apply_facility_shell_visibility(...)
#       SceneModesMixin.enter_zone_overview(...)
#         Назначение: Переключить сцену в режим контура зоны + выбор стеллажей.
#       SceneModesMixin.prepare_rack_placement(...)
#         Назначение: Выйти из режима выбора стеллажа перед началом размещения.
#
#    C. SceneModesMixin: основной сценарий:
#       SceneModesMixin._apply_facility_shell_visibility(...)
#         Назначение: Профиль оболочки уровня facility: активен только пол, остальные слои отключены.
#       SceneModesMixin.apply_zone_edit_visibility(...)
#         Назначение: Скрыть слои сцены/стеллажи для упрощения редактирования контура зоны.
#
#    D. SceneModesMixin: завершение и очистка:
#       SceneModesMixin.restore_zone_rack_selection(...)
#         Назначение: Остановить превью размещения и восстановить режим выбора стеллажей.
#       SceneModesMixin.restore_zone_edit_visibility(...)
#         Назначение: Восстановить состояние сцены, сохранённое перед режимом редактирования зоны.
#
# 3) Важные ограничения и инварианты:
#    - Модуль выполняется в составе ModelViewWidget и использует согласованные поля состояния self._... .
#    - Межмодульная связность: только через фасад model_view; прямые обращения между zone, rack, shelf, cell запрещены.
#    - Очистка состояния должна быть идемпотентной: повторный вызов не меняет корректное состояние в ошибочное.
#
# 4) Правило сопровождения:
#    - Любое изменение сценария должно сопровождаться обновлением этого блока с сохранением фактического порядка вызовов.
#    - При добавлении метода указывать его место в цепочке сценария (запуск, основной шаг, завершение, вспомогательная логика).
