//! Error handling for importing destructured [OpenPGP certificates] as [VOA] verifiers.
//!
//! [OpenPGP certificates]: https://openpgp.dev/book/certificates.html
//! [VOA]: https://uapi-group.org/specifications/specs/file_hierarchy_for_the_verification_of_os_artifacts/

use std::path::PathBuf;

use pgp::types::{Fingerprint, Tag};

use crate::import::destructured::{CERTIFICATION_DIR, REVOCATION_DIR};

/// The error that can occur when importing verifiers.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    /// A directory must only contain other directories, but contains a path that is not a
    /// directory.
    #[error(
        "The directory {dir:?} must only contain directories, but the path {path:?} is not a directory."
    )]
    DirMustContainDirs {
        /// The directory that must only contain other directories.
        dir: PathBuf,
        /// The path, that does not represent a directory.
        path: PathBuf,
    },

    /// A directory is only supposed to contain regular files, but contains a path that is not a
    /// regular file.
    #[error(
        "The directory {dir:?} must only contain regular files, but the path {path:?} is not a regular file."
    )]
    DirMustContainRegularFiles {
        /// The directory that must only contain regular files.
        dir: PathBuf,
        /// The path, that does not represent a regular file.
        path: PathBuf,
    },

    /// A directory must only contain regular files or directories, but contains a path that
    /// represents neither.
    #[error(
        "The directory {dir:?} must only contain regular files or directories, but the path {path:?} is neither."
    )]
    DirMustContainRegularFilesOrDirs {
        /// The directory that must only contain regular files or other directories.
        dir: PathBuf,
        /// The path, that does not represent a regular file or directory.
        path: PathBuf,
    },

    /// There is an additional, unwanted OpenPGP certificate.
    #[error("There is an excess OpenPGP certificate with fingerprint {fingerprint} in {path:?}")]
    ExcessCertificateInDir {
        /// The directory path in which OpenPGP packets of more than one OpenPGP certificate are
        /// present.
        path: PathBuf,
        /// The OpenPGP fingerprint of the excess OpenPGP certificate.
        fingerprint: Fingerprint,
    },

    /// There is an additional, unwanted OpenPGP packet in a file.
    #[error("There is an excess {tag:?} OpenPGP packet in file {path:?}")]
    ExcessPacket {
        /// The path of the file in which an excess OpenPGP packet is present.
        path: PathBuf,
        /// The excess OpenPGP packet.
        tag: Tag,
    },

    /// A regular file is empty.
    #[error("The file {path:?} is empty.")]
    FileIsEmpty {
        /// The path of the empty file.
        path: PathBuf,
    },

    /// A directory does not have a valid Arch Linux keyring structure.
    #[error("The import directory {path:?} does not contain a valid Arch Linux keyring structure")]
    InvalidArchLinuxKeyringStructure {
        /// The path to the directory that is not a valid Arch Linux keyring structure.
        path: PathBuf,
    },

    /// A directory in a User ID directory is not valid
    #[error(
        "The directory {path:?} is not a valid component subdirectory ({} and/or {})",
        CERTIFICATION_DIR,
        REVOCATION_DIR
    )]
    InvalidComponentSubDirectory {
        /// The path to the directory that is invalid in a User ID directory.
        path: PathBuf,
    },

    /// A directory does not have a valid flat structure.
    #[error("The import directory {path:?} does not contain a valid flat structure")]
    InvalidFlatStructure {
        /// The path to the directory that does not contain a flat structure.
        path: PathBuf,
    },

    /// There is more than one top-level OpenPGP packet file in a directory.
    #[error("There is more than one top-level OpenPGP packet file in directory {path:?}")]
    MultipleTopLevelPackets {
        /// The path of a directory with more than one top-level OpenPGP packet file.
        path: PathBuf,
    },

    /// An OpenPGP certificate cannot be constructed from OpenPGP packets in a directory.
    #[error("No OpenPGP certificate can be constructed from the directory {path:?}")]
    NoOpenPgpCertInDir {
        /// The directory path from which no OpenPGP certificate can be constructed.
        path: PathBuf,
    },

    /// There is no OpenPGP packet in a file.
    #[error("There is no OpenPGP packet in file {path:?}")]
    NoPacketInFile {
        /// The path at which no packet
        path: PathBuf,
    },

    /// There is no top-level OpenPGP packet file in a directory.
    #[error("There is no top-level OpenPGP packet file in directory {path:?}")]
    NoTopLevelPacket {
        /// The path of a directory in which there is no top-level OpenPGP packet file.
        path: PathBuf,
    },

    /// A path is not a directory.
    #[error("The path {path:?} is not a directory.")]
    PathIsNotADir {
        /// The path that is not a directory.
        path: PathBuf,
    },
}
