///! Thin wrapper struct for creating temp directories
///! Taken after cgroups/tempdir
use anyhow::{Context, Result};
use std::{
    fs,
    ops::Deref,
    path::{Path, PathBuf},
};
use uuid::Uuid;

pub struct TempDir {
    path: Option<PathBuf>,
}

impl TempDir {
    pub fn new<P: Into<PathBuf>>(path: P) -> Result<Self> {
        let p = path.into();
        std::fs::create_dir_all(&p)
            .with_context(|| format!("failed to create diectory {:?}", p))?;
        Ok(Self { path: Some(p) })
    }

    pub fn path(&self) -> &Path {
        self.path
            .as_ref()
            .expect("temp dir has already been removed")
    }

    pub fn remove(&mut self) {
        if let Some(p) = &self.path {
            let _ = fs::remove_dir_all(p);
            self.path = None;
        }
    }
}

impl Drop for TempDir {
    fn drop(&mut self) {
        self.remove();
    }
}

impl AsRef<Path> for TempDir {
    fn as_ref(&self) -> &Path {
        self.path()
    }
}

impl Deref for TempDir {
    type Target = Path;

    fn deref(&self) -> &Self::Target {
        self.path()
    }
}

pub fn create_temp_dir(id: &Uuid) -> Result<TempDir> {
    let dir = TempDir::new(std::env::temp_dir().join(id.to_string()))?;
    Ok(dir)
}
