use crate::ast::*;
use crate::builders::WireContext;
use crate::error::CompilerError;
use crate::packet::build_ethernet_and_l2;
use alloc::vec::Vec;
pub fn build_stp_frame(
ctx: &WireContext,
spec: &StpSpec,
payload: &[u8],
) -> Result<Vec<u8>, CompilerError> {
let mut bpdu = Vec::with_capacity(35 + payload.len());
bpdu.extend_from_slice(&0_u16.to_be_bytes());
bpdu.push(if spec.is_rstp { 2 } else { 0 });
bpdu.push(if spec.is_rstp { 2 } else { 0 });
bpdu.push(spec.flags.unwrap_or(0));
bpdu.extend_from_slice(&0x8000_u16.to_be_bytes()); bpdu.extend_from_slice(&ctx.src_mac);
bpdu.extend_from_slice(&spec.cost.unwrap_or(0).to_be_bytes());
bpdu.extend_from_slice(&0x8000_u16.to_be_bytes());
bpdu.extend_from_slice(&ctx.src_mac);
bpdu.extend_from_slice(&spec.port_id.unwrap_or(0x8001).to_be_bytes());
bpdu.extend_from_slice(&0_u16.to_be_bytes());
let max_age = spec.max_age.unwrap_or(20) << 8;
bpdu.extend_from_slice(&max_age.to_be_bytes());
let hello = spec.hello_time.unwrap_or(2) << 8;
bpdu.extend_from_slice(&hello.to_be_bytes());
let fwd_delay = spec.forward_delay.unwrap_or(15) << 8;
bpdu.extend_from_slice(&fwd_delay.to_be_bytes());
bpdu.extend_from_slice(payload);
let mut llc_packet = Vec::with_capacity(3 + bpdu.len());
llc_packet.push(0x42);
llc_packet.push(0x42);
llc_packet.push(0x03);
llc_packet.extend_from_slice(&bpdu);
let length_field = llc_packet.len() as u16;
let dst_mac = ctx.l2.dst_mac.unwrap_or([0x01, 0x80, 0xc2, 0x00, 0x00, 0x00]);
Ok(build_ethernet_and_l2(ctx.src_mac, dst_mac, ctx.l2, length_field, &llc_packet))
}