use crate::dataloading::songinfo::SongInfo;
use crate::traktor_api;
use crate::traktor_api::TraktorDataProvider;
use std::cmp::PartialEq;
#[derive(Default, Debug, PartialEq, Clone)]
pub enum SongDataSource {
#[default]
Blank,
Traktor,
Other(SongInfo),
Static(usize),
Playlist(usize),
}
#[derive(Debug, Clone, Copy)]
pub enum SongChange {
Blank,
Traktor,
StaticAbsolute(usize),
PlaylistAbsolute(usize),
Previous,
Next,
}
#[derive(Debug, Clone)]
pub enum SongDataEdit {
Title(String),
Artist(String),
Dance(String),
}
#[derive(Default)]
pub struct SongDataProvider {
pub playlist_songs: Vec<SongInfo>,
pub playlist_played: Vec<bool>,
pub statics: Vec<SongInfo>,
pub traktor_provider: TraktorDataProvider,
pub current: SongDataSource,
pub next: Option<SongDataSource>,
should_scroll: bool,
}
impl SongDataProvider {
pub fn set_vec(&mut self, vec: Vec<SongInfo>) {
self.playlist_songs = vec;
self.playlist_played = vec![false; self.playlist_songs.len()];
if !self.playlist_songs.is_empty() {
self.current = SongDataSource::Playlist(0);
} else {
self.current = SongDataSource::Blank;
}
}
pub fn set_statics(&mut self, vec: Vec<SongInfo>) {
self.statics = vec;
}
fn set_current_as_played(&mut self) {
let i = match self.current {
SongDataSource::Playlist(i) => i,
SongDataSource::Traktor => {
let Some(index) = self.get_current_traktor_index() else {
return;
};
index
}
_ => return,
};
if let Some(v) = self.playlist_played.get_mut(i) {
*v = true;
}
}
pub fn get_current_song_info(&self) -> Option<&SongInfo> {
match self.current {
SongDataSource::Static(i) => self.statics.get(i),
SongDataSource::Playlist(i) => self.playlist_songs.get(i),
SongDataSource::Other(ref song) => Some(song),
SongDataSource::Blank => None,
SongDataSource::Traktor => self.traktor_provider.get_song_info(),
}
}
pub fn get_next_song_info(&self) -> Option<&SongInfo> {
if let Some(next) = self.next.as_ref() {
return match next {
SongDataSource::Static(i) => self.statics.get(*i),
SongDataSource::Playlist(i) => self.playlist_songs.get(*i),
SongDataSource::Other(song) => Some(song),
SongDataSource::Blank => None,
SongDataSource::Traktor => self.traktor_provider.get_next_song_info(),
};
}
match self.current {
SongDataSource::Static(_) => None,
SongDataSource::Playlist(i) => self.playlist_songs.get(i + 1),
SongDataSource::Other(ref song) => Some(song),
SongDataSource::Blank => None,
SongDataSource::Traktor => self.traktor_provider.get_next_song_info(),
}
}
pub fn prev(&mut self) {
self.should_scroll = true;
let SongDataSource::Playlist(current_index) = self.current else {
return;
};
if current_index == 0 {
return;
}
self.set_current_as_played();
self.current = SongDataSource::Playlist(current_index - 1);
}
pub fn next(&mut self) {
self.should_scroll = true;
if let Some(next) = self.next.take() {
self.set_current_as_played();
self.current = next;
return;
}
let SongDataSource::Playlist(current_index) = self.current else {
return;
};
if current_index == self.playlist_songs.len() - 1 {
return;
}
self.set_current_as_played();
self.current = SongDataSource::Playlist(current_index + 1);
}
pub fn set_current(&mut self, n: SongDataSource) {
self.set_current_as_played();
match n {
SongDataSource::Static(i) => {
if self.playlist_songs.get(i).is_some() {
self.current = n;
}
}
SongDataSource::Playlist(i) => {
if self.playlist_songs.get(i).is_some() {
self.current = n;
}
}
_ => self.current = n,
}
}
pub fn set_next(&mut self, next: SongDataSource) {
self.next = Some(next);
}
pub fn append_song(&mut self, song: SongInfo) {
self.playlist_songs.push(song);
self.playlist_played.push(false);
}
pub fn delete_song(&mut self, song: SongDataSource) {
if let SongDataSource::Playlist(i) = song {
self.playlist_songs.remove(i);
self.playlist_played.remove(i);
} else if let SongDataSource::Static(i) = song {
self.statics.remove(i);
}
}
pub fn handle_song_change(&mut self, change: SongChange) {
match change {
SongChange::Blank => {
self.set_current_as_played();
self.current = SongDataSource::Blank;
}
SongChange::Traktor => {
self.set_current_as_played();
self.current = SongDataSource::Traktor;
}
SongChange::StaticAbsolute(index) => {
self.set_current_as_played();
self.current = SongDataSource::Static(index);
}
SongChange::PlaylistAbsolute(index) => {
self.set_current_as_played();
self.current = SongDataSource::Playlist(index);
}
SongChange::Previous => {
self.prev();
}
SongChange::Next => {
self.next();
}
}
}
pub fn handle_song_data_edit(&mut self, i: usize, edit: SongDataEdit) {
if let Some(song) = self.playlist_songs.get_mut(i) {
match edit {
SongDataEdit::Title(title) => {
song.title = title;
}
SongDataEdit::Artist(artist) => {
song.artist = artist;
}
SongDataEdit::Dance(dance) => {
song.dance = dance;
}
}
}
}
pub fn process_traktor_message(&mut self, message: traktor_api::ServerMessage) {
self.set_current_as_played();
self.traktor_provider
.process_message(message, &self.playlist_songs);
}
pub fn get_current_traktor_index(&self) -> Option<usize> {
self.traktor_provider
.get_current_index(&self.playlist_songs)
}
pub fn take_scroll_index(&mut self) -> Option<usize> {
let should_scroll = self.should_scroll | self.traktor_provider.take_should_scroll();
self.should_scroll = false;
if !should_scroll {
return None;
}
match self.current {
SongDataSource::Traktor => self.get_current_traktor_index(),
SongDataSource::Playlist(i) => Some(i),
_ => None,
}
}
}