use crate::error::FormsError;
use crate::pdf::{checkbox_on, collect_fields, load, text_value};
use std::collections::BTreeMap;
use toml::Value;
pub fn extract_lines(pdf: &[u8], map_toml: &str) -> Result<BTreeMap<String, String>, FormsError> {
let map: Value = map_toml.parse()?;
let doc = load(pdf)?;
let fields = collect_fields(&doc)?;
let by_name: BTreeMap<&str, _> = fields.iter().map(|f| (f.fqn.as_str(), f)).collect();
let mut out = BTreeMap::new();
walk(&map, "", &by_name, &doc, &mut out);
Ok(out)
}
fn walk(
node: &Value,
prefix: &str,
by_name: &BTreeMap<&str, &crate::pdf::Field>,
doc: &lopdf::Document,
out: &mut BTreeMap<String, String>,
) {
match node {
Value::String(fqn) => {
if let Some(f) = by_name.get(fqn.as_str()) {
if let Some(v) = text_value(doc, f.id) {
if !v.trim().is_empty() {
out.insert(prefix.to_string(), v);
}
}
}
}
Value::Table(t) if t.contains_key("field") => {
let Some(Value::String(fqn)) = t.get("field") else {
return;
};
if let Some(f) = by_name.get(fqn.as_str()) {
if let Some(on) = checkbox_on(doc, f.id) {
out.insert(prefix.to_string(), on);
}
}
}
Value::Table(t) => {
for (k, v) in t {
let key = if prefix.is_empty() {
k.clone()
} else {
format!("{prefix}.{k}")
};
walk(v, &key, by_name, doc, out);
}
}
Value::Array(a) => {
for (i, v) in a.iter().enumerate() {
walk(v, &format!("{prefix}[{i}]"), by_name, doc, out);
}
}
_ => {}
}
}