use infer::{
    audio::{is_aiff, is_ape, is_flac, is_m4a, is_mp3, is_ogg, is_wav},
    video::is_mp4,
};
use serde::{Deserialize, Serialize};

/// All recognized audio containers
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
pub enum ContainerFormat {
    Flac,
    Mp3,
    Ogg,
    Wav,
    Aiff,
    Ape,
    Mp4,
}

impl ContainerFormat {
    /// Gets container type by reading magic bytes
    ///
    /// Returns none if the container type is unsupported or unrecognized, or cannot be read
    #[must_use]
    pub fn from_buf(buf: &[u8; 16]) -> Option<Self> {
        let container = if is_flac(buf) {
            ContainerFormat::Flac
        } else if is_ogg(buf) {
            ContainerFormat::Ogg
        } else if is_mp3(buf) {
            ContainerFormat::Mp3
        } else if is_wav(buf) {
            ContainerFormat::Wav
        } else if is_aiff(buf) {
            ContainerFormat::Aiff
        } else if is_ape(buf) {
            ContainerFormat::Ape
        } else if is_m4a(buf) || is_mp4(buf) {
            ContainerFormat::Mp4
        } else {
            return None;
        };
        Some(container)
    }

    /// Returns the name as of the container that ffmpeg uses for encoding (the "`format_name`")
    #[must_use]
    pub fn format_name(&self) -> &str {
        match self {
            ContainerFormat::Aiff => "aiff",
            ContainerFormat::Ape => "ape",
            ContainerFormat::Flac => "flac",
            ContainerFormat::Mp3 => "mp3",
            ContainerFormat::Ogg => "ogg",
            ContainerFormat::Wav => "wav",
            ContainerFormat::Mp4 => "mp4",
        }
    }
}
