from gi.repository import GObject, Gtk


@Gtk.Template(resource_path="/org/gnome/gitlab/cheywood/Iotas/ui/revealer_notification.ui")
class RevealerNotification(Gtk.Revealer):
    __gtype_name__ = "RevealerNotification"

    _spinner = Gtk.Template.Child()
    _label = Gtk.Template.Child()

    def __init__(self):
        super().__init__()

        self.__callback = None
        self.__default_duration = self.get_transition_duration()

        self.connect("notify::child-revealed", self.__callback_wrapper)

    def show(
        self,
        text: str,
        show_spinner: bool = True,
        immediate: bool = False,
        callback=None,
    ) -> None:
        """Show the notification

        :param str text: The text to display
        :param bool show_spinner: Whether to show a spinner
        :param bool immediate: Whether to show immediately or with normal transition
        :param callback: Function to call when the notification is fully revealed. If the
            notification reveal is disrupted during normal operation the callback will still be
            called, however this excludes eg. the app shutting down.
        """
        self._label.set_text(text)
        self.set_transition_duration(0 if immediate else self.__default_duration)
        self.__ensure_prev_callback_called()
        if callback:
            self.__callback = callback
        self._spinner.set_visible(show_spinner)
        if show_spinner:
            self._spinner.start()
        self.set_reveal_child(True)

    def hide(self, immediate: bool = False) -> None:
        """Hide the notification.

        :param bool immediate: Whether to hide immediately or with normal transition
        """
        self.set_transition_duration(0 if immediate else self.__default_duration)
        self.set_reveal_child(False)
        self.__ensure_prev_callback_called()

    def __callback_wrapper(self, _obj: GObject.Object, _value: GObject.ParamSpec) -> None:
        if self.get_child_revealed():
            if self.__callback is not None:
                self.__callback()
                self.__callback = None
        else:
            if self._spinner.props.spinning:
                self._spinner.stop()

    def __ensure_prev_callback_called(self) -> None:
        if self.__callback is not None:
            self.__callback()
        self.__callback = None
