from __future__ import annotations

from .tkstate import state


class tkAnnotationController:
    def __init__(self, events):
        self.events = events
        self.state = state(fig=None, is_active=True, entries=[], cursor=None, sel=None)
        self.state.add_line = self.add_line
        self.state.activate = self.activate

    def prepare(self):
        self.state.entries.clear(); self.state.sel = None; self.state.cursor = None

    def add_line(self, label, axis, ref_axis, x_list, y_list, line, inf_list=None,
                 annotation_format=None, inf_format=None):
        self.state.entries.append(dict(label=label, axis=axis, ref_axis=ref_axis, x=x_list, y=y_list,
                                       line=line, inf_list=inf_list, annotation_format=annotation_format,
                                       inf_format=inf_format))

    def activate(self, flag=True): self.state.is_active = bool(flag)

    def register(self, fig, activate=True, on_mouse_move=None, on_click=None, print_level=0):
        self.state.fig = fig; self.activate(activate)
        try:
            import mplcursors
        except ImportError as exc:
            raise ImportError("Annotation support requires mplcursors: pip install mplcursors") from exc
        artists = [entry["line"] for entry in self.state.entries]
        cursor = mplcursors.cursor(artists, hover=True)
        self.state.cursor = cursor

        @cursor.connect("add")
        def _on_add(sel):
            if not self.state.is_active:
                sel.annotation.set_visible(False); return
            self.state.sel = sel
            artist = sel.artist
            entry = next((e for e in self.state.entries if e["line"] is artist), None)
            if entry is None: return
            index = int(round(sel.index)) if hasattr(sel, "index") else None
            x, y = sel.target
            fmt = entry["annotation_format"]
            if callable(fmt): text = fmt(x, y, index)
            elif isinstance(fmt, str): text = fmt.format(label=entry["label"], x=x, y=y, i=index)
            else: text = f"{entry['label']}\nx={x:g}\ny={y:g}"
            sel.annotation.set_text(text)
            if print_level: print(text)

        if on_mouse_move is not None:
            self.events.connect(fig, "motion_notify_event", on_mouse_move, key=("annotation-motion", id(fig)))
        if on_click is not None:
            self.events.connect(fig, "button_press_event", on_click, key=("annotation-click", id(fig)))
        return cursor
