//! The anti-list — formats this project will never support, and why.
//!
//! See `DECISION.md` D002 and `download/format-research.md` for the full rationale.
//! The list is hardcoded; adding to it requires a code change (intentional —
//! we don't want this list silently editable at runtime).

/// Information about a rejected format, shown to the user when they try to open one.
#[derive(Debug, Clone, Copy)]
pub struct AntiListedFormat {
    /// The display name, e.g. "HEIC", "Canon CR3".
    pub name: &'static str,
    /// File extensions (lowercase, no leading dot) that trigger this rejection.
    pub extensions: &'static [&'static str],
    /// Short user-facing reason.
    pub reason: &'static str,
    /// Suggested open alternative.
    pub alternative: &'static str,
}

/// The full anti-list. Add new entries here if a new proprietary format
/// becomes a problem. Do NOT remove entries without updating DECISION.md.
pub const ANTI_LIST: &[AntiListedFormat] = &[
    AntiListedFormat {
        name: "HEIF",
        extensions: &["heif", "heifs"],
        reason: "ISOBMFF container paired with HEVC; subject to MPEG-LA / HEVC Advance patent pools. Not royalty-free.",
        alternative: "AVIF — same ISOBMFF container, royalty-free AV1 codec. Covers HDR, animation, and alpha.",
    },
    AntiListedFormat {
        name: "HEIC",
        extensions: &["heic", "heics"],
        reason: "Apple's HEIF variant. Same HEVC patent baggage as HEIF.",
        alternative: "AVIF for HDR/animation, or JPEG XL for archival masters.",
    },
    AntiListedFormat {
        name: "Canon CR3",
        extensions: &["cr3", "crw"],
        reason: "Proprietary Canon RAW format. Spec is not public; Canon can change it at will.",
        alternative: "Convert to DNG (still Adobe-controlled) or to TIFF for an open archival master.",
    },
    AntiListedFormat {
        name: "Nikon NEF",
        extensions: &["nef"],
        reason: "Proprietary Nikon RAW format. Spec is not public.",
        alternative: "Convert to TIFF for an open archival master.",
    },
    AntiListedFormat {
        name: "Sony ARW",
        extensions: &["arw", "srf", "sr2"],
        reason: "Proprietary Sony RAW format. Spec is not public.",
        alternative: "Convert to TIFF for an open archival master.",
    },
    AntiListedFormat {
        name: "Adobe PSD",
        extensions: &["psd", "psb"],
        reason: "Proprietary Photoshop format. Partially documented but Adobe-controlled; layered rendering is non-trivial.",
        alternative: "Export as TIFF for layered raster, or PNG/JPEG XL for flattened.",
    },
    AntiListedFormat {
        name: "Adobe DNG",
        extensions: &["dng"],
        reason: "'Partially open' — Adobe publishes the spec but retains control. Not a true open standard.",
        alternative: "TIFF for archival still photography (16-bit, ICC, multi-page).",
    },
    AntiListedFormat {
        name: "Apple Live Photos",
        extensions: &["livephoto", "live"],
        reason: "Proprietary paired image+video container. Apple-controlled. Not really an image format — out of scope for a still-image viewer.",
        alternative: "Export the still component as JPEG or HEIC (then convert HEIC to AVIF).",
    },
];

/// Look up an extension in the anti-list. Returns the format info if found.
pub fn lookup(extension: &str) -> Option<AntiListedFormat> {
    let ext = extension.to_ascii_lowercase();
    ANTI_LIST
        .iter()
        .find(|f| f.extensions.contains(&ext.as_str()))
        .copied()
}

/// Is this extension in the anti-list?
/// Convenience wrapper around `lookup` for callers that don't need the
/// format details. Currently used only by tests; kept for future callers
/// (e.g. a drag-and-drop handler that needs a yes/no answer).
#[allow(dead_code)]
pub fn is_anti_listed(extension: &str) -> bool {
    lookup(extension).is_some()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn heic_is_rejected() {
        assert!(is_anti_listed("heic"));
        assert!(is_anti_listed("HEIC"));
        assert!(is_anti_listed("Heic"));
    }

    #[test]
    fn cr3_is_rejected() {
        assert!(is_anti_listed("cr3"));
        assert!(is_anti_listed("CR3"));
    }

    #[test]
    fn png_is_not_anti_listed() {
        assert!(!is_anti_listed("png"));
    }

    #[test]
    fn lookup_returns_correct_info() {
        let info = lookup("heic").unwrap();
        assert_eq!(info.name, "HEIC");
        assert!(info.reason.contains("HEVC"));
        assert!(info.alternative.contains("AVIF"));
    }

    #[test]
    fn case_insensitive() {
        assert_eq!(lookup("DNG").unwrap().name, "Adobe DNG");
        assert_eq!(lookup("Psd").unwrap().name, "Adobe PSD");
    }
}
