#[cfg(feature = "enable_codec")]
pub(crate) use enabled::AACEncoder;

#[cfg(not(feature = "enable_codec"))]
pub(crate) use disabled::AACEncoder;

#[cfg(feature = "enable_codec")]
mod enabled {
    use std::pin::Pin;

    use crate::packet::{Audio, AudioCodec};
    use anyhow::{Result, bail};
    use bytes::Bytes;

    use th_rs::define::{TH_AUDIOCODECTYPE_TH_ACT_G711, TH_DATATYPE_TH_DT_AUDIO, TH_ESStreamInfo};
    use tokio::task::block_in_place;

    use xodec_rs::encoder_aac::EncoderAAC;

    pub(crate) struct AACEncoder {
        encoder: Pin<Box<EncoderAAC>>,
    }

    impl AACEncoder {
        pub fn new() -> Self {
            Self {
                encoder: EncoderAAC::new(),
            }
        }

        pub fn write(&mut self, audio: &Audio, payload: Bytes) -> Result<Bytes> {
            let encoder = &mut self.encoder;
            match audio.codec {
                AudioCodec::Aac => Ok(payload),
                AudioCodec::G711A => {
                    let o_aac = block_in_place(move || {
                        let sp = tracing::span!(tracing::Level::ERROR, "aac_encode");
                        let _enter = sp.enter();
                        encoder.write(
                            &payload,
                            &TH_ESStreamInfo {
                                streamType: TH_DATATYPE_TH_DT_AUDIO as _,
                                aCodecType: TH_AUDIOCODECTYPE_TH_ACT_G711 as _,
                                aSampleRate: audio.sample_rate,
                                aChannels: audio.channels,
                                aSampleBits: audio.bits,
                                ..Default::default()
                            },
                        )
                    });

                    let Ok(aac) = o_aac else { bail!("Encode aac fail") };

                    Ok(Bytes::copy_from_slice(aac))
                },
                other => bail!("No support audio codec({:?}) encode to aac", other),
            }
        }
    }
}

#[cfg(not(feature = "enable_codec"))]
mod disabled {
    use crate::packet::Audio;
    use anyhow::{Result, bail};
    use bytes::Bytes;

    pub(crate) struct AACEncoder;

    impl AACEncoder {
        pub fn new() -> Self {
            Self
        }

        #[allow(unused_variables)]
        pub fn write(&mut self, audio: &Audio, payload: Bytes) -> Result<Bytes> {
            const ERR_MSG: &str = "enable_codec feature is not enabled, cannot encode audio";
            tracing::error!("{ERR_MSG}");
            bail!(ERR_MSG)
        }
    }
}