use serde::{Deserialize, Serialize};
use serde_json::Value;
use super::{Anime, Cover, Format, Manga, Media, Status, Title};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Relation {
pub(crate) node: Value,
pub id: i64,
pub relation_type: RelationType,
pub is_main_studio: bool,
}
impl Relation {
pub fn media(&self) -> Media {
let media = self.node.clone();
match self.node["type"].as_str() {
Some("ANIME") => Media::Anime(Anime {
id: media["id"].as_i64().unwrap(),
id_mal: media["idMal"].as_i64(),
title: Title::deserialize(&media["title"]).unwrap(),
format: Format::deserialize(&media["format"]).unwrap(),
status: Status::deserialize(&media["status"]).unwrap(),
description: media["description"].as_str().unwrap().to_string(),
cover: Cover::deserialize(&media["coverImage"]).unwrap(),
banner: media["bannerImage"].as_str().map(String::from),
average_score: media["averageScore"].as_u64().map(|x| x as u8),
mean_score: media["meanScore"].as_u64().map(|x| x as u8),
url: media["siteUrl"].as_str().unwrap().to_string(),
..Default::default()
}),
Some("MANGA") => Media::Manga(Manga {
id: media["id"].as_i64().unwrap(),
id_mal: media["idMal"].as_i64(),
title: Title::deserialize(&media["title"]).unwrap(),
format: Format::deserialize(&media["format"]).unwrap(),
status: Status::deserialize(&media["status"]).unwrap(),
description: media["description"].as_str().unwrap().to_string(),
cover: Cover::deserialize(&media["coverImage"]).unwrap(),
banner: media["bannerImage"].as_str().map(String::from),
average_score: media["averageScore"].as_u64().map(|x| x as u8),
mean_score: media["meanScore"].as_u64().map(|x| x as u8),
url: media["siteUrl"].as_str().unwrap().to_string(),
..Default::default()
}),
_ => Media::Unknown,
}
}
}
#[derive(Debug, Default, Clone, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[serde(rename_all(deserialize = "SCREAMING_SNAKE_CASE"))]
pub enum RelationType {
Adaptation,
Prequel,
Sequel,
Parent,
SideStory,
Character,
Summary,
Alternative,
SpinOff,
#[default]
Other,
Source,
Compilation,
Contains,
}
impl RelationType {
pub fn summary(&self) -> &str {
match self {
RelationType::Adaptation => "An adaption of this media into a different format",
RelationType::Prequel => "Released before the relation",
RelationType::Sequel => "Released after the relation",
RelationType::Parent => "The media a side story is from",
RelationType::SideStory => "A side story of the parent media",
RelationType::Character => "Shares at least 1 character",
RelationType::Summary => "A shortened and summarized version",
RelationType::Alternative => "An alternative version of the same media",
RelationType::SpinOff => {
"An alternative version of the media with a different primary focus"
}
RelationType::Other => "Other",
RelationType::Source => "The source material the media was adapted from",
RelationType::Compilation => "A compilation of the media",
RelationType::Contains => "A media that contains the relation",
}
}
}