/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/

pub mod flac;
pub mod matroska;

use crate::{
    ContainerFormat,
    demuxers::{flac::FlacDemuxer, matroska::MatroskaDemuxer},
    magic::detect_container_format,
};
use anyhow::Result;
use std::io::{Read, Seek, SeekFrom};
use winter_matroska::{Attachments, Chapters, Cluster, Cues, Info, Tags, Tracks};

pub trait ReadSeek: Read + Seek {}
impl<T: Read + Seek> ReadSeek for T {}

pub trait DemuxerNew: Demuxer + Sized {
    fn new(reader: Box<dyn ReadSeek>) -> Self;
}

#[rustfmt::skip]
pub trait Demuxer {
    fn info(&mut self) -> Result<Info>;
    fn tracks(&mut self) -> Result<Option<Tracks>> { Ok(None) }
    fn chapters(&mut self) -> Result<Option<Chapters>> { Ok(None) }
    fn attachments(&mut self) -> Result<Option<Attachments>> { Ok(None) }
    fn tags(&mut self) -> Result<Option<Tags>> { Ok(None) }
    fn cues(&mut self) -> Result<Option<Cues>> { Ok(None) }

    fn seek_cluster(&mut self, position: Option<u64>) -> Result<()>;
    fn read_cluster(&mut self) -> Result<Option<(u64, Cluster)>>;
}

pub fn create_demuxer(container: ContainerFormat, reader: Box<dyn ReadSeek>) -> Box<dyn Demuxer> {
    match container {
        ContainerFormat::Matroska | ContainerFormat::Webm => Box::new(MatroskaDemuxer::new(reader)),
        ContainerFormat::Flac => Box::new(FlacDemuxer::new(reader)),
        ContainerFormat::Mpeg4 => todo!(),
    }
}
pub fn create_demuxer_autodetect(
    mut reader: Box<dyn ReadSeek>,
) -> Result<Option<Box<dyn Demuxer>>> {
    let Some(container) = detect_container_format(&mut reader)? else {
        return Ok(None);
    };
    reader.seek(SeekFrom::Start(0))?;
    Ok(Some(create_demuxer(container, reader)))
}
