# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/views.line_graph.ipynb (unless otherwise specified).

__all__ = ['LineGraph']

# Cell
#from linegraph import LineGraph
# Ref: https://stackoverflow.com/questions/34855074/interactive-line-in-matplotlib

import numpy as np
from itertools import cycle
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib import rcParams

class LineGraph:
    """Plot line(s) with movable end markers"""

    def __init__(self, model, width=2.9, height=1.75, tolerance=0.05, **kwargs):
        super().__init__(**kwargs)
        plt.ioff()  # Required to display plots separately  TODO Confirm
        rcParams.update({'font.size': 5})
        self.model = model
        self.fig = plt.figure(figsize=[width, height])
        self.tolerance = tolerance  # Distance for click detect ("epsilon")
        self.axes = self.fig.add_subplot()
        self.lines = []
        self.ind = None  # Index of selected marker (end point): None, 0, or 1
        self.cur_line = None # Selected line: index into self.lines or None

        # interactive canvas has a lot of features we want to hide
        self.fig.tight_layout(pad=0, w_pad=0, h_pad=0)
        self.fig.subplots_adjust(right=0.80)
        self.fig.canvas.toolbar_visible = False
        self.fig.canvas.header_visible = False # Hide name at top of figure
        self.fig.canvas.footer_visible = False
        self.fig.canvas.resizable = False
        self.fig.canvas.capture_scroll = False
        self.fig.legend('right', borderaxespad=0.)

        # create plot components, store lines

        lineCycler = cycle(["-","--","-.",":"])
        markerCycler = cycle(['d','s','o'])

        for i in range(len(self.model.names)):
            line = Line2D(self.model.xs[i],self.model.ys[i], label=self.model.names[i],
                          marker=next(markerCycler), c='black', markerfacecolor='black',
                          linestyle=next(lineCycler))
            self.axes.add_line(line)
            self.lines.append(line)

        self.axes.autoscale()
        self.axes.legend(loc='right', bbox_to_anchor=(1.27, 0.5), borderaxespad=0.)

        # register our methods as event callbacks
        self.fig.canvas.mpl_connect('button_press_event', self._onButtonPress)
        self.fig.canvas.mpl_connect('button_release_event', self._onButtonRelease)
        self.fig.canvas.mpl_connect('motion_notify_event', self._onMotionNotify)

    def displayTo(self, out):
        plt.ion()  # Required to display plots separately  TODO Confirm

        with out:
            self.fig.show()

    def _onButtonPress(self, event):
        if event.button == 1:
            self.ind = None

            for i in range(len(self.model.names)):
                x = np.array(self.lines[i].get_xdata())
                y = np.array(self.lines[i].get_ydata())
                d = np.sqrt((x-event.xdata)**2 + (y - event.ydata)**2)

                if min(d) > self.tolerance:
                    continue
                else:
                    self.cur_line = i

                if d[0] < d[1]:
                    self.ind = 0
                else:
                    self.ind = 1

                break

    def _onButtonRelease(self, event):
        if event.button == 1:
            self.ind = None
            self.background = None

            if self.cur_line is not None:
                self.lines[self.cur_line].figure.canvas.draw()

            self.cur_line = None

    def _onMotionNotify(self, event):
        if event.button == 1 and self.ind is not None and self.cur_line is not None:
            if event.inaxes == self.lines[self.cur_line].axes:
                self.model.xs[self.cur_line][self.ind] = event.xdata
                self.model.ys[self.cur_line][self.ind] = event.ydata
                self.lines[self.cur_line].set_data(self.model.xs[self.cur_line],
                                                   self.model.ys[self.cur_line])


# Cell
import numpy as np
from itertools import cycle
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from matplotlib import rcParams
from matplotlib import widgets as mpl