//!
use std::path::Path;

/// The amount of retries to do during various aspects of the directory creation.
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
pub struct Retries {
    /// How many times the whole directory can be created in the light of racy interference.
    /// This count combats racy situations where another process is trying to remove a directory that we want to create,
    /// and is deliberately higher than those who do deletion. That way, creation usually wins.
    pub to_create_entire_directory: usize,
    /// The amount of times we can try to create a directory because we couldn't as the parent didn't exist.
    /// This amounts to the maximum subdirectory depth we allow to be created. Counts once per attempt to create the entire directory.
    pub on_create_directory_failure: usize,
    /// How often to retry to create a single directory if an interrupt happens, as caused by signals.
    pub on_interrupt: usize,
}

impl Default for Retries {
    fn default() -> Self {
        Retries {
            on_interrupt: 10,
            to_create_entire_directory: 5,
            on_create_directory_failure: 25,
        }
    }
}

mod error {
    use std::{fmt, path::Path};

    use crate::dir::create::Retries;

    /// The error returned by [all()][super::all()].
    #[allow(missing_docs)]
    #[derive(Debug)]
    pub enum Error<'a> {
        /// A failure we will probably recover from by trying again.
        Intermediate { dir: &'a Path, kind: std::io::ErrorKind },
        /// A failure that ends the operation.
        Permanent {
            dir: &'a Path,
            err: std::io::Error,
            /// The retries left after running the operation
            retries_left: Retries,
            /// The original amount of retries to allow determining how many were actually used
            retries: Retries,
        },
    }

    impl<'a> fmt::Display for Error<'a> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            match self {
                Error::Intermediate { dir, kind } => write!(
                    f,
                    "Intermediae failure creating {:?} with error: {:?}",
                    dir.display(),
                    kind
                ),
                Error::Permanent {
                    err: _,
                    dir,
                    retries_left,
                    retries,
                } => write!(
                    f,
                    "Permanently failing to create directory {dir:?} ({retries_left:?} of {retries:?})",
                ),
            }
        }
    }

    impl<'a> std::error::Error for Error<'a> {
        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
            match self {
                Error::Permanent { err, .. } => Some(err),
                _ => None,
            }
        }
    }
}
pub use error::Error;

enum State {
    CurrentlyCreatingDirectories,
    SearchingUpwardsForExistingDirectory,
}

/// A special iterator which communicates its operation through results where…
///
/// * `Some(Ok(created_directory))` is yielded once or more success, followed by `None`
/// * `Some(Err(Error::Intermediate))` is yielded zero or more times while trying to create the directory.
/// * `Some(Err(Error::Permanent))` is yielded exactly once on failure.
pub struct Iter<'a> {
    cursors: Vec<&'a Path>,
    retries: Retries,
    original_retries: Retries,
    state: State,
}

/// Construction
impl<'a> Iter<'a> {
    /// Create a new instance that creates `target` when iterated with the default amount of [`Retries`].
    pub fn new(target: &'a Path) -> Self {
        Self::new_with_retries(target, Default::default())
    }

    /// Create a new instance that creates `target` when iterated with the specified amount of `retries`.
    pub fn new_with_retries(target: &'a Path, retries: Retries) -> Self {
        Iter {
            cursors: vec![target],
            original_retries: retries,
            retries,
            state: State::SearchingUpwardsForExistingDirectory,
        }
    }
}

impl<'a> Iter<'a> {
    fn permanent_failure(
        &mut self,
        dir: &'a Path,
        err: impl Into<std::io::Error>,
    ) -> Option<Result<&'a Path, Error<'a>>> {
        self.cursors.clear();
        Some(Err(Error::Permanent {
            err: err.into(),
            dir,
            retries_left: self.retries,
            retries: self.original_retries,
        }))
    }

    fn intermediate_failure(&self, dir: &'a Path, err: std::io::Error) -> Option<Result<&'a Path, Error<'a>>> {
        Some(Err(Error::Intermediate { dir, kind: err.kind() }))
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = Result<&'a Path, Error<'a>>;

    fn next(&mut self) -> Option<Self::Item> {
        use std::io::ErrorKind::*;
        match self.cursors.pop() {
            Some(dir) => match std::fs::create_dir(dir) {
                Ok(()) => {
                    self.state = State::CurrentlyCreatingDirectories;
                    Some(Ok(dir))
                }
                Err(err) => match err.kind() {
                    AlreadyExists if dir.is_dir() => {
                        self.state = State::CurrentlyCreatingDirectories;
                        Some(Ok(dir))
                    }
                    AlreadyExists => self.permanent_failure(dir, err), // is non-directory
                    NotFound => {
                        self.retries.on_create_directory_failure -= 1;
                        if let State::CurrentlyCreatingDirectories = self.state {
                            self.state = State::SearchingUpwardsForExistingDirectory;
                            self.retries.to_create_entire_directory -= 1;
                            if self.retries.to_create_entire_directory < 1 {
                                return self.permanent_failure(dir, NotFound);
                            }
                            self.retries.on_create_directory_failure =
                                self.original_retries.on_create_directory_failure;
                        }
                        if self.retries.on_create_directory_failure < 1 {
                            return self.permanent_failure(dir, NotFound);
                        };
                        self.cursors.push(dir);
                        self.cursors.push(match dir.parent() {
                            None => return self.permanent_failure(dir, InvalidInput),
                            Some(parent) => parent,
                        });
                        self.intermediate_failure(dir, err)
                    }
                    Interrupted => {
                        self.retries.on_interrupt -= 1;
                        if self.retries.on_interrupt <= 1 {
                            return self.permanent_failure(dir, Interrupted);
                        };
                        self.cursors.push(dir);
                        self.intermediate_failure(dir, err)
                    }
                    _unexpected_kind => self.permanent_failure(dir, err),
                },
            },
            None => None,
        }
    }
}

/// Create all directories leading to `dir` including `dir` itself with the specified amount of `retries`.
/// Returns the input `dir` on success that make it useful in expressions.
pub fn all(dir: &Path, retries: Retries) -> std::io::Result<&Path> {
    for res in Iter::new_with_retries(dir, retries) {
        match res {
            Err(Error::Permanent { err, .. }) => return Err(err),
            Err(Error::Intermediate { .. }) | Ok(_) => continue,
        }
    }
    Ok(dir)
}
