use std::env;
use std::fmt::{self, Display, Formatter};
use std::fs::OpenOptions;
use anyhow::{Result, anyhow};
use constcat::concat;
use crate::model::Message;
use crate::model::mua::NEOMUTT_XDG_CONFIG_DIR;
const QUEUE_FILE: &str = concat!(NEOMUTT_XDG_CONFIG_DIR, "/.midnight");
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct Record {
pub id: String,
pub msg: Message,
}
impl Record {
pub fn new(id: String, msg: Message) -> Record {
Record { id, msg }
}
pub fn write(&self) -> Result<()> {
let writer = OpenOptions::new()
.write(true)
.create(true)
.append(true)
.open(Self::queue_file()?)?;
let mut writer = csv::WriterBuilder::new()
.has_headers(false)
.from_writer(writer);
writer.serialize(self)?;
writer.flush()?;
Ok(())
}
pub fn read() -> Result<Vec<Self>> {
let mut reader = csv::ReaderBuilder::new()
.has_headers(false)
.from_path(Self::queue_file()?)?;
let mut records = vec![];
for record in reader.deserialize() {
records.push(record?);
}
Ok(records)
}
pub fn find(id: String) -> Result<Self> {
let rcds = Record::read()?;
let matching = rcds
.iter()
.filter(|rcd| rcd.msg.id == id)
.collect::<Vec<&Record>>();
if let Some(rcd) = matching.first() {
return Ok(rcd.to_owned().to_owned());
}
Err(anyhow!(
"No matching record found in queue file for ID: {}",
id
))
}
pub fn clear() -> Result<()> {
OpenOptions::new()
.write(true)
.truncate(true)
.open(Self::queue_file()?)?;
Ok(())
}
fn queue_file() -> Result<String> {
Ok(String::from(format!(
"{}/{}",
env::var("HOME")?,
QUEUE_FILE
)))
}
}
impl Display for Record {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"[{}] {}\nFrom: {} <{}>\nTo: {} <{}>\nAt: {}",
self.id,
self.msg.subject,
self.msg.sender,
self.msg.sender_addr,
self.msg.recipient,
self.msg.recipient_addr,
self.msg.at
)
}
}