use super::ToDo;
use crate::config::{TaskSort, ToDoConfig};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use todo_txt::task::Simple as Task;
#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
pub enum ToDoData {
Pending,
Done,
}
impl ToDoData {
pub fn get_data<'a>(&self, todo: &'a ToDo) -> &'a Vec<Task> {
match self {
Self::Pending => &todo.pending,
Self::Done => &todo.done,
}
}
pub fn get_data_mut<'a>(&self, todo: &'a mut ToDo) -> &'a mut Vec<Task> {
todo.version.update(self);
match self {
Self::Pending => &mut todo.pending,
Self::Done => &mut todo.done,
}
}
pub fn get_sorting<'a>(&self, config: &'a ToDoConfig) -> &'a [TaskSort] {
use ToDoData::*;
match self {
Pending => &config.pending_sort,
Done => &config.done_sort,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToDoCategory {
Projects,
Contexts,
Hashtags,
}
impl ToDoCategory {
pub fn get_data<'a>(&self, task: &'a Task) -> &'a [String] {
use ToDoCategory::*;
match self {
Projects => &task.projects,
Contexts => &task.contexts,
Hashtags => &task.hashtags,
}
}
pub fn get_all() -> &'static [ToDoCategory] {
use ToDoCategory::*;
static ALL_CATEGORIES: [ToDoCategory; 3] = [Projects, Contexts, Hashtags];
&ALL_CATEGORIES
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
pub enum FilterState {
Select,
Remove,
}
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct ToDoState {
pub active: Option<(ToDoData, usize)>,
pub actual_pending: Option<usize>,
pub actual_done: Option<usize>,
pub project_filters: BTreeMap<String, FilterState>,
pub context_filters: BTreeMap<String, FilterState>,
pub hashtag_filters: BTreeMap<String, FilterState>,
}
impl ToDoState {
pub fn get_category(&self, category: ToDoCategory) -> &BTreeMap<String, FilterState> {
use ToDoCategory::*;
match category {
Projects => &self.project_filters,
Contexts => &self.context_filters,
Hashtags => &self.hashtag_filters,
}
}
pub fn get_mut_category(
&mut self,
category: ToDoCategory,
) -> &mut BTreeMap<String, FilterState> {
use ToDoCategory::*;
match category {
Projects => &mut self.project_filters,
Contexts => &mut self.context_filters,
Hashtags => &mut self.hashtag_filters,
}
}
pub fn filter_out(&self, task: &Task) -> bool {
fn filter(category: &BTreeMap<String, FilterState>, task_categories: &[String]) -> bool {
category.iter().all(|(category, state)| {
let contains = task_categories.contains(category);
match state {
FilterState::Select => contains,
FilterState::Remove => !contains,
}
})
}
filter(&self.project_filters, &task.projects)
&& filter(&self.context_filters, &task.contexts)
&& filter(&self.hashtag_filters, &task.hashtags)
}
pub fn set_filter(&mut self, category: ToDoCategory, filter: &str, filter_state: FilterState) {
let category = self.get_mut_category(category);
match category.get_mut(filter) {
Some(a) => {
if filter_state == *a {
category.remove(filter);
} else {
*a = filter_state;
}
}
None => {
category.insert(filter.to_owned(), filter_state);
}
}
}
}