// Use https://kazlauskas.me/entries/errors as a reference

use crate::*;

use std::io;
use std::result;
use thiserror::Error;

pub type Result<T> = result::Result<T, Error>;

/// Result wrapper used to easily `Display` the Status of an execution
pub struct Status {
    result: Result<()>,
}

impl Display for Status {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Status { result: Ok(_) } => write!(f, "Ok"),
            Status { result: Err(e) } => write!(f, "Error: {}", e),
        }
    }
}

impl From<Result<()>> for Status {
    fn from(result: Result<()>) -> Self {
        Status { result }
    }
}

/// An error that can occur in this crate.
///
/// Generally, this error corresponds to problems with underlying process.
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum Error {
    // TODO: This error is meh, better get the full list of errors for a Packager and then if all executors are in error have a generic one? Or details all and ask to fix one?
    #[error(
        r#"No configured executor could be run, last one returned: {source} for "{filename}""#
    )]
    Config {
        source: which::Error,
        filename: String,
    },
    #[error("Could not achieve the \"{step}\" step. Command `{cmd}` exited with: {source}")]
    Execution {
        source: io::Error,
        step: UpdateSteps,
        cmd: ActualCmd,
    },
}
