# encoding=utf-8
__author__ = "Aaron Randreth"
__copyright__ = "Copyright 2015+, Consortium MonPaGe"
__license__ = "Creative Commons 4.0 By-Nc-Sa"
__maintainer__ = "Roland Trouville"
__email__ = "contact.monpage@gmail.com"
__status__ = "Production"

from typing import Union

import pyqtgraph as pg  # type: ignore

# pg.setConfigOptions(foreground="k", background="d")
from PySide6.QtGui import QAction
from PySide6.QtWidgets import QToolBar


class ZoomToolbar(QToolBar):
	"""
	A toolbar providing zoom controls for PyQtGraph ViewBoxes.

	The toolbar allows:
	    - Zooming in and out along the x-axis
	    - Zooming to a selected region
	    - Resetting zoom to auto-range

	Attributes:
	    selection (pg.LinearRegionItem): The region used for zoom-to-selection.
	    scale (float): The zoom scale factor (e.g., 0.9 for zoom-in, 1.1 for zoom-out).
	    viewboxes (list[pg.ViewBox]): List of linked ViewBoxes to apply zoom operations to.
	"""

	def __init__(self, selection: pg.LinearRegionItem, scale: float = 0.9):
		super().__init__("Zoom Toolbar")

		# < 1 for in and > 1 for out
		self.scale = scale
		self.selection = selection
		self.viewboxes: list[pg.ViewBox] = []

		# Add Zoom In button
		self.zoom_in_action = QAction("Zoom In", self)
		self.zoom_in_action.setStatusTip("Zoom in")
		self.addAction(self.zoom_in_action)

		# Add Zoom Out button
		self.zoom_out_action = QAction("Zoom Out", self)
		self.zoom_out_action.setStatusTip("Zoom out")
		self.addAction(self.zoom_out_action)

		# Zoom in by 10% (0.9) and out by 10% (1.1) by default
		self.zoom_in_action.triggered.connect(
			lambda: self.handle_plot_zoom_buttons(self.scale)
		)
		self.zoom_out_action.triggered.connect(
			lambda: self.handle_plot_zoom_buttons(1 / self.scale)
		)

		# Add Zoom to Selection button
		self.zoom_selection_action = QAction("Zoom to Selection", self)
		self.zoom_selection_action.setStatusTip("Zoom to selection")
		self.zoom_selection_action.triggered.connect(self.zoom_to_selection)
		self.addAction(self.zoom_selection_action)

		# Add Reset Zoom button
		self.reset_zoom_action = QAction("Reset Zoom", self)
		self.reset_zoom_action.setStatusTip("Reset zoom to original")
		self.reset_zoom_action.triggered.connect(self.reset_zoom)
		self.addAction(self.reset_zoom_action)

	def link_viewbox(
		self, viewbox_or_plot: Union[pg.ViewBox, pg.PlotWidget, pg.PlotItem]
	):
		"""
		Link a ViewBox, PlotWidget, or PlotItem to the zoom toolbar.
		:param viewbox_or_plot: view to link
		:returns None
		"""
		if isinstance(viewbox_or_plot, pg.PlotWidget):
			viewbox = viewbox_or_plot.getViewBox()
		elif isinstance(viewbox_or_plot, pg.PlotItem):
			viewbox = viewbox_or_plot.getViewBox()
		elif isinstance(viewbox_or_plot, pg.ViewBox):
			viewbox = viewbox_or_plot
		else:
			raise TypeError("Argument must be a ViewBox, PlotWidget, or PlotItem")

		self.viewboxes.append(viewbox)

	def handle_plot_zoom_buttons(self, factor: float):
		"""
		Zoom on the abscissa (x-axis) on all linked viewboxes.
		:param factor: factor of zoom
		:returns None
		"""
		for vb in self.viewboxes:
			vb.scaleBy((factor, 1))  # Zoom only on the x-axis

	def zoom_to_selection(self):
		"""
		Zoom to the selected region defined by the LinearRegionItem.
		:returns None
		"""
		region = self.selection.getRegion()
		for vb in self.viewboxes:
			vb.setXRange(region[0], region[1], padding=0)

	def reset_zoom(self):
		"""
		Reset the zoom to the original view.
		:returns None
		"""
		for vb in self.viewboxes:
			vb.autoRange()
