use super::shared::schema;
use cynic::http::ReqwestExt;
use reqwest::Client;
use crate::api::shared::ApiError;
use cynic::QueryBuilder;
use serde::{Deserialize, Serialize};
use crate::classes::Class;
#[derive(cynic::QueryVariables, Debug)]
struct SpellcastingAbilityQueryVariables {
pub index: Option<String>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "SpellcastingAbilityQueryVariables")]
struct SpellcastingAbilityQuery {
#[arguments(index: $index)]
pub class: Option<ClassSpellCasting>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Class")]
struct ClassSpellCasting {
pub spellcasting: Option<ClassSpellcasting>,
}
#[derive(cynic::QueryFragment, Debug)]
struct ClassSpellcasting {
#[cynic(rename = "spellcasting_ability")]
pub spellcasting_ability: AbilityScore,
}
#[derive(cynic::QueryFragment, Debug)]
struct AbilityScore {
pub index: String,
}
#[derive(cynic::QueryVariables, Debug)]
pub struct SpellcastingQueryVariables {
pub index: Option<String>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "SpellcastingQueryVariables")]
pub struct SpellcastingQuery {
#[arguments(index: $index)]
pub level: Option<Level>,
}
#[derive(cynic::QueryFragment, Debug)]
pub struct Level {
pub spellcasting: Option<LevelSpellcasting>,
}
#[derive(cynic::QueryFragment, Debug, Serialize)]
pub struct LevelSpellcasting {
#[cynic(rename = "cantrips_known")]
pub cantrips_known: Option<i32>,
#[cynic(rename = "spell_slots_level_1")]
pub spell_slots_level_1: Option<i32>,
#[cynic(rename = "spell_slots_level_2")]
pub spell_slots_level_2: Option<i32>,
#[cynic(rename = "spell_slots_level_3")]
pub spell_slots_level_3: Option<i32>,
#[cynic(rename = "spell_slots_level_4")]
pub spell_slots_level_4: Option<i32>,
#[cynic(rename = "spell_slots_level_5")]
pub spell_slots_level_5: Option<i32>,
#[cynic(rename = "spell_slots_level_6")]
pub spell_slots_level_6: Option<i32>,
#[cynic(rename = "spell_slots_level_7")]
pub spell_slots_level_7: Option<i32>,
#[cynic(rename = "spell_slots_level_8")]
pub spell_slots_level_8: Option<i32>,
#[cynic(rename = "spell_slots_level_9")]
pub spell_slots_level_9: Option<i32>,
}
#[derive(cynic::QueryVariables, Debug)]
pub struct LevelFeaturesQueryVariables {
pub class: Option<StringFilter>,
pub level: Option<IntFilter>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "LevelFeaturesQueryVariables")]
pub struct LevelFeaturesQuery {
#[arguments(level: $level, class: $class)]
pub features: Option<Vec<Feature>>,
}
#[derive(cynic::QueryFragment, Debug)]
pub struct Feature {
pub index: String,
}
#[derive(cynic::Scalar, Debug, Clone)]
pub struct IntFilter(pub String);
#[derive(cynic::Scalar, Debug, Clone)]
pub struct StringFilter(pub String);
enum CustomLevelFeature {
}
impl CustomLevelFeature {
pub fn identify(index: String) -> Option<CustomLevelFeature> {
match index.as_str() {
_ => None
}
}
}
impl Class {
pub async fn get_spellcasting_ability_index(&self) -> Result<String, ApiError> {
let op = SpellcastingAbilityQuery::build(SpellcastingAbilityQueryVariables {
index: Some(self.0.clone())
});
let ability_index = Client::new()
.post("https://www.dnd5eapi.co/graphql")
.run_graphql(op).await?
.data.ok_or(ApiError::Schema)?
.class.ok_or(ApiError::Schema)?
.spellcasting.ok_or(ApiError::Schema)?
.spellcasting_ability.index;
Ok(ability_index)
}
pub async fn get_spellcasting_slots(&self) -> Result<LevelSpellcasting, ApiError> {
let op = SpellcastingQuery::build(SpellcastingQueryVariables {
index: Some(format!("{}-{}", self.0, self.1.level))
});
let spellcasting_slots = Client::new()
.post("https://www.dnd5eapi.co/graphql")
.run_graphql(op).await?
.data.ok_or(ApiError::Schema)?
.level.ok_or(ApiError::Schema)?
.spellcasting.ok_or(ApiError::Schema)?;
Ok(spellcasting_slots)
}
pub async fn set_level(&mut self, new_level: u8) -> Result<(), ApiError> {
let op = LevelFeaturesQuery::build(LevelFeaturesQueryVariables {
class: Some(StringFilter(self.0.clone())),
level: Some(IntFilter(format!("{{ gte: {}, lte: {} }}", self.1.level, new_level)))
});
let features = Client::new()
.post("https://www.dnd5eapi.co/graphql")
.run_graphql(op).await?
.data.ok_or(ApiError::Schema)?
.features.ok_or(ApiError::Schema)?;
features.iter().filter_map(|feature| {
CustomLevelFeature::identify(feature.index.clone())
}).for_each(|feature| {
match feature {
}
});
self.1.level = new_level;
Ok(())
}
pub async fn get_levels_features(&self, from_level: Option<u8>) -> Result<Vec<String>, ApiError> {
let op = LevelFeaturesQuery::build(LevelFeaturesQueryVariables {
class: Some(StringFilter(self.0.clone())),
level: Some(IntFilter(format!("{{ gte: {}, lte: {} }}", from_level.unwrap_or(0), self.1.level)))
});
let features = Client::new()
.post("https://www.dnd5eapi.co/graphql")
.run_graphql(op).await?
.data.ok_or(ApiError::Schema)?
.features.ok_or(ApiError::Schema)?;
let features = features.into_iter().filter(|feature| {
CustomLevelFeature::identify(feature.index.clone()).is_none()
}).map(|feature| feature.index).collect();
Ok(features)
}
}