//! Information about the user's repository.

use std::sync::LazyLock;


/// Cargo metadata as collected by the `cargo_metadata` crate.
pub static CARGO_METADATA: LazyLock<cargo_metadata::Metadata> = LazyLock::new(|| {
    cargo_metadata::MetadataCommand::new()
        .manifest_path(&*path::WORKSPACE_CARGO_TOML)
        .exec()
        .expect("Failed to gather Cargo metadata.")
});

pub use cargo_metadata;


/// Paths in the user's repository.
pub mod path {
    use std::{path::{Path, PathBuf}, sync::LazyLock};


    /// Root of your Cargo workspace. This is the directory where
    /// your `Cargo.lock` file and `target/` folder is placed.
    ///
    /// This is equivalent to `repo_path!()` in most projects.
    /// The two differ, if your Rust code lives in a subfolder of a larger repository.
    pub fn workspace_dir() -> &'static Path {
        super::CARGO_METADATA.workspace_root.as_std_path()
    }

    /// The `target/` directory of your workspace.
    ///
    /// Compile artifacts can be found in here.
    pub fn target_dir() -> &'static Path {
        super::CARGO_METADATA.target_directory.as_std_path()
    }

    /// Path of the Cargo.toml file at the root of the workspace.
    pub static WORKSPACE_CARGO_TOML: LazyLock<PathBuf> = LazyLock::new(|| {
        let output = std::process::Command::new(env!("CARGO"))
            .arg("locate-project")
            .arg("--workspace")
            .arg("--message-format=plain")
            .output()
            .expect("Failed to run `cargo locate-project` subcommand while determining the workspace Cargo.toml.")
            .stdout;

        let output = std::str::from_utf8(&output)
            .expect("Failed to convert output from `cargo locate-project` subcommand to UTF-8 string.")
            .trim();

        PathBuf::from(output)
    });



    /// Paths used by Cicero.
    pub mod cicero {
        use std::path::PathBuf;

        /// The directory where Cicero places its artifacts.
        /// This is a sub-path of the `target/` folder.
        pub fn target_cicero_dir() -> PathBuf {
            super::target_dir().join("cicero")
        }

        /// Directory used for internal logic of Cicero.
        pub fn internal_dir() -> PathBuf {
            target_cicero_dir().join(".internal")
        }
    }
}
