use crate::cells::{push_identity, push_money};
use crate::error::FormsError;
use crate::map::ScheduleSeMap;
use crate::pdf;
use crate::verify::{verify_flat, FlatPlacement};
use btctax_core::tax::packet::ReturnHeader;
use btctax_core::tax::printed::ScheduleSeLines;
use btctax_core::Usd;
const SE_COL_MID: usize = 0;
const SE_COL_AMOUNT: usize = 1;
const SE_CLUSTERS: &[(f32, f32)] = &[(410.0, 482.0), (504.0, 576.0)];
pub fn fill_schedule_se_full_with_map(
lines: &ScheduleSeLines,
header: &ReturnHeader,
map: &ScheduleSeMap,
) -> Result<Vec<u8>, FormsError> {
let mut doc = pdf::load(pdf::schedule_se_pdf(map.year)?)?;
let blank_fields = pdf::collect_fields(&doc)?;
let mut writes: Vec<(String, pdf::FieldValue)> = Vec::new();
let mut placements: Vec<FlatPlacement> = Vec::new();
let identity = map.identity.as_ref().ok_or_else(|| {
FormsError::Geometry(format!(
"the {} Schedule SE map has no [identity] block — a full return cannot file an unnamed \
Schedule SE",
map.year
))
})?;
let proprietor = header.proprietor.as_ref().ok_or_else(|| {
FormsError::Geometry(
"Schedule SE has no proprietor — the return names no one with self-employment income"
.into(),
)
})?;
push_identity(
&mut writes,
&mut placements,
identity,
&proprietor.full_name(),
&proprietor.ssn,
&blank_fields,
)?;
let skip_8d_to_10 = lines.line9 == Usd::ZERO;
let plan: [(Usd, usize, bool); 12] = [
(lines.line2, SE_COL_AMOUNT, true), (lines.line3, SE_COL_AMOUNT, true), (lines.line4a, SE_COL_AMOUNT, true), (lines.line4c, SE_COL_AMOUNT, true), (lines.line6, SE_COL_AMOUNT, true), (lines.line8a, SE_COL_MID, true), (lines.line8d, SE_COL_AMOUNT, !skip_8d_to_10), (lines.line9, SE_COL_AMOUNT, !skip_8d_to_10), (lines.line10, SE_COL_AMOUNT, !skip_8d_to_10), (lines.line11, SE_COL_AMOUNT, true), (lines.line12, SE_COL_AMOUNT, true), (lines.line13, SE_COL_MID, true), ];
for (ord, (cell, (value, col, include))) in map.lines().iter().zip(plan).enumerate() {
if !include {
continue;
}
push_money(
&mut writes,
&mut placements,
cell,
value,
col,
Some((0, ord as u32)),
);
}
for fqn in &map.prefilled_exempt {
placements.push(FlatPlacement::free(fqn.clone(), crate::cells::page_of(fqn)));
}
let index = pdf::index(&blank_fields);
pdf::drop_xfa_and_set_needappearances(&mut doc)?;
pdf::apply_writes(&mut doc, &index, &writes)?;
pdf::strip_nondeterminism(&mut doc);
let bytes = pdf::save(&mut doc)?;
let check = pdf::load(&bytes)?;
let fields = pdf::collect_fields(&check)?;
verify_flat(&check, &fields, &placements, SE_CLUSTERS)?;
Ok(bytes)
}