//! The output assets generated for each Emoji version.

use std::fmt;

/// One of the eight assets produced for each Emoji version.
///
/// Each variant maps to a file name. The text formats differ by target. See the
/// per-variant docs for the exact shape.
///
/// This enum is `#[non_exhaustive]`. A future asset kind adds a variant in a
/// minor release. Match on it with a wildcard arm, or iterate
/// [`OutputKind::ALL`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[non_exhaustive]
pub enum OutputKind {
    /// Human readable index. One line per emoji: `<U+XXXX ...> \u{2192} <emoji>`.
    /// Ends with a newline.
    Index,
    /// One emoji string per line. Ends with a newline.
    IndexStrings,
    /// A CSS `unicode-range` value. Comma joined `U+...` ranges. Ends with a
    /// newline.
    Css,
    /// JavaScript regex pattern for use without the `u` flag. Astral code
    /// points render as UTF-16 surrogate pairs. No trailing newline.
    JavaScript,
    /// JavaScript regex pattern for use with the `u` flag. Astral code points
    /// render as `\u{...}`. No trailing newline.
    JavaScriptU,
    /// JavaScript regex pattern for use with the `v` flag. Prefixed with
    /// `\p{RGI_Emoji}|`. No trailing newline.
    JavaScriptV,
    /// Java `java.util.regex.Pattern` compatible pattern. Astral code points
    /// render as `\x{...}`. No trailing newline.
    Java,
    /// Google RE2 (C++) compatible pattern. Every non `\xHH` code point renders
    /// as `\x{...}`. No trailing newline.
    CppRe2,
}

impl OutputKind {
    /// Every output kind.
    pub const ALL: [OutputKind; 8] = [
        OutputKind::Index,
        OutputKind::IndexStrings,
        OutputKind::Css,
        OutputKind::JavaScript,
        OutputKind::JavaScriptU,
        OutputKind::JavaScriptV,
        OutputKind::Java,
        OutputKind::CppRe2,
    ];

    /// The file name for this asset, such as `"index.txt"`.
    #[must_use]
    pub const fn file_name(self) -> &'static str {
        match self {
            OutputKind::Index => "index.txt",
            OutputKind::IndexStrings => "index-strings.txt",
            OutputKind::Css => "css.txt",
            OutputKind::JavaScript => "javascript.txt",
            OutputKind::JavaScriptU => "javascript-u.txt",
            OutputKind::JavaScriptV => "javascript-v.txt",
            OutputKind::Java => "java.txt",
            OutputKind::CppRe2 => "cpp-re2.txt",
        }
    }

    /// Whether this asset ends with a trailing newline.
    ///
    /// The three text assets end with `\n`. The five regex patterns do not.
    #[must_use]
    pub const fn has_trailing_newline(self) -> bool {
        matches!(
            self,
            OutputKind::Index | OutputKind::IndexStrings | OutputKind::Css
        )
    }
}

impl fmt::Display for OutputKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.file_name())
    }
}
