//! Collection of songs

use fmod;
use vec_map::VecMap;

#[derive(Clone, Debug, Default, PartialEq)]
pub struct Music {
  songs : VecMap <fmod::Sound>
}

pub type IndexType = u16;
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Id (pub IndexType);

impl Music {
  /// Initialize by loading a list of .mid (standard midi file) / .dls (soundfont) pairs
  #[inline]
  #[expect(clippy::missing_panics_doc)]
  pub fn load_midi (
    system : &mut fmod::System,
    songs : VecMap <(String, String)>
  ) -> Self {
    use std::iter::FromIterator;
    let mut midi_exinfo = fmod::sound::Createsoundexinfo::default();
    let songs = VecMap::<fmod::Sound>::from_iter (
      songs.into_iter().map (|(i, (midfilename, dlsfilename))| {
        midi_exinfo.dlsname = std::ffi::CString::new (dlsfilename).unwrap();
        let track = system.create_sound_from_file (
          &midfilename, fmod::Mode::DEFAULT, Some (&mut midi_exinfo)
        ).unwrap();
        (i, track)
      })
    );
    Music { songs }
  }
  /// Initialize by loading a list of .mid (standard midi file) / .dls (soundfont) pairs
  #[inline]
  #[expect(clippy::missing_panics_doc)]
  pub fn load_midi_memory (
    system : &mut fmod::System,
    songs : VecMap <(&[u8], String)>
  ) -> Self {
    use std::iter::FromIterator;
    let mut midi_exinfo = fmod::sound::Createsoundexinfo::default();
    let songs = VecMap::<fmod::Sound>::from_iter (
      songs.into_iter().map (|(i, (bytes, dlsfilename))| {
        midi_exinfo.dlsname = std::ffi::CString::new (dlsfilename).unwrap();
        let track = system.create_sound_from_memory (
          bytes, fmod::Mode::DEFAULT, Some (&mut midi_exinfo)
        ).unwrap();
        (i, track)
      })
    );
    Music { songs }
  }
  #[inline]
  pub fn get (&self, id : Id) -> Option <&fmod::Sound> {
    self.songs.get (id.0 as usize)
  }
  #[inline]
  pub fn get_mut (&mut self, id : Id) -> Option <&mut fmod::Sound> {
    self.songs.get_mut (id.0 as usize)
  }
  #[inline]
  pub fn set (&mut self, sample : fmod::Sound, id : Id) {
    let _ = self.songs.insert (id.0 as usize, sample);
  }
  #[inline]
  pub fn remove (&mut self, id : Id) -> Option <fmod::Sound> {
    self.songs.remove (id.0 as usize)
  }
}
