//! Error handling.

use std::path::PathBuf;

use voa_core::identifiers::{Purpose, Technology};

/// The error that can occur when using VOA.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    /// An I/O error occurred at a path.
    #[error("I/O error at path {path} while {context}:\n{source}")]
    IoPath {
        /// The path at which the error occurred.
        path: PathBuf,
        /// The context in which the error occurred.
        ///
        /// This is meant to complete the sentence "I/O error at path while ".
        context: &'static str,
        /// The source error.
        source: std::io::Error,
    },

    /// A path is not a regular file.
    #[error("The path {path:?} is not a regular file")]
    PathIsNotAFile {
        /// The invalid path.
        path: PathBuf,
    },

    /// A path represents neither a directory nor a regular file.
    #[error("The path {path:?} is not a directory or a regular file")]
    PathIsNotDirOrFile {
        /// The invalid path.
        path: PathBuf,
    },

    /// A user has no default VOA load path.
    ///
    /// This usually happens if the user has no `$HOME` assigned to it.
    #[error("There is no default VOA load path for this user")]
    NoLoadPath,

    /// A technology is not supported.
    #[error("The {technology} technology is not (yet) supported")]
    UnsupportedTechnology {
        /// The technology that is not supported.
        technology: Technology,
    },

    /// An error occurred in VOA-core.
    #[error("VOA core error:\n{0}")]
    VoaCore(#[from] voa_core::Error),

    /// An error occurred in VOA-OpenPGP.
    #[error("VOA OpenPGP error:\n{0}")]
    VoaOpenPgp(#[from] voa_openpgp::Error),

    /// The JSON serialization of data failed.
    #[error("JSON serialization error while {context}: {source}")]
    #[cfg(feature = "cli")]
    JsonSerialization {
        /// The context in which the error occurred.
        ///
        /// This is meant to complete the sentence "JSON serialization error while...".
        context: &'static str,

        /// The error source.
        source: serde_json::Error,
    },

    /// The verification of one or more signatures failed.
    #[error("The verification of the following signatures failed: {}", signatures.join(", "))]
    SignatureVerificationFailed {
        /// The paths of the failed signatures.
        signatures: Vec<String>,
    },

    /// A [`Purpose`] represents the trust anchor mode, but should represent the artifact verifier
    /// mode.
    #[error(
        "The purpose {purpose} represents the trust anchor mode, but should represent the artifact verifier mode"
    )]
    PurposeIsATrustAnchor {
        /// The invalid purpose.
        purpose: Purpose,
    },
}
