# PlotRKC.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
from View.Tools.PamhyrPlot import PamhyrPlot

from PyQt5.QtCore import (
    QCoreApplication, Qt,
)
from PyQt5.QtWidgets import QApplication

from matplotlib.collections import LineCollection

_translate = QCoreApplication.translate


class PlotRKC(PamhyrPlot):
    def __init__(self, canvas=None, trad=None, toolbar=None,
                 river=None, reach=None, profile=None,
                 parent=None):
        super(PlotRKC, self).__init__(
            canvas=canvas,
            trad=trad,
            data=river,
            toolbar=toolbar,
            parent=parent
        )

        self._current_reach = reach
        self._current_profile = profile

        self.label_x = self._trad["unit_rk"]
        self.label_y = self._trad["unit_elevation"]

        self._isometric_axis = False

        self._auto_relim_update = True
        self._autoscale_update = False
        self.parent = parent
        self.anotate_lst = []

    @property
    def river(self):
        return self.data

    @river.setter
    def river(self, river):
        self.data = river

    @timer
    def draw(self, highlight=None):
        self.init_axes()

        if self.data is None:
            self.profile = None
            self.line_rk_zmin_zmax = None
            self.line_rk_zmin = None
            self.hs_vlines = None
            return

        if self._current_reach is None:
            self.profile = None
            self.line_rk_zmin_zmax = None
            self.line_rk_zmin = None
            self.hs_vlines = None
            return

        self.draw_data(highlight)

        self.idle()
        self._init = True

    def draw_data(self, highlight):
        reach = self._current_reach
        rk = reach.reach.get_rk()
        z_min = reach.reach.get_z_min()
        z_max = reach.reach.get_z_max()

        self.line_rk_zmin, = self.canvas.axes.plot(
            rk, z_min,
            color=self.color_plot_river_bottom,
            lw=1.,
        )

        self.line_rk_zmax, = self.canvas.axes.plot(
            rk, z_max,
            color=self.color_plot_river_bottom,
            lw=1.,
            alpha=0.0
        )

        if len(rk) != 0:
            self.line_rk_zmin_zmax = self.canvas.axes.vlines(
                x=rk,
                ymin=z_min, ymax=z_max,
                color=self.color_highlight(highlight),
                lw=1.,
                picker=10
            )

        self.draw_hs()
        # Draw HS

    def draw_hs(self):
        reach = self._current_reach
        rk = reach.reach.get_rk()
        z_min = reach.reach.get_z_min()
        z_max = reach.reach.get_z_max()
        lhs = filter(
            lambda hs: hs._input_reach is reach,
            filter(
                lambda hs: hs._input_reach is not None,
                self.data.hydraulic_structures.lst
            )
        )

        vx = []
        vymin = []
        vymax = []
        self.anotate_lst = []
        hs_color = []
        index = self.parent.tableView.selectedIndexes()
        for i, hs in enumerate(lhs):
            section = hs.input_section
            if section is None:
                continue

            if i == index[0].row():
                color = "blue"
            elif hs.enabled:
                color = "red"
            else:
                color = "darkgrey"

            x = section.rk
            if x is not None:
                a = self.canvas.axes.annotate(
                    " > " + hs.name,
                    (x, max(z_max)),
                    horizontalalignment='left',
                    verticalalignment='top',
                    annotation_clip=True,
                    fontsize=9,
                    color=color,
                )
                self.anotate_lst.append(a)
                vx.append(x)
                vymin.append(min(z_min))
                vymax.append(max(z_max))
                hs_color.append(color)

        self.hs_vlines = self.canvas.axes.vlines(
            x=vx, ymin=vymin, ymax=vymax,
            linestyle="--",
            lw=1.,
            color=hs_color,
        )

    def color_highlight(self, highlight):

        reach = self._current_reach
        colors = [self.color_plot_river_bottom] * reach.reach.number_profiles

        if highlight is not None:
            rk = reach.reach.get_rk()
            rows = [i for i in range(len(rk))
                    if (rk[i] >= highlight[0] and rk[i] <= highlight[1])]
            if len(rows) > 0:
                for row in rows:
                    colors[row] = "blue"
        return colors

    def set_reach(self, reach):
        self._current_reach = reach
        self._current_profile = None
        self.update()

    def set_profile(self, profile):
        self._current_profile = profile
        self.update_current_profile()

    def update(self):
        self.draw()

    def update_current_profile(self):
        reach = self._current_reach
        rk = reach.reach.get_rk()
        z_min = reach.reach.get_z_min()
        z_max = reach.reach.get_z_max()

        if self.profile is None:
            self.draw()
        else:
            self.profile.set_data(
                [self._current_profile.rk, self._current_profile.rk],
                [self._current_profile.z_min(), self._current_profile.z_max()],
            )

            self.update_idle()

    def clear(self):
        if self.profile is not None:
            self.profile[0].set_data([], [])

        if self.line_rk_zmin_zmax is not None:
            self.line_rk_zmin_zmax.remove()
            self.line_rk_zmin_zmax = None

        if self.line_rk_zmin is not None:
            self.line_rk_zmin.set_data([], [])

        if self.hs_vlines is not None:
            self.hs_vlines.remove()
            self.hs_vlines = None

        for a in self.anotate_lst:
            a.remove()
        self.anotate_lst = []

        self.canvas.figure.canvas.draw_idle()

    def clear_profile(self):
        if self.profile is not None:
            self.profile[0].set_data([], [])

        self.canvas.figure.canvas.draw_idle()

    def onpick(self, event):
        if event.mouseevent.inaxes != self.canvas.axes:
            return
        if event.mouseevent.button.value != 1:
            return

        modifiers = QApplication.keyboardModifiers()
        if modifiers not in [Qt.ControlModifier,
                             Qt.NoModifier,
                             Qt.ShiftModifier]:
            return

        closest = self._closest_profile(event)
        index = self.parent.tableView.selectedIndexes()
        if self.parent._table is not None:
            self.parent._table.setData(index[2], closest)

        return

    def _closest_profile(self, event):

        s = event.artist.get_segments()
        x = [i[0, 0] for i in s]
        mx = event.mouseevent.xdata
        points = enumerate(x)

        def dist_mouse(point):
            x = point[1]
            d = abs(mx - x)
            return d

        closest = min(
            points, key=dist_mouse
        )

        return closest[1]
