use super::directives::{comment_else, comment_endif, comment_if};
use super::dom::{DomNode, parse_html};
use super::tree_diff::{DiffOp, diff_children};
use super::variant::find_pair_for_axis;
use super::{Axis, content_indices};
pub(super) fn insert_boolean_directives(
tree: &[DomNode],
a_nodes: &[DomNode],
b_nodes: &[DomNode],
path: &str,
) -> Vec<DomNode> {
let ops = diff_children(a_nodes, b_nodes);
let content_map = content_indices(tree);
let mut result = Vec::new();
let mut tree_content_idx = 0usize; let mut tree_pos = 0usize;
fn copy_leading_directives(
tree: &[DomNode],
tree_pos: &mut usize,
content_map: &[usize],
tree_content_idx: usize,
result: &mut Vec<DomNode>,
) {
let target =
if tree_content_idx < content_map.len() { content_map[tree_content_idx] } else { tree.len() };
while *tree_pos < target {
result.push(tree[*tree_pos].clone());
*tree_pos += 1;
}
}
let mut op_idx = 0;
while op_idx < ops.len() {
match &ops[op_idx] {
DiffOp::Identical(_, _) => {
copy_leading_directives(tree, &mut tree_pos, &content_map, tree_content_idx, &mut result);
result.push(tree[tree_pos].clone());
tree_pos += 1;
tree_content_idx += 1;
op_idx += 1;
}
DiffOp::Modified(ai, bi) => {
copy_leading_directives(tree, &mut tree_pos, &content_map, tree_content_idx, &mut result);
match (&tree[tree_pos], &a_nodes[*ai], &b_nodes[*bi]) {
(
DomNode::Element { tag, attrs, children: tc, self_closing },
DomNode::Element { attrs: aa, children: ac, .. },
DomNode::Element { attrs: ab, children: bc, .. },
) if aa == ab => {
let merged = insert_boolean_directives(tc, ac, bc, path);
result.push(DomNode::Element {
tag: tag.clone(),
attrs: attrs.clone(),
children: merged,
self_closing: *self_closing,
});
}
_ => {
result.push(comment_if(path));
result.push(tree[tree_pos].clone());
result.push(comment_else());
result.push(b_nodes[*bi].clone());
result.push(comment_endif(path));
}
}
tree_pos += 1;
tree_content_idx += 1;
op_idx += 1;
}
DiffOp::OnlyLeft(_ai) => {
copy_leading_directives(tree, &mut tree_pos, &content_map, tree_content_idx, &mut result);
if op_idx + 1 < ops.len()
&& let DiffOp::OnlyRight(bi) = &ops[op_idx + 1]
{
result.push(comment_if(path));
result.push(tree[tree_pos].clone());
result.push(comment_else());
result.push(b_nodes[*bi].clone());
result.push(comment_endif(path));
tree_pos += 1;
tree_content_idx += 1;
op_idx += 2;
continue;
}
result.push(comment_if(path));
result.push(tree[tree_pos].clone());
result.push(comment_endif(path));
tree_pos += 1;
tree_content_idx += 1;
op_idx += 1;
}
DiffOp::OnlyRight(bi) => {
copy_leading_directives(tree, &mut tree_pos, &content_map, tree_content_idx, &mut result);
result.push(comment_if(path));
result.push(comment_else());
result.push(b_nodes[*bi].clone());
result.push(comment_endif(path));
op_idx += 1;
}
}
}
while tree_pos < tree.len() {
result.push(tree[tree_pos].clone());
tree_pos += 1;
}
result
}
pub(super) fn process_boolean(
result: Vec<DomNode>,
axes: &[Axis],
variants: &[String],
axis_idx: usize,
) -> Vec<DomNode> {
let axis = &axes[axis_idx];
let pair = find_pair_for_axis(axes, variants.len(), axis_idx);
let Some((vi_a, vi_b)) = pair else {
return result;
};
let tree_a = parse_html(&variants[vi_a]);
let tree_b = parse_html(&variants[vi_b]);
insert_boolean_directives(&result, &tree_a, &tree_b, &axis.path)
}