//! systemd service module.
//!
//! Implements systemd-specific service subsystem interactions.

use sd_notify::NotifyState;

/// A service reporter that sends notifications to systemd.
pub struct ServiceReporter {}

impl super::StateReporter for ServiceReporter {
  fn starting(&self, _checkpoint: u32, status: &str) {
    // Sent startup status to systemd (via sd-notify)
    if let Err(e) = sd_notify::notify(false, &[NotifyState::Status(status)]) {
      log::error!("Unable to report service started state; {e}");
    }
  }

  fn started(&self) {
    // Inform systemd that the initialization phase has finshed
    if let Err(e) = sd_notify::notify(false, &[NotifyState::Ready]) {
      log::error!("Unable to report service started state; {e}");
    }

    // inform user (via systemd) that the service is entering the main service
    // application state.
    let status = "Running service application";
    if let Err(e) = sd_notify::notify(false, &[NotifyState::Status(status)]) {
      log::error!("Unable to report service status; {e}");
    }
  }

  fn stopping(&self, checkpoint: u32, status: &str) {
    // For systemd, there aren't mutltiple stop checkpoints -- there's just a
    // single "stopping has initiated" event.  Use the special checkpoint 0 to
    // signal that service is stopping.
    if checkpoint == 0
      && let Err(e) = sd_notify::notify(false, &[NotifyState::Stopping])
    {
      log::error!("Unable to report service stopped state; {e}");
    }

    // ToDo: Is it okay to set status after "Stopping" has been set?
    if let Err(e) = sd_notify::notify(false, &[NotifyState::Status(status)]) {
      log::error!("Unable to report service stopping state; {e}");
    }
  }

  fn stopped(&self) {
    // ToDo: Is it okay to set status after "Stopping" has been set?
    let status = "Service application termination completed";
    if let Err(e) = sd_notify::notify(false, &[NotifyState::Status(status)]) {
      log::error!("Unable to report service stopping state; {e}");
    }
  }
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :
