use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;
use filters::filter::Filter;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::storeid::StoreId;
use crate::is_in_diary::IsInDiary;
use failure::Fallible as Result;
use failure::err_msg;
pub struct DiaryEntryIterator {
name: String,
iter: StoreIdIterator,
year: Option<i32>,
month: Option<u32>,
day: Option<u32>,
}
impl Debug for DiaryEntryIterator {
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
write!(fmt, "DiaryEntryIterator<name = {}, year = {:?}, month = {:?}, day = {:?}>",
self.name, self.year, self.month, self.day)
}
}
impl DiaryEntryIterator {
pub fn new(diaryname: String, iter: StoreIdIterator) -> DiaryEntryIterator {
DiaryEntryIterator {
name: diaryname,
iter,
year: None,
month: None,
day: None,
}
}
pub fn year(mut self, year: i32) -> DiaryEntryIterator {
self.year = Some(year);
self
}
pub fn month(mut self, month: u32) -> DiaryEntryIterator {
self.month = Some(month);
self
}
pub fn day(mut self, day: u32) -> DiaryEntryIterator {
self.day = Some(day);
self
}
}
impl Filter<StoreId> for DiaryEntryIterator {
fn filter(&self, id: &StoreId) -> bool {
if id.is_in_diary(&self.name) {
match (self.year, self.month, self.day) {
(None , None , None) => true,
(Some(y) , None , None) => id.is_in_collection(&[&self.name, &y.to_string()]),
(Some(y) , Some(m) , None) => id.is_in_collection(&[&self.name, &y.to_string(), &m.to_string()]),
(Some(y) , Some(m) , Some(d)) => id.is_in_collection(&[&self.name, &y.to_string(), &m.to_string(), &d.to_string()]),
(None , Some(_) , Some(_)) => false ,
(None , None , Some(_)) => false ,
(None , Some(_) , None) => false ,
(Some(_) , None , Some(_)) => false ,
}
} else {
false
}
}
}
impl Iterator for DiaryEntryIterator {
type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.iter.next() {
None => return None,
Some(Err(e)) => return Some(Err(e)),
Some(Ok(s)) => {
debug!("Next element: {:?}", s);
if Filter::filter(self, &s) {
return Some(Ok(s))
} else {
continue
}
},
}
}
}
}
pub struct DiaryNameIterator(StoreIdIterator);
impl DiaryNameIterator {
pub fn new(s: StoreIdIterator) -> DiaryNameIterator {
DiaryNameIterator(s)
}
}
impl Iterator for DiaryNameIterator {
type Item = Result<String>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.0.next() {
match next {
Err(e) => return Some(Err(e)),
Ok(next) => if next.is_in_collection(&["diary"]) {
return Some(next
.to_str()
.and_then(|s| {
s.split("diary/")
.nth(1)
.and_then(|n| n.split('/').nth(0).map(String::from))
.ok_or_else(|| err_msg("Error finding diary name"))
}));
},
}
}
None
}
}