use std::{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() -> PathBuf {
    metadata::CARGO
        .workspace_root
        .clone()
        .into_std_path_buf()
}

/// The `target/` directory of your workspace.
///
/// Compile artifacts can be found in here.
pub fn target_dir() -> PathBuf {
    metadata::CARGO
        .target_directory
        .clone()
        .into_std_path_buf()
}

pub static USER_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()
        .unwrap()
        .stdout;

    let output = std::str::from_utf8(&output).unwrap()
        .trim();

    PathBuf::from(output)
});


pub mod metadata {
    use std::sync::LazyLock;

    pub static CARGO: LazyLock<cargo_metadata::Metadata> = LazyLock::new(|| {
        cargo_metadata::MetadataCommand::new()
            .manifest_path(super::USER_WORKSPACE_CARGO_TOML.as_path())
            .exec()
            .expect("Failed to gather Cargo metadata.")
    });
}


/// 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() -> PathBuf {
        super::target_dir().join("cicero")
    }

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