use crate::rhythm::TrackId;
use std::{collections::HashMap, sync::Arc};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum GroupId {
Main,
Named(Arc<str>),
}
impl GroupId {
pub fn as_deref(&self) -> Option<&str> {
match self {
GroupId::Main => None,
GroupId::Named(name) => Some(name),
}
}
}
pub trait NoteGroup {
fn main_group() -> Self;
fn tempo_track_id(&self) -> &TrackId;
fn scroll_track_id(&self) -> &TrackId;
}
#[derive(Debug, Clone)]
pub struct NoteGroups<G> {
main: G,
named: HashMap<Arc<str>, G>,
}
impl<G: NoteGroup> NoteGroups<G> {
pub fn new() -> Self {
Self {
named: Default::default(),
main: G::main_group(),
}
}
pub fn with_groups(main: G, groups: impl Iterator<Item = (Arc<str>, G)>) -> Self {
let named = groups.into_iter().collect();
Self { named, main }
}
pub fn groups(&self) -> impl Iterator<Item = (GroupId, &G)> {
std::iter::chain(
std::iter::once((GroupId::Main, &self.main)),
self.named
.iter()
.map(|(gid, g)| (GroupId::Named(gid.clone()), g)),
)
}
pub fn add_group(&mut self, id: Arc<str>, group: G) {
if self.named.contains_key(&id) {
return;
}
self.named.insert(id, group);
}
pub fn remove_group(&mut self, id: &str) -> Option<G> {
self.named.remove(id)
}
pub fn insert_or_replace_group(&mut self, id: GroupId, group: G) -> Option<G> {
match id {
GroupId::Named(id) => self.named.insert(id, group),
GroupId::Main => Some(std::mem::replace(&mut self.main, group)),
}
}
pub fn get_group_mut(&mut self, id: &GroupId) -> Option<&mut G> {
match id.as_deref() {
Some(id) => self.named.get_mut(id),
None => Some(&mut self.main),
}
}
pub fn get_group(&self, id: &GroupId) -> Option<&G> {
match id.as_deref() {
Some(id) => self.named.get(id),
None => Some(&self.main),
}
}
pub fn get_group_or_mainmut(&mut self, id: &GroupId) -> &mut G {
match id.as_deref() {
Some(id) => self.named.get_mut(id).unwrap_or(&mut self.main),
None => &mut self.main,
}
}
pub fn get_group_or_main(&self, id: &GroupId) -> &G {
match id.as_deref() {
Some(id) => self.named.get(id).unwrap_or(&self.main),
None => &self.main,
}
}
pub fn main_group(&self) -> &G {
&self.main
}
pub fn main_group_mut(&mut self) -> &mut G {
&mut self.main
}
}
impl<G: Default + NoteGroup> Default for NoteGroups<G> {
fn default() -> Self {
Self::new()
}
}