//! Golden-file conformance tests.
//!
//! Each case converts a TTF fixture and checks the result byte for byte against
//! the matching EOT fixture. The two inputs differ in OS/2 version, which gates
//! whether the codepage range gets written.

use std::path::Path;

use ttf2eot::ttf2eot;

/// Load a fixture by name from `tests/fixtures`.
fn load(name: &str) -> Vec<u8> {
    let p = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests/fixtures")
        .join(name);
    std::fs::read(&p).unwrap_or_else(|e| panic!("read {name}: {e}"))
}

/// Compare two buffers and report the first differing offset on failure.
fn assert_bytes_eq(got: &[u8], want: &[u8], label: &str) {
    assert_eq!(
        got.len(),
        want.len(),
        "{label}: length got={} want={}",
        got.len(),
        want.len()
    );
    if let Some(i) = got.iter().zip(want).position(|(a, b)| a != b) {
        panic!(
            "{label}: first diff at offset {i}: got={:#04x} want={:#04x}",
            got[i], want[i]
        );
    }
}

/// OS/2 version 0 font. Codepage range stays zero.
#[test]
fn bin_compare_os2_version_0() {
    let src = load("test_v0.ttf");
    let dst = load("test_v0.eot");
    assert_bytes_eq(&ttf2eot(&src).expect("convert"), &dst, "os2_v0");
}

/// OS/2 version 1 or later font. Codepage range is written.
#[test]
fn bin_compare() {
    let src = load("test.ttf");
    let dst = load("test.eot");
    assert_bytes_eq(&ttf2eot(&src).expect("convert"), &dst, "os2_v1plus");
}

/// Both cases in a table so adding fonts later stays easy.
#[test]
fn golden_table() {
    for (ttf, eot, label) in [
        ("test.ttf", "test.eot", "os2_v1plus"),
        ("test_v0.ttf", "test_v0.eot", "os2_v0"),
    ] {
        assert_bytes_eq(&ttf2eot(&load(ttf)).expect(label), &load(eot), label);
    }
}

fn le_u32(b: &[u8], o: usize) -> u32 {
    u32::from_le_bytes(b[o..o + 4].try_into().unwrap())
}

fn le_u16(b: &[u8], o: usize) -> u16 {
    u16::from_le_bytes(b[o..o + 2].try_into().unwrap())
}

/// Header fields for the OS/2 version 1+ font. Codepage range is written.
#[test]
fn eot_header_fields_v1plus() {
    let ttf = load("test.ttf");
    let out = ttf2eot(&ttf).unwrap();
    assert_eq!(le_u32(&out, 0), out.len() as u32); // LENGTH (whole file)
    assert_eq!(le_u32(&out, 4), ttf.len() as u32); // FONT_LENGTH
    assert_eq!(le_u32(&out, 8), 0x0002_0001); // VERSION
    assert_eq!(out[26], 1); // CHARSET
    assert_eq!(le_u16(&out, 34), 0x504C); // MAGIC "LP"
    assert_eq!(le_u32(&out, 28), 400); // WEIGHT
    assert_eq!(out[27], 0); // ITALIC
    assert_eq!(le_u32(&out, 52), 1); // CODEPAGE_RANGE written
    assert_eq!(&out[out.len() - ttf.len()..], &ttf[..]); // tail verbatim
}

/// Header fields for the OS/2 version 0 font. Codepage range stays zero.
#[test]
fn eot_header_fields_v0() {
    let ttf = load("test_v0.ttf");
    let out = ttf2eot(&ttf).unwrap();
    assert_eq!(le_u32(&out, 52), 0); // CODEPAGE_RANGE not written
    assert_eq!(le_u32(&out, 56), 0);
    assert_eq!(&out[out.len() - ttf.len()..], &ttf[..]); // tail verbatim
}
