use super::SyncTrackInfo;
use crate::{IdMetadataExt, Stack, Track};
use std::collections::HashSet;
#[derive(Debug, Clone, PartialEq, Eq)]
struct TrackBoundaryGroup {
track_indices: Vec<usize>,
}
impl Stack {
pub fn add_track(&mut self, track: Track) {
self.children.push(track);
self.sanitize();
}
pub fn add_track_at(&mut self, track: Track, insertion_index: isize) -> bool {
let idx = super::clamp_insertion_index(self.children.len(), insertion_index);
self.children.insert(idx, track);
self.sanitize();
true
}
pub fn reorder_track(&mut self, id: &str, insertion_index: isize) -> bool {
let Some((track_index, _)) = self.get_track_by_id(id) else {
return false;
};
let dest_index = super::clamp_insertion_index(self.children.len(), insertion_index);
if dest_index == track_index || dest_index == track_index + 1 {
return true;
}
let track = self.children.remove(track_index);
let adjusted_dest_index = if dest_index > track_index {
dest_index - 1
} else {
dest_index
};
self.children.insert(adjusted_dest_index, track);
self.sanitize();
true
}
pub fn sync_track_info(&self) -> Vec<SyncTrackInfo> {
self.track_boundary_ranges()
.into_iter()
.map(|group| {
let track_indices = group.track_indices.clone();
let track_ids = track_indices
.iter()
.map(|index| self.children[*index].get_id())
.collect();
SyncTrackInfo {
track_indices,
track_ids,
}
})
.collect()
}
pub fn delete_track(&mut self, id: &str) -> Option<Track> {
let (i, _) = self.get_track_by_id(id)?;
let removed = self.children.remove(i);
self.sanitize_preserving_all_gap_tracks();
Some(removed)
}
pub(super) fn boundary_group_indices(&self, track_index: usize) -> Vec<usize> {
let mut indices = HashSet::new();
for group in self.track_boundary_ranges() {
if group.track_indices.contains(&track_index) {
indices.extend(&group.track_indices);
}
}
if indices.is_empty() {
return vec![track_index];
}
let mut result: Vec<_> = indices.into_iter().collect();
result.sort_unstable();
result
}
fn track_boundary_ranges(&self) -> Vec<TrackBoundaryGroup> {
let len = self.children.len();
if len == 0 {
return Vec::new();
}
let mut groups = Vec::new();
let mut seen = std::collections::HashSet::new();
for anchor in 0..len {
let mut track_indices: Vec<usize> = (0..len)
.filter(|&candidate| self.tracks_share_sync_clips(anchor, candidate))
.collect();
track_indices.sort_unstable();
if seen.insert(track_indices.clone()) {
groups.push(TrackBoundaryGroup { track_indices });
}
}
groups.sort_by(|left, right| left.track_indices.cmp(&right.track_indices));
groups
}
}