"""The Configuration widget for pyuson."""

from functools import partial

from PyQt6.QtCore import pyqtSignal, pyqtSlot
from pyqtgraph.parametertree import Parameter

from pymagnetos.core.gui.widgets import BaseConfigurationWidget

from ._param_content import ParamContent


class ConfigurationWidget(BaseConfigurationWidget):
    """
    Initialize a PyQtGraph ParameterTree.

    Signals
    -------
    sig_find_f0 : emits when the "Find f0" button is clicked.
    sig_demodulate : emits when the "Demodulate" button is clicked.
    """

    sig_find_f0 = pyqtSignal()
    sig_demodulate = pyqtSignal()

    def __init__(self, param_content: type[ParamContent]) -> None:
        super().__init__(param_content)
        self.add_extra_parameter()

    def init_demodulation_tree(self) -> None:
        """Create ParameterTree for demodulation parameters."""
        if not hasattr(self._param_content, "children_demodulation"):
            raise ValueError(
                "Could not add the demodulation parameter tree, not in digital mode"
            )
        self.demodulation_parameters = Parameter.create(
            name="Demodulation",
            type="group",
            children=self._param_content.children_demodulation,
        )
        self.host_parameters.addChild(self.demodulation_parameters)

        # Store buttons as the others
        self.button_findf0 = self.demodulation_parameters.child("find_f0")
        self.button_findf0.setOpts(enabled=False)
        self.button_demodulate = self.demodulation_parameters.child("demodulate")
        self.button_demodulate.setOpts(enabled=False)

        self.connect_to_signals_demodulation()

    def add_extra_parameter(self) -> None:
        """Add extra parameters to the tree, only for the GUI."""
        # Show the RF frequency read in the metadata file
        rf_freq = Parameter.create(
            name="rf_frequency",
            type="float",
            readonly=True,
            value=-1,
            suffix="Hz",
            siPrefix=True,
            title="RF frequency in metadata",
        )
        self.host_parameters.addChild(rf_freq)

    def connect_to_signals_demodulation(self) -> None:
        """Additionnal connections for demodulation."""
        self.button_findf0.sigActivated.connect(self.sig_find_f0.emit)
        self.button_demodulate.sigActivated.connect(self.sig_demodulate.emit)

        for p in self.demodulation_parameters:
            self.demodulation_parameters.child(p.name()).sigValueChanged.connect(
                partial(self.send_signal_on_change, "demodulation", p.name())
            )

    @pyqtSlot(str, str)
    def send_signal_on_change(
        self,
        context: str,
        param_name: str,
    ) -> None:
        """
        Send a signal when a parameter in the tree is changed.

        The context (section of the tree - "parameters", "settings", ...), parameter
        name, and value is emitted.
        """
        if context == "demodulation":
            current_value = self.demodulation_parameters[param_name]

            # Parse it if needed
            if param_name in self.parameters_to_parse:
                # special case that needs to be parsed
                current_value = self.get_numbers_from_text(current_value)

            # Send the signal
            self.sig_parameter_changed.emit(context, param_name, current_value)
        else:
            # Use parent handler
            super().send_signal_on_change(context, param_name)

    def enable_buttons(self) -> None:
        super().enable_buttons()
        if hasattr(self, "button_findf0"):
            self.button_findf0.setOpts(enabled=True)
        if hasattr(self, "button_demodulate"):
            self.button_demodulate.setOpts(enabled=True)

    def disable_buttons(self) -> None:
        super().disable_buttons()
        if hasattr(self, "button_findf0"):
            self.button_findf0.setOpts(enabled=False)
        if hasattr(self, "button_demodulate"):
            self.button_demodulate.setOpts(enabled=False)
