from functools import wraps
from typing import NamedTuple, Dict, Callable, Any

from axipy import (provider_manager,
                   Notifications, Table, MapView, SelectionTable, Attribute)


class Pnt(NamedTuple):
    x: float
    y: float


DictPnt = Dict[int, Pnt]


class MatchingPoints(NamedTuple):
    src_pnt: Pnt
    dst_pnt: Pnt


def try_except(notify_msg: str) -> Callable:
    def decorate(func: Callable) -> Callable:

        @wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            try:
                return func(*args, **kwargs)
            except Exception as e:
                print(e)
                if notify_msg:
                    self = args[0]
                    if hasattr(self, "title"):
                        title = self.title
                    else:
                        title = ''
                    if hasattr(self, "plugin"):
                        plugin = self.plugin
                    else:
                        plugin = None

                    if plugin:
                        arg = self.plugin.tr(notify_msg)
                    else:
                        arg = notify_msg

                    Notifications.push(title, arg + f" ({e})", Notifications.Critical)

        return wrapper

    return decorate


def try_except_silent() -> Callable:
    def decorate(func: Callable) -> Callable:

        @wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            try:
                return func(*args, **kwargs)
            except (Exception,):
                # logging.debug(traceback.format_exc())
                pass

        return wrapper

    return decorate


TEMPORARY_MAP_VIEW = "820f73c489e2484b8dd34c821f691561"


def filter_one_input_table(table: Table) -> bool:
    return bool(
        table.provider == provider_manager.tab.id and
        table.is_spatial and
        not isinstance(table, SelectionTable)
    )


def filter_one_map_view(map_view: MapView) -> bool:
    return bool(map_view.title != TEMPORARY_MAP_VIEW)


class Attrs(NamedTuple):
    row: Attribute = Attribute.integer("row")
    x_col: Attribute = Attribute.integer("x_col")
    y_col: Attribute = Attribute.integer("y_col")


ATTRS = Attrs()
