use crate::app::component::actionhandler::ComponentEffect;
use crate::app::server::song_downloader::{DownloadProgressUpdate, DownloadProgressUpdateType};
use crate::app::server::song_thumbnail_downloader::{SongThumbnail, SongThumbnailID};
use crate::app::server::{ArcServer, TaskMetadata};
use crate::app::structures::ListSongID;
use crate::app::ui::playlist::Playlist;
use crate::async_rodio_sink::{
AllStopped, AutoplayUpdate, PausePlayResponse, Paused, PlayUpdate, ProgressUpdate, QueueUpdate,
Resumed, Stopped, VolumeUpdate,
};
use async_callback_manager::{AsyncTask, FrontendEffect};
use rodio::decoder::DecoderError;
use std::fmt::Debug;
use tracing::error;
#[derive(Debug, PartialEq)]
pub struct HandleAllStopped;
#[derive(Debug, PartialEq)]
pub struct HandleStopped;
#[derive(Debug, PartialEq)]
pub struct HandleSetSongPlayProgress;
#[derive(Debug, PartialEq)]
pub struct HandleVolumeUpdate;
#[derive(Debug, PartialEq)]
pub struct HandleGetSongThumbnailOk;
#[derive(Debug, PartialEq)]
pub struct HandlePausePlayResponse;
#[derive(Debug, PartialEq)]
pub struct HandleResumeResponse;
#[derive(Debug, PartialEq)]
pub struct HandlePausedResponse;
#[derive(Debug, PartialEq)]
pub struct HandleGetSongThumbnailError(pub SongThumbnailID<'static>);
#[derive(Debug, PartialEq, Clone)]
pub struct HandlePlayUpdateOk;
#[derive(Debug, PartialEq, Clone)]
pub struct HandleAutoplayUpdateOk;
#[derive(Debug, PartialEq, Clone)]
pub struct HandleQueueUpdateOk;
#[derive(Debug, PartialEq, Clone)]
pub struct HandlePlayUpdateError(pub ListSongID);
#[derive(Debug, PartialEq, Clone)]
pub struct HandleSongDownloadProgressUpdate;
#[derive(Debug, PartialEq)]
enum PlaylistEffect {
SetStatusStopped(AllStopped),
StopSongID(Stopped<ListSongID>),
HandleSetSongPlayProgress(ProgressUpdate<ListSongID>),
HandleVolumeUpdate(VolumeUpdate),
HandlePausePlayResponse(PausePlayResponse<ListSongID>),
HandleResumed(ListSongID),
HandlePaused(ListSongID),
HandlePlayUpdate(PlayUpdate<ListSongID>),
HandleQueueUpdate(QueueUpdate<ListSongID>),
HandleAutoplayUpdate(AutoplayUpdate<ListSongID>),
HandleSetToError(ListSongID),
HandleSongDownloadProgressUpdate {
kind: DownloadProgressUpdateType,
id: ListSongID,
},
SetSongThumbnailError(SongThumbnailID<'static>),
AddSongThumbnail(SongThumbnail),
}
impl_youtui_task_handler!(HandleStopped, Stopped<ListSongID>, Playlist, |_, input| {
PlaylistEffect::StopSongID(input)
});
impl_youtui_task_handler!(HandleAllStopped, AllStopped, Playlist, |_, input| {
PlaylistEffect::SetStatusStopped(input)
});
impl_youtui_task_handler!(
HandleSetSongPlayProgress,
ProgressUpdate<ListSongID>,
Playlist,
|_, input| PlaylistEffect::HandleSetSongPlayProgress(input)
);
impl_youtui_task_handler!(HandleVolumeUpdate, VolumeUpdate, Playlist, |_, input| {
PlaylistEffect::HandleVolumeUpdate(input)
});
impl_youtui_task_handler!(
HandlePlayUpdateOk,
PlayUpdate<ListSongID>,
Playlist,
|_, input| PlaylistEffect::HandlePlayUpdate(input)
);
impl_youtui_task_handler!(
HandleQueueUpdateOk,
QueueUpdate<ListSongID>,
Playlist,
|_, input| PlaylistEffect::HandleQueueUpdate(input)
);
impl_youtui_task_handler!(
HandleAutoplayUpdateOk,
AutoplayUpdate<ListSongID>,
Playlist,
|_, input| PlaylistEffect::HandleAutoplayUpdate(input)
);
impl_youtui_task_handler!(
HandlePlayUpdateError,
DecoderError,
Playlist,
|this: HandlePlayUpdateError, input| {
error!("Error {input} received when trying to decode {:?}", this.0);
PlaylistEffect::HandleSetToError(this.0)
}
);
impl_youtui_task_handler!(
HandleSongDownloadProgressUpdate,
DownloadProgressUpdate,
Playlist,
|_, input| {
let DownloadProgressUpdate { kind, id } = input;
PlaylistEffect::HandleSongDownloadProgressUpdate { kind, id }
}
);
impl_youtui_task_handler!(
HandleGetSongThumbnailOk,
SongThumbnail,
Playlist,
|_, input| PlaylistEffect::AddSongThumbnail(input)
);
impl_youtui_task_handler!(
HandleGetSongThumbnailError,
anyhow::Error,
Playlist,
|this: HandleGetSongThumbnailError, input| {
error!("Error {input} getting album art");
PlaylistEffect::SetSongThumbnailError(this.0)
}
);
impl_youtui_task_handler!(
HandlePausePlayResponse,
PausePlayResponse<ListSongID>,
Playlist,
|_, input| PlaylistEffect::HandlePausePlayResponse(input)
);
impl_youtui_task_handler!(
HandleResumeResponse,
Resumed<ListSongID>,
Playlist,
|_, input: Resumed<_>| PlaylistEffect::HandleResumed(input.0)
);
impl_youtui_task_handler!(
HandlePausedResponse,
Paused<ListSongID>,
Playlist,
|_, input: Paused<_>| PlaylistEffect::HandlePaused(input.0)
);
impl FrontendEffect<Playlist, ArcServer, TaskMetadata> for PlaylistEffect {
fn apply(self, target: &mut Playlist) -> impl Into<ComponentEffect<Playlist>> {
match self {
PlaylistEffect::SetStatusStopped(msg) => {
target.handle_all_stopped(msg);
}
PlaylistEffect::StopSongID(msg) => {
target.handle_stopped(msg);
}
PlaylistEffect::HandlePausePlayResponse(msg) => {
match msg {
PausePlayResponse::Paused(id) => target.handle_paused(id),
PausePlayResponse::Resumed(id) => target.handle_resumed(id),
};
}
PlaylistEffect::HandleResumed(msg) => target.handle_resumed(msg),
PlaylistEffect::HandlePaused(msg) => target.handle_paused(msg),
PlaylistEffect::HandleSetSongPlayProgress(msg) => {
return target.handle_set_song_play_progress(msg.duration, msg.identifier);
}
PlaylistEffect::HandleVolumeUpdate(msg) => target.handle_volume_update(msg),
PlaylistEffect::HandleQueueUpdate(msg) => return target.handle_queue_update(msg),
PlaylistEffect::HandlePlayUpdate(msg) => return target.handle_play_update(msg),
PlaylistEffect::HandleAutoplayUpdate(msg) => {
return target.handle_autoplay_update(msg);
}
PlaylistEffect::HandleSetToError(msg) => target.handle_set_to_error(msg),
PlaylistEffect::HandleSongDownloadProgressUpdate { kind, id } => {
return target.handle_song_download_progress_update(kind, id);
}
PlaylistEffect::SetSongThumbnailError(msg) => target.list.set_song_thumbnail_error(msg),
PlaylistEffect::AddSongThumbnail(msg) => target.list.add_song_thumbnail(msg),
}
AsyncTask::new_no_op()
}
}