from typing import Optional

import axipy
from axipy import Plugin
from axipy.da import CollectionStyle, Feature, GeometryType, PolygonStyle, Style, Table
from axipy.gui import view_manager

from ..data_types import NamedSearchPatterns, SearchGroupPatterns
from ..widgets.region_style_widget import SelectByRegionStyleWidget
from ..widgets.style_widget_interface import SelectByStyleWidgetInterface
from .line_strategy import LineStrategy
from .strategy_base import SelectStrategy


class PolygonStrategy(SelectStrategy):
    """
    Стратегия для выделения площадных объектов
    """

    def __init__(self, f: Feature, table: Table) -> None:
        super().__init__(f, table)
        self.__geometries = [
            GeometryType.Polygon,
            GeometryType.Ellipse,
            GeometryType.Rectangle,
            GeometryType.RoundedRectangle,
            GeometryType.MultiPolygon,
            GeometryType.GeometryCollection,
        ]
        self.__pattern = axipy.tr("Стиль заливки")
        self.__color = axipy.tr("Цвет")
        self.__background = axipy.tr("Фон")
        self.__patterns = [self.__pattern, self.__color, self.__background]

    def identify(self, style: Style) -> bool:
        return isinstance(style, PolygonStyle)

    def search_patterns_brush(self) -> NamedSearchPatterns:
        return NamedSearchPatterns({p: True for p in self.__patterns}, self.brush_key())

    def search_patterns_border(self) -> NamedSearchPatterns:
        line = LineStrategy(self.feature, self.table)
        return NamedSearchPatterns(line.search_patterns(), self.border_key())

    def fill_widget(self, widget: "SelectByRegionStyleWidget"):
        widget.search_geometries = {gtype: True for gtype in self.__geometries}
        widget.set_region_patterns(self.search_patterns_border(), self.search_patterns_brush())

    @staticmethod
    def border_key() -> str:
        return "region_border_key"

    @staticmethod
    def brush_key() -> str:
        return "region_brush_key"

    def settings_widget(self, iface: Plugin) -> SelectByStyleWidgetInterface:
        ui_file = str(iface.plugin_dir / "ui" / "SelectByRegionStyle.ui")
        widget = SelectByRegionStyleWidget(ui_file, view_manager.global_parent)
        self.fill_widget(widget)
        return widget

    def string_pattern_group_key(self) -> str:
        # FIXME: Не используется. Используются два отдельных ключа для контура
        # и заливки
        return "region_key"

    def is_supported_style(
        self, target: PolygonStyle, source: PolygonStyle, group_patterns: SearchGroupPatterns
    ) -> bool:
        assert isinstance(target, PolygonStyle)
        assert isinstance(source, PolygonStyle)
        patterns = group_patterns[self.brush_key()]
        source_fill = source.fill
        target_fill = target.fill
        if patterns[self.__pattern] and source_fill.pattern != target_fill.pattern:
            return False
        if patterns[self.__color] and source_fill.color != target_fill.color:
            return False
        if patterns[self.__background] and source_fill.bg_color != target_fill.bg_color:
            return False
        border = LineStrategy(self.feature, self.table)
        border_patterns = group_patterns[self.border_key()]
        line_grp_patterns = {border.string_pattern_group_key(): border_patterns}
        if not border.is_supported_style(target.border, source.border, line_grp_patterns):
            return False
        return True

    def extract_style_from_collection(self, collection_style: CollectionStyle) -> Optional[Style]:
        polygon_style = collection_style.polygon  # type: PolygonStyle
        if polygon_style:
            return polygon_style.clone()
        return polygon_style
