use eyre::{Result, eyre};
use crate::{Task, TaskPriority, Vault};
pub struct TaskBuilder<'a> {
list_name: String,
project_id: Option<u32>,
task: Task,
vault: &'a mut Vault,
}
impl<'a> TaskBuilder<'a> {
pub fn new(vault: &'a mut Vault, subject: impl Into<String>) -> Self {
let canonical_id = &vault.index.peek_next_canonical_id();
let friendly_id = &format!("{}", &vault.index.peek_next_friendly_id_by_default());
let task = Task::new(*canonical_id, friendly_id, subject);
Self {
list_name: String::from("someday"),
project_id: None,
task,
vault,
}
}
pub fn create(&mut self) -> Result<Task> {
self.task.id = self.vault.index.allocate_canonical_id();
if self.project_id.is_none() {
self.task.friendly_id = format!("{}", self.vault.index.allocate_friendly_id_for_default());
} else {
self.task.friendly_id = format!(
"{}",
self
.vault
.index
.allocate_friendly_id_for_project(self.project_id.unwrap())
);
let project = self
.vault
.projects
.get_mut(&self.project_id.unwrap())
.unwrap();
project.task_ids.push(self.task.id);
}
self
.vault
.index
.register_task(&self.task, &self.list_name, self.project_id);
self.vault.tasks.insert(self.task.id, self.task.clone());
let list = self.vault.task_lists.get_mut(&self.list_name).unwrap();
list.task_ids.push(self.task.id);
self.vault.save()?;
Ok(self.task.clone())
}
pub fn for_project(mut self, project_key: impl Into<String>) -> Result<Self> {
let key = project_key.into();
let project_id = self
.vault
.index
.get_canonical_project_id_from_key(&key)
.ok_or_else(|| eyre!("Project with key '{}' not found", key))?;
let next_project_id = self
.vault
.index
.peek_next_friendly_id_by_project(project_id);
self.task.friendly_id = format!("{}-{}", &key, &next_project_id);
self.project_id = Some(project_id);
Ok(self)
}
pub fn in_list(mut self, list_name: impl Into<String>) -> Result<Self> {
self.list_name = list_name.into();
if !self.vault.task_lists.contains_key(&self.list_name) {
return Err(eyre!(
"List '{}' not found. Must be one of: {}",
self.list_name,
self
.vault
.task_lists
.keys()
.map(String::as_str)
.collect::<Vec<_>>()
.join(", ")
));
}
Ok(self)
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.task.description = Some(description.into());
self
}
pub fn with_priority(mut self, priority: TaskPriority) -> Self {
self.task.priority = priority;
self
}
}