use imap::extensions::list_status::ExtendedNames;
use std::collections::BTreeMap;
use thiserror::Error;
use vomit::VomitError;
use crate::state::{self, StateError, SyncState};
#[derive(Error, Debug)]
pub enum MailboxesError {
#[error("error loading local mailboxes: {0}")]
VomitError(#[from] VomitError),
#[error("error loading mailbox state: {0}")]
StateError(#[from] StateError),
}
#[derive(Debug)]
pub enum SyncAction {
Sync,
CreateLocal,
CreateRemote,
DeleteLocal,
DeleteRemote,
}
pub struct SyncJob {
pub name: String,
pub delimiter: String,
pub action: SyncAction,
}
pub(crate) fn load_local(
path: &str,
delimiter: &str,
) -> Result<BTreeMap<String, SyncState>, MailboxesError> {
vomit::load_mailboxes(path, false, false)?
.into_iter()
.map(|mb| {
let name = mb.imap_name(delimiter);
let state = SyncState::load(&mb.abs_path())?;
Ok((name, state))
})
.collect::<Result<BTreeMap<_, _>, _>>()
}
pub fn load_remote(names: &ExtendedNames) -> BTreeMap<String, u64> {
names
.iter()
.map(|name| {
let modseq = name
.1
.as_ref()
.map(|mb| mb.highest_mod_seq.unwrap_or(0))
.unwrap_or(0);
(String::from(name.0.name()), modseq)
})
.collect()
}
pub(crate) fn sync_create_local(name: String, delimiter: String) -> Option<SyncJob> {
Some(SyncJob {
name,
delimiter,
action: SyncAction::CreateLocal,
})
}
pub(crate) fn sync_delete_local(name: String, delimiter: String) -> Option<SyncJob> {
Some(SyncJob {
name,
delimiter,
action: SyncAction::DeleteLocal,
})
}
pub(crate) fn sync_create_remote(name: String, delimiter: String) -> Option<SyncJob> {
Some(SyncJob {
name,
delimiter,
action: SyncAction::CreateRemote,
})
}
pub(crate) fn sync_delete_remote(name: String, delimiter: String) -> Option<SyncJob> {
Some(SyncJob {
name,
delimiter,
action: SyncAction::DeleteRemote,
})
}
pub fn sync(name: String, delimiter: String) -> Option<SyncJob> {
Some(SyncJob {
name,
delimiter,
action: SyncAction::Sync,
})
}
pub(crate) fn sync_done(job: SyncJob, state: &mut state::RootState) {
let dirname = vomit::Mailbox::virtual_to_dir(&job.name, &job.delimiter);
match job.action {
SyncAction::CreateLocal | SyncAction::CreateRemote => state.subdirs.insert(dirname),
SyncAction::DeleteLocal | SyncAction::DeleteRemote => state.subdirs.remove(&dirname),
SyncAction::Sync => state.subdirs.insert(dirname),
};
}