# PlotXY.py -- Pamhyr
# Copyright (C) 2023-2026  INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# -*- coding: utf-8 -*-

from tools import timer, trace
from View.Tools.PamhyrPlot import PamhyrPlot
from matplotlib import collections
import numpy as np

from PyQt5.QtCore import (
    QCoreApplication, Qt, QItemSelectionModel,
    QItemSelection, QItemSelectionRange,
)
from PyQt5.QtWidgets import QApplication, QTableView

_translate = QCoreApplication.translate


class PlotXY(PamhyrPlot):
    def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
                 table=None, parent=None):
        super(PlotXY, self).__init__(
            canvas=canvas,
            trad=trad,
            data=data,
            toolbar=toolbar,
            table=table,
            parent=parent
        )

        self.line_xy = []
        self.line_gl = []

        self.label_x = self._trad["x"]
        self.label_y = self._trad["y"]

        self.before_plot_selected = None
        self.plot_selected = None
        self.after_plot_selected = None
        self.parent = parent
        self.line_xy_collection = None
        self._table = table
        self._colors = []
        self._style = []

    def onpick(self, event):
        if event.mouseevent.inaxes != self.canvas.axes:
            return
        if event.mouseevent.button not in [1, 3]:
            return

        closest = self._closest_section(event)
        t = self.parent.current_tab()
        tableView = self.parent.find(QTableView, f"tableView_{t}")
        table = self.parent._table[t]
        index = tableView.selectedIndexes()
        rk = self.data.get_rk()
        if self.parent._table is not None:
            if event.mouseevent.button == 1:
                table.setData(index[3], rk[closest[0]])
            if event.mouseevent.button == 3:
                table.setData(index[4], rk[closest[0]])

        return

    def _closest_section(self, event):
        axes = self.canvas.axes
        mx = event.mouseevent.xdata
        my = event.mouseevent.ydata
        bx, by = axes.get_xlim(), axes.get_ylim()
        ratio = (bx[0] - bx[1]) / (by[0] - by[1])

        segments = event.artist.get_segments()
        ind = event.ind

        points = []
        for i in ind:
            points = points + [[i, j] for j in segments[i]]

        def dist_mouse(point):
            x, y = point[1]
            d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2)
            return d2

        closest = min(
            points, key=dist_mouse
        )

        return closest

    @timer
    def draw(self):
        self.init_axes()

        if self.data is None:
            self.idle()
            return

        if self.data.number_profiles == 0:
            self._init = False
            self.idle()
            return

        self.draw_xy()
        self.draw_lr()
        self.draw_gl()

        self.idle()
        self._init = True

    def draw_xy(self):
        self.line_xy = []
        for xy in zip(self.data.get_x(), self.data.get_y()):
            self.line_xy.append(np.column_stack(xy))

        self._colors, self._style = self.color_hightlight()
        self.line_xy_collection = collections.LineCollection(
                self.line_xy,
                colors=self._colors,
                linestyle=self._style,
                picker=10
            )
        self.canvas.axes.add_collection(self.line_xy_collection)

    def color_hightlight(self):
        rk_min, rk_max = (-1, -1)
        if self._highlight_data is not None:
            rk_min, rk_max = self._highlight_data

        colors = [self.color_plot_river_bottom
                  for row in range(len(self._data))]
        for i, rk in enumerate(self.data.get_rk_complete_profiles()):
            if rk_min <= rk <= rk_max:
                colors[i] = self.color_plot_current
        style = ["-" for row in range(len(self._data))]

        return colors, style

    def draw_lr(self):
        lx = []
        ly = []
        rx = []
        ry = []

        self.line_lr = []
        for x, y in zip(self.data.get_x(),
                        self.data.get_y()):
            lx.append(x[0])
            ly.append(y[0])

            rx.append(x[-1])
            ry.append(y[-1])

        line = self.canvas.axes.plot(
            lx, ly,
            color=self.color_plot_river_bottom,
            linestyle="dotted",
            lw=1.,
        )
        self.line_lr.append(line)

        line = self.canvas.axes.plot(
            rx, ry,
            color=self.color_plot_river_bottom,
            linestyle="dotted",
            lw=1.,
        )
        self.line_lr.append(line)

    def draw_gl(self):
        x_complete = self.data.get_guidelines_x()
        y_complete = self.data.get_guidelines_y()

        ind = 0
        self.line_gl = []
        for x, y in zip(x_complete, y_complete):
            line = self.canvas.axes.plot(
                x, y, color=self.colors[ind % len(self.colors)],
                linestyle=self.linestyle[ind // len(self.colors)]
            )
            self.line_gl.append(line)
            ind += 1

    @timer
    def update(self):
        if not self._init:
            self.draw()
            return

        if self.data is None:
            return

        self.update_lr()
        self.update_gl()
        self.update_current()

        self.update_idle()

    def update_gl(self):
        self.data.compute_guidelines()
        x_complete = list(self.data.get_guidelines_x())
        y_complete = list(self.data.get_guidelines_y())

#        TODO comprendre à quoi sert ce bout de code
#        ========>
#        for i in range(self.data.number_profiles):
#            if i < len(self.line_xy):
#                self.line_xy[i][0].set_data(
#                    self.data.profile(i).x(),
#                    self.data.profile(i).y()
#                )
#            else:
#                self.line_xy.append(
#                    self.canvas.axes.plot(
#                        self.data.profile(i).x(),
#                        self.data.profile(i).y(),
#                        color='r',
#                        **self.plot_default_kargs
#                    )
#                )
#        <========

        for i in range(len(x_complete)):
            if i < len(self.line_gl):
                self.line_gl[i][0].set_data(
                    x_complete[i],
                    y_complete[i]
                )
            else:
                self.line_gl.append(
                    self.canvas.axes.plot(
                        x_complete[i],
                        y_complete[i]
                    )
                )

    def update_current(self):
        if self._current_data_update:
            self._colors, self._style = self.color_hightlight()
            self.line_xy_collection.set_colors(self._colors)
            self.line_xy_collection.set_linestyle(self._style)

    def update_lr(self):
        for line in self.line_lr:
            line[0].remove()

        self.draw_lr()
