"""."""

import matplotlib.pyplot as plt
import numpy as np

from matplotlib.backend_bases import Event, KeyEvent, MouseEvent, PickEvent

from association_studio.mpl_vis.horizontal_bar import get_fig_axes
from association_studio.mpl_vis.prepare_axes import prepare_axes

from .back import AssociationStudioBackend


class PltHolder:
    ion = plt.ion
    show = plt.show


class AssociationFrontend:
    def __init__(self, back: AssociationStudioBackend) -> None:
        self.back = back
        PltHolder.ion()  # replot on any sneeze
        self.fig_boxes, self.ax_boxes = plt.subplots()
        self.fig_boxes.canvas.manager.set_window_title('Association Studio: boxes')
        self.ax_boxes.set_title(self.back.get_title())
        prepare_axes(self.ax_boxes, np.array([(-15.0, -15.0), (5.0, 5.0)]))
        self.ax_boxes.add_artist(self.back.ref_poly)
        self.ax_boxes.add_artist(self.back.ref_circle)
        self.ax_boxes.add_artist(self.back.probe_poly)
        self.ax_boxes.add_artist(self.back.probe_circle)
        bbox_dct = dict(boxstyle='round,pad=0.5', fc='wheat', ec='orange')
        self.text = self.ax_boxes.text(-14.0, -14.0, back.get_text(), size=10, bbox=bbox_dct)
        self.fig_boxes.canvas.mpl_connect('key_press_event', self.on_key)
        self.fig_boxes.canvas.mpl_connect('button_release_event', self.on_release)
        self.fig_boxes.canvas.mpl_connect('motion_notify_event', self.on_move)
        self.fig_boxes.canvas.mpl_connect('pick_event', self.on_pick)
        self.pick_events: list[PickEvent] = []
        self.fig_metrics, self.ax_metrics = get_fig_axes()
        self.bar = back.get_horizontal_bar_container(self.ax_metrics)

    def on_key(self, event: Event | KeyEvent) -> None:
        match event.key:
            case 'c':
                self.back.next_show_coo_mode()
            case 'm':
                self.back.next_metric()
            case 'O':
                self.back.move_probe_to_origin()
            case 'R':
                self.back.rotate_probe_30()
            case '1':
                self.back.set_unit_size_ref()
            case '2':
                self.back.set_size_probe(2.0, 4.0)

        self.back.update_horizontal_bar_container(self.bar)
        self.ax_boxes.set_title(self.back.get_title())
        self.text.set_text(self.back.get_text())

    def on_pick(self, event: Event | PickEvent) -> None:
        self.pick_events.append(event)
        self.back.start_pose_change()

    def on_release(self, _event: Event | MouseEvent) -> None:
        self.pick_events.clear()

    def on_move(self, event: Event | MouseEvent) -> None:
        if self.pick_events and event.xdata is not None:
            self.back.change_trk_pose(self.pick_events[-1], event)
            self.text.set_text(self.back.get_text())
            self.ax_boxes.set_title(self.back.get_title())
            self.back.update_horizontal_bar_container(self.bar)

    @staticmethod
    def show() -> None:
        PltHolder.show(block=True)
