complish 0.0.1

Core library for project-aware task management with git integration
Documentation
use eyre::{Result, eyre};

use crate::{Project, Vault};

pub struct ProjectBuilder<'a> {
  project: Project,
  vault: &'a mut Vault,
}

impl<'a> ProjectBuilder<'a> {
  pub fn new(vault: &'a mut Vault, name: impl Into<String>) -> Self {
    let id = vault.index.peek_next_canonical_project_id();
    let project = Project::new(id, name);

    Self {
      project,
      vault,
    }
  }

  pub fn create(&mut self) -> Result<Project> {
    self.project.id = self.vault.index.allocate_canonical_project_id();
    self
      .vault
      .projects
      .insert(self.project.id, self.project.clone());

    self
      .vault
      .index
      .project_key_to_canonical_id
      .entry(self.project.key.clone())
      .or_default()
      .push(self.project.id);

    self.vault.save()?;
    Ok(self.project.clone())
  }

  pub fn with_description(mut self, description: impl Into<String>) -> Self {
    self.project.description = Some(description.into());
    self
  }

  pub fn with_key(mut self, key: impl Into<String>) -> Result<Self> {
    let key = key.into();

    if self
      .vault
      .index
      .project_key_to_canonical_id
      .contains_key(&key)
    {
      let existing: &Vec<u32> = self.vault.index.project_key_to_canonical_id[&key].as_ref();
      for id in existing {
        let proj = self.vault.projects[id].clone();
        if !proj.is_complete() {
          return Err(eyre!("Project with key {} already exists", &key));
        }
      }
    }

    self.project.key = key;
    Ok(self)
  }
}