//!# Systemdzbus
//!
//!Interact with systemd through DBus with a convenient rust interface.
//!All of the manager proxy types were automatically generated by the CLI tool 'zbus-xmlgen'.
//!From here I just copied the documentation from the systemd man page to
//!get good descriptions for each function.
//!
//!The plan is to gradually start wrapping each of the types into more descriptive types informed
//!by the man pages, mainly found in "man org.freedesktop.systemd1".
//!
//!## Usage
//!
//!```rust
//!     use std::error::Error;
//!     use systemdzbus::SystemCtlBuilder;
//!
//!     async fn example_get_units() -> Result<(), Box::<dyn Error>> {
//!       let systemctl = SystemCtlBuilder::new()
//!         // You may also want to have access to the system bus instead of only the user bus
//!         .with_system_connection_level()
//!         .init()
//!         .await?;
//!
//!       let units = systemctl.list_units().await?;
//!
//!       assert!(!units.is_empty());
//!
//!       Ok(())
//!     }
//!```
//!
//!You may also access the manager proxy directly if managing the connection yourself suits your
//!needs better.
//!To find out more about how to use the Connection, see the [zbus library](https://docs.rs/zbus/latest/zbus/).
//!
//!```rust
//!    use std::error::Error;
//!    use systemdzbus::{ManagerProxy, Connection, SystemCtlBuilder};
//!
//!    async fn example_get_units_manager_proxy() -> Result<(), Box::<dyn Error>> {
//!       /// Create zbus connection. You can also use Connection::session() here.
//!       let connection = Connection::system().await?;
//!
//!       /// Create proxy per zbus
//!       let proxy = ManagerProxy::new(&connection).await?;
//!
//!       /// Use the methods on the proxy. These are the ones
//!       /// that are actually documented here
//!       let units_raw = proxy.list_units().await?;
//!
//!       assert!(!units_raw.is_empty());
//!
//!       /// Or you can still have your connection managed, but still have direct access to
//!       /// manager.
//!       let systemctl = SystemCtlBuilder::new().init().await?;
//!
//!       let manager = systemctl.get_manager_proxy();
//!
//!       let units_raw = manager.list_units().await?;
//!
//!       assert!(!units_raw.is_empty());
//!
//!       Ok(())
//!   }
//!```
//!
//! # D-Bus interface proxy for: `org.freedesktop.systemd1.Manager`
//!
//! In terms of the ManagerProxy:
//! This code was generated by `zbus-xmlgen` `5.1.0` from D-Bus introspection data.
//! Source: `Interface '/org/freedesktop/systemd1' from service 'org.freedesktop.systemd1' on system bus`.
//!
//! More information can be found in the [Writing a client proxy] section of the zbus
//! documentation.
//!
//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the
//! following zbus API can be used:
//!
//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,

pub mod errors;
pub mod manager;
pub mod systemctl;
pub use manager::ManagerProxy;
pub use systemctl::systemctl_async::SystemCtlBuilder;
pub use systemctl::systemctl_blocking::SystemCtlBlockingBuilder;
pub use systemctl::unit::UnitMode;

pub use zbus::Connection;

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[test]
    fn it_can_use_builder_pattern_to_get_system_connection_level() {
        let systemctl = SystemCtlBlockingBuilder::new()
            .with_system_connection_level()
            .init()
            .expect("Should be able to initialise connection");

        let units = systemctl.list_units();

        assert!(units.is_ok());

        let units = units.expect("Units are OK at this point.");

        assert!(!units.is_empty());
    }

    #[test]
    fn can_list_units_with_higher_level_interface_blocking() {
        let systemctl = SystemCtlBlockingBuilder::new()
            .init()
            .expect("Should be able to initialise connection");

        let units = systemctl.list_units();

        assert!(units.is_ok());

        let units = units.expect("Units are OK at this point.");

        assert!(!units.is_empty());
    }

    #[test]
    fn can_list_units() {
        let res: Result<(), Box<dyn Error>> = smol::block_on(async {
            let connection = Connection::system().await?;
            let proxy = ManagerProxy::new(&connection).await?;
            let res = proxy.list_units().await?;

            assert!(!res.is_empty());
            Ok(())
        });

        assert!(res.is_ok());
    }
}
