from typing import List, Optional

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

from ..data_types import NamedSearchPatterns, SearchGroupPatterns
from ..widgets.collection_style_widget import SelectByCollectionStyleWidget
from ..widgets.style_widget_interface import SelectByStyleWidgetInterface
from .line_strategy import LineStrategy
from .mapinfo_point_strategy import MapinfoPointStrategy
from .polygon_strategy import PolygonStrategy
from .raster_point_strategy import RasterPointStrategy
from .strategy_base import SelectStrategy
from .vector_point_strategy import VectorPointStrategy


class CollectionStrategy(SelectStrategy):
    """
    Стратегия выделения коллекций. При выборе пользователем коллекции поиск
    осущствляется только среди других коллекций
    """

    def __init__(self, f: Feature, table: Table) -> None:
        super().__init__(f, table)

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

    def fill_widget(self, widget: "SelectByCollectionStyleWidget"):
        collection_style = self.feature.style
        if not isinstance(collection_style, CollectionStyle):
            return None

        if collection_style.point is not None:
            point = self.__point_strategy()
            widget.set_point_patterns(
                NamedSearchPatterns(getattr(point, "search_patterns")(), point.string_pattern_group_key())
            )

        if collection_style.line is not None:
            line = LineStrategy(self.feature, self.table)
            widget.set_line_patterns(NamedSearchPatterns(line.search_patterns(), line.string_pattern_group_key()))

        if collection_style.polygon is not None:
            region = PolygonStrategy(self.feature, self.table)
            widget.set_region_patterns(region.search_patterns_border(), region.search_patterns_brush())
        widget.search_geometries = []

    def __point_strategy(self) -> Optional[SelectStrategy]:
        collection_style = self.style
        if not isinstance(collection_style, CollectionStyle):
            return None

        point_strategies = [
            MapinfoPointStrategy(self.feature, self.table),
            VectorPointStrategy(self.feature, self.table),
            RasterPointStrategy(self.feature, self.table),
        ]  # type: List[SelectStrategy]
        for pstrategy in point_strategies:
            if pstrategy.identify(collection_style.point):
                return pstrategy
        # до этого момента доходить не должно так как все стили точек известны
        raise NotImplementedError()

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

    def string_pattern_group_key(self) -> str:
        return "collection_key"

    def extract_style_from_collection(self, collection_style: CollectionStyle) -> Optional[Style]:
        return collection_style.clone()

    def is_supported_style(
        self, target: CollectionStyle, source: CollectionStyle, group_patterns: SearchGroupPatterns
    ) -> bool:
        if source.line:
            if not target.line:
                return False
            line_stategy = LineStrategy(self.feature, self.table)
            ok = line_stategy.is_supported_style(target.line, source.line, group_patterns)
            if not ok:
                return False
        if source.polygon:
            poly_stategy = PolygonStrategy(self.feature, self.table)
            if not target.polygon:
                return False
            ok = poly_stategy.is_supported_style(target.polygon, source.polygon, group_patterns)
            if not ok:
                return False
        if source.point:
            point_strategy = self.__point_strategy()

            # if type(target.point) != type(source.point):
            #     return False
            if not isinstance(target.point, type(source.point)):
                return False

            ok = point_strategy.is_supported_style(target.point, source.point, group_patterns)
            if not ok:
                return False
        return True
