use std::hash::Hash;
use async_trait::async_trait;
use crate::Video;
use tf_observer::{Observable, Observer, ObserverList};
#[derive(Clone)]
pub struct ExpandedVideo<V> {
observers: ObserverList<VideoEvent>,
video: V,
playing: bool,
}
impl<V> PartialEq for ExpandedVideo<V>
where
V: Video,
{
fn eq(&self, other: &Self) -> bool {
self.video.eq(&other.video)
}
}
impl<V> Eq for ExpandedVideo<V> where V: Video {}
impl<V> Hash for ExpandedVideo<V>
where
V: Video,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.video.hash(state);
}
}
impl<V: Video> std::convert::TryFrom<Vec<String>> for ExpandedVideo<V> {
type Error = <V as std::convert::TryFrom<Vec<String>>>::Error;
fn try_from(strings: Vec<String>) -> Result<Self, Self::Error> {
V::try_from(strings).map(|v| ExpandedVideo::from(v))
}
}
impl<V: Video> From<ExpandedVideo<V>> for Vec<String> {
fn from(video: ExpandedVideo<V>) -> Self {
video.video.into()
}
}
#[async_trait]
impl<V: Video> Video for ExpandedVideo<V> {
type Subscription = V::Subscription;
fn url(&self) -> String {
self.video.url()
}
fn title(&self) -> String {
self.video.title()
}
fn uploaded(&self) -> chrono::NaiveDateTime {
self.video.uploaded()
}
fn subscription(&self) -> Self::Subscription {
self.video.subscription()
}
fn thumbnail_url(&self) -> String {
self.video.thumbnail_url()
}
async fn thumbnail_with_client(&self, client: &reqwest::Client) -> image::DynamicImage {
self.video.thumbnail_with_client(client).await
}
}
impl<V> From<V> for ExpandedVideo<V>
where
V: Video,
{
fn from(video: V) -> Self {
ExpandedVideo {
video,
playing: false,
observers: ObserverList::new(),
}
}
}
impl<V: Video> ExpandedVideo<V> {
pub fn play(&mut self) {
self.playing = true;
self.observers.notify(VideoEvent::Play);
}
pub fn stop(&mut self) {
self.playing = false;
self.observers.notify(VideoEvent::Stop);
}
pub fn playing(&self) -> bool {
self.playing
}
pub fn internal(&self) -> V {
self.video.clone()
}
}
#[derive(Clone)]
pub enum VideoEvent {
Play,
Stop,
}
impl<V: Video> Observable<VideoEvent> for ExpandedVideo<V> {
fn attach(
&mut self,
observer: std::sync::Weak<std::sync::Mutex<Box<dyn Observer<VideoEvent> + Send>>>,
) {
self.observers.attach(observer)
}
fn detach(
&mut self,
observer: std::sync::Weak<std::sync::Mutex<Box<dyn Observer<VideoEvent> + Send>>>,
) {
self.observers.detach(observer)
}
}