use serde::Serialize;
use std::collections::HashMap;
use crate::client::AnkiClient;
use crate::error::Result;
use crate::types::{
CardTemplate, CreateModelParams, FieldFont, FieldsOnTemplates, FindReplaceParams, ModelStyling,
};
#[derive(Debug)]
pub struct ModelActions<'a> {
pub(crate) client: &'a AnkiClient,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct ModelNameParams<'a> {
model_name: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct RenameFieldParams<'a> {
model_name: &'a str,
old_field_name: &'a str,
new_field_name: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct RepositionFieldParams<'a> {
model_name: &'a str,
field_name: &'a str,
index: i32,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct AddFieldParams<'a> {
model_name: &'a str,
field_name: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
index: Option<i32>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct RemoveFieldParams<'a> {
model_name: &'a str,
field_name: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct SetFieldFontParams<'a> {
model_name: &'a str,
field_name: &'a str,
font: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct SetFieldSizeParams<'a> {
model_name: &'a str,
field_name: &'a str,
font_size: i32,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct SetFieldDescriptionParams<'a> {
model_name: &'a str,
field_name: &'a str,
description: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct FindModelsByIdParams<'a> {
model_ids: &'a [i64],
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct FindModelsByNameParams<'a> {
model_names: &'a [&'a str],
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateRenameParams<'a> {
model_name: &'a str,
old_template_name: &'a str,
new_template_name: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateRepositionParams<'a> {
model_name: &'a str,
template_name: &'a str,
index: i32,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateAddParams<'a> {
model_name: &'a str,
template: TemplateAddInner<'a>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateAddInner<'a> {
#[serde(rename = "Name")]
name: &'a str,
#[serde(rename = "Front")]
front: &'a str,
#[serde(rename = "Back")]
back: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateRemoveParams<'a> {
model_name: &'a str,
template_name: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdateStylingParams<'a> {
model: UpdateStylingModel<'a>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdateStylingModel<'a> {
name: &'a str,
css: &'a str,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdateTemplatesParams<'a> {
model: UpdateTemplatesModel<'a>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdateTemplatesModel<'a> {
name: &'a str,
templates: HashMap<&'a str, TemplateContent<'a>>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct TemplateContent<'a> {
#[serde(rename = "Front")]
front: &'a str,
#[serde(rename = "Back")]
back: &'a str,
}
impl<'a> ModelActions<'a> {
pub async fn names(&self) -> Result<Vec<String>> {
self.client.invoke_without_params("modelNames").await
}
pub async fn names_and_ids(&self) -> Result<HashMap<String, i64>> {
self.client.invoke_without_params("modelNamesAndIds").await
}
pub async fn field_names(&self, model_name: &str) -> Result<Vec<String>> {
self.client
.invoke("modelFieldNames", ModelNameParams { model_name })
.await
}
pub async fn field_descriptions(&self, model_name: &str) -> Result<HashMap<String, String>> {
self.client
.invoke("modelFieldDescriptions", ModelNameParams { model_name })
.await
}
pub async fn field_fonts(&self, model_name: &str) -> Result<HashMap<String, FieldFont>> {
self.client
.invoke("modelFieldFonts", ModelNameParams { model_name })
.await
}
pub async fn fields_on_templates(&self, model_name: &str) -> Result<FieldsOnTemplates> {
self.client
.invoke("modelFieldsOnTemplates", ModelNameParams { model_name })
.await
}
pub async fn create(&self, params: CreateModelParams) -> Result<serde_json::Value> {
self.client.invoke("createModel", params).await
}
pub async fn templates(&self, model_name: &str) -> Result<HashMap<String, CardTemplate>> {
self.client
.invoke("modelTemplates", ModelNameParams { model_name })
.await
}
pub async fn styling(&self, model_name: &str) -> Result<ModelStyling> {
self.client
.invoke("modelStyling", ModelNameParams { model_name })
.await
}
pub async fn update_templates(
&self,
model_name: &str,
templates: HashMap<&str, (&str, &str)>,
) -> Result<()> {
let template_map: HashMap<&str, TemplateContent> = templates
.into_iter()
.map(|(name, (front, back))| (name, TemplateContent { front, back }))
.collect();
self.client
.invoke_void(
"updateModelTemplates",
UpdateTemplatesParams {
model: UpdateTemplatesModel {
name: model_name,
templates: template_map,
},
},
)
.await
}
pub async fn update_styling(&self, model_name: &str, css: &str) -> Result<()> {
self.client
.invoke_void(
"updateModelStyling",
UpdateStylingParams {
model: UpdateStylingModel {
name: model_name,
css,
},
},
)
.await
}
pub async fn find_and_replace(&self, params: FindReplaceParams) -> Result<i64> {
self.client.invoke("findAndReplaceInModels", params).await
}
pub async fn rename_field(
&self,
model_name: &str,
old_name: &str,
new_name: &str,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldRename",
RenameFieldParams {
model_name,
old_field_name: old_name,
new_field_name: new_name,
},
)
.await
}
pub async fn reposition_field(
&self,
model_name: &str,
field_name: &str,
index: i32,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldReposition",
RepositionFieldParams {
model_name,
field_name,
index,
},
)
.await
}
pub async fn add_field(
&self,
model_name: &str,
field_name: &str,
index: Option<i32>,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldAdd",
AddFieldParams {
model_name,
field_name,
index,
},
)
.await
}
pub async fn remove_field(&self, model_name: &str, field_name: &str) -> Result<()> {
self.client
.invoke_void(
"modelFieldRemove",
RemoveFieldParams {
model_name,
field_name,
},
)
.await
}
pub async fn set_field_font(
&self,
model_name: &str,
field_name: &str,
font: &str,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldSetFont",
SetFieldFontParams {
model_name,
field_name,
font,
},
)
.await
}
pub async fn set_field_font_size(
&self,
model_name: &str,
field_name: &str,
size: i32,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldSetFontSize",
SetFieldSizeParams {
model_name,
field_name,
font_size: size,
},
)
.await
}
pub async fn set_field_description(
&self,
model_name: &str,
field_name: &str,
description: &str,
) -> Result<()> {
self.client
.invoke_void(
"modelFieldSetDescription",
SetFieldDescriptionParams {
model_name,
field_name,
description,
},
)
.await
}
pub async fn find_by_id(&self, model_ids: &[i64]) -> Result<Vec<serde_json::Value>> {
self.client
.invoke("findModelsById", FindModelsByIdParams { model_ids })
.await
}
pub async fn find_by_name(&self, model_names: &[&str]) -> Result<Vec<serde_json::Value>> {
self.client
.invoke("findModelsByName", FindModelsByNameParams { model_names })
.await
}
pub async fn rename_template(
&self,
model_name: &str,
old_name: &str,
new_name: &str,
) -> Result<()> {
self.client
.invoke_void(
"modelTemplateRename",
TemplateRenameParams {
model_name,
old_template_name: old_name,
new_template_name: new_name,
},
)
.await
}
pub async fn reposition_template(
&self,
model_name: &str,
template_name: &str,
index: i32,
) -> Result<()> {
self.client
.invoke_void(
"modelTemplateReposition",
TemplateRepositionParams {
model_name,
template_name,
index,
},
)
.await
}
pub async fn add_template(
&self,
model_name: &str,
template_name: &str,
front: &str,
back: &str,
) -> Result<()> {
self.client
.invoke_void(
"modelTemplateAdd",
TemplateAddParams {
model_name,
template: TemplateAddInner {
name: template_name,
front,
back,
},
},
)
.await
}
pub async fn remove_template(&self, model_name: &str, template_name: &str) -> Result<()> {
self.client
.invoke_void(
"modelTemplateRemove",
TemplateRemoveParams {
model_name,
template_name,
},
)
.await
}
}