#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::must_use_candidate, clippy::missing_errors_doc)]
mod creator;
mod db;
mod installer;
mod item;
mod package;
mod plist;
mod repository;
pub mod tar;
mod version;

use std::path::PathBuf;

pub use {
    creator::{CreationError, Creator, Message},
    db::Database,
    installer::{Error as InstallError, Hooks, InstallMessage, Installer},
    item::{Error as ItemError, Item},
    package::{Arch, Dependency, Group, Package, Specs, User},
    plist::{Entry, Plist},
    repository::Repository,
    version::{GitRev, Rapid, SemVer, Version},
};

const DB: [&str; 4] = ["var", "db", "hpk", "db.ron.zstd"];
const DBDIR: [&str; 3] = ["var", "db", "hpk"];
const CACHE: [&str; 3] = ["var", "cache", "hpk"];

/// Gets the database file path. Takes an optional prefix variable for working
/// with an alternate filesystem root.
/// ## Examples
/// Get the database path for the currently running system:
/// ```Rust
/// let db = hpk::get_db(None);
/// ```
/// Get the database path for a chroot mounted at /mnt/aarch64:
/// ```Rust
/// let chroot = PathBuf::from("/mnt/aarch64");
/// let db = hpk::get_db(Some(chroot));
/// ```
pub fn get_db(prefix: Option<PathBuf>) -> PathBuf {
    let mut path = match prefix {
        Some(p) => p,
        None => PathBuf::from("/"),
    };
    DB.iter().for_each(|seg| path.push(seg));
    path
}

/// Gets the database directory path. Takes anoptional prefix variable for
/// working with an alternate filesystem root.
/// ## Examples
/// Get the database path for the currently running system:
/// ```Rust
/// let db = hpk::get_dbdir(None);
/// ```
/// Get the database path for a chroot mounted at /mnt/aarch64:
/// ```Rust
/// let chroot = PathBuf::from("/mnt/aarch64");
/// let db = hpk::get_dbdir(Some(chroot));
/// ```
pub fn get_dbdir(prefix: Option<PathBuf>) -> PathBuf {
    let mut path = match prefix {
        Some(p) => p,
        None => PathBuf::from("/"),
    };
    DBDIR.iter().for_each(|seg| path.push(seg));
    path
}

/// Gets the cache directory path. Takes an optional prefix variable for working
/// with an alternate filesystem root.
/// ## Examples
/// Get the cache directory for the currently running system:
/// ```Rust
/// let db = hpk::get_cache(None);
/// ```
/// Get the cache directory for a chroot mounted at /mnt/aarch64:
/// ```Rust
/// let chroot = PathBuf::from("/mnt/aarch64");
/// let db = hpk::get_cache(Some(chroot));
/// ```
pub fn get_cache(prefix: Option<PathBuf>) -> PathBuf {
    let mut path = match prefix {
        Some(p) => p,
        None => PathBuf::from("/"),
    };
    CACHE.iter().for_each(|seg| path.push(seg));
    path
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn getdb_local() {
        let db = get_db(None);
        assert_eq!(db, PathBuf::from("/var/db/hpk/db.ron.zstd"));
    }

    #[test]
    fn getdb_chroot() {
        let prefix = PathBuf::from("/mnt/aarch64");
        let db = get_db(Some(prefix));
        assert_eq!(db, PathBuf::from("/mnt/aarch64/var/db/hpk/db.ron.zstd"));
    }

    #[test]
    fn get_cache_local() {
        let cache = get_cache(None);
        assert_eq!(cache, PathBuf::from("/var/cache/hpk"));
    }

    #[test]
    fn get_cache_chroot() {
        let prefix = PathBuf::from("/mnt/aarch64");
        let cache = get_cache(Some(prefix));
        assert_eq!(cache, PathBuf::from("/mnt/aarch64/var/cache/hpk"));
    }
}
