use std::cmp::Ordering;
use std::convert::TryFrom;
use arrayvec::ArrayVec;
use compact_str::CompactString;
use crate::genre::Genre;
use crate::EpisodeLink;
use crate::Error;
use crate::Title;
use crate::TitleType;
#[derive(Eq, PartialEq)]
pub struct Show {
pub imdb_id: u32,
pub title: CompactString,
pub is_adult: bool,
pub start_year: u16,
pub end_year: Option<u16>,
pub runtime_minutes: Option<u16>,
pub genres: ArrayVec<Genre, 3>,
pub episodes: Vec<Episode>
}
impl std::fmt::Debug for Show {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Show")
.field("imdb_id", &self.imdb_id)
.field("title", &self.title)
.field("is_adult", &self.is_adult)
.field("start_year", &self.start_year)
.field("end_year", &self.end_year)
.field("runtime_minutes", &self.runtime_minutes)
.field("genres", &self.genres)
.field("episodes", &self.episodes.len())
.finish()
}
}
impl Show {
pub(crate) fn from_wrapped_title(input: Result<Title, Error>) -> Result<Self, Error> {
Self::try_from(input?)
} }
impl TryFrom<Title> for Show {
type Error = Error;
#[inline]
fn try_from(input: Title) -> Result<Self, Error> {
match input.title_type {
TitleType::TVSeries => Ok(Self{
imdb_id: input.imdb_id,
title: input.primary_title,
is_adult: input.is_adult,
start_year: match input.start_year {
Some(v) => v,
None => return Err(Error::YearMissing)
},
end_year: input.end_year,
runtime_minutes: input.runtime_minutes,
genres: input.genres,
episodes: Vec::new()
}),
_ => Err(Error::WrongMediaType(input.title_type.into(), "Show"))
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Episode {
pub season: u16,
pub episode: u16,
pub imdb_id: u32,
pub title: CompactString,
pub year: Option<u16>,
pub runtime_minutes: Option<u16>
}
impl PartialOrd for Episode {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Episode {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
match self.season.cmp(&other.season) {
Ordering::Equal => self.episode.cmp(&other.episode),
v => v
}
}
}
impl Episode {
#[cfg(test)]
pub(crate) fn new(season: u16, episode: u16, imdb_id: u32, title: &str, year: Option<u16>, runtime_minutes: Option<u16>) -> Self {
Self{
season,
episode,
imdb_id,
title: CompactString::new(title),
year,
runtime_minutes
}
}
#[inline]
pub(crate) fn from_title_and_link(title: Title, link: EpisodeLink) -> Result<Self, Error> {
match title.title_type {
TitleType::Episode => Ok(Self{
season: match link.season {
Some(v) => v,
None => return Err(Error::SeasonMissing)
},
episode: match link.episode {
Some(v) => v,
None => return Err(Error::EpisodeMissing)
},
imdb_id: title.imdb_id,
title: title.primary_title,
year: title.start_year,
runtime_minutes: title.runtime_minutes
}),
_ => Err(Error::WrongMediaType(title.title_type.into(), "Episode"))
}
} }
#[inline]
pub(crate) fn title_matches_show_name_and_year(title: &Result<Title, Error>, name: &str, year: u16) -> bool {
if let Ok(title) = title {
if(title.title_type != TitleType::TVSeries) {
return false;
}
if let Some(title_year) = title.start_year {
if(title_year != year) {
return false;
}
} else {
return false;
}
if(title.primary_title != name && title.original_title != name) {
return false;
}
return true;
}
false
}