"""Generate public synthetic gzip members, then measure the actual files."""
from pathlib import Path
import base64, gzip, hashlib, json, platform, struct, zlib

OUT = Path(__file__).resolve().parent / 'generated'
OUT.mkdir(parents=True, exist_ok=True)

def member(payload):
    compressor = zlib.compressobj(6, zlib.DEFLATED, -15)
    raw = compressor.compress(payload) + compressor.flush()
    # Fixed header: deflate, no optional fields, zero timestamp, OS unknown.
    return bytes.fromhex('1f8b08000000000000ff') + raw + struct.pack('<II', zlib.crc32(payload), len(payload))

def inspect(data):
    rows, rest, offset = [], data, 0
    while rest:
        decoder = zlib.decompressobj(31)
        payload = decoder.decompress(rest) + decoder.flush()
        assert decoder.eof, 'Incomplete gzip member'
        used = len(rest) - len(decoder.unused_data)
        assert used > 0
        crc, size = struct.unpack('<II', rest[used-8:used])
        assert crc == zlib.crc32(payload) and size == len(payload)
        rows.append(dict(index=len(rows)+1, start=offset, end_exclusive=offset+used,
                         compressed_bytes=used, output_bytes=len(payload),
                         crc32=f'{crc:08x}', text=payload.decode('ascii')))
        rest = decoder.unused_data
        offset += used
    return rows

def main():
    a, b = b'ALPHA: keep this line.\n', b'BETA: keep this line too.\n'
    cases = {'single': member(a), 'joined': member(a)+member(b), 'reversed': member(b)+member(a)}
    report = dict(python=platform.python_version(), zlib=zlib.ZLIB_RUNTIME_VERSION, cases={})
    for name, data in cases.items():
        (OUT/(name+'.gz')).write_bytes(data)
        encoded = base64.b64encode(data)
        (OUT/(name+'.b64.txt')).write_bytes(encoded)
        decoded = base64.b64decode(encoded, validate=True)
        assert decoded == data
        first = zlib.decompress(decoded, 31)
        full = gzip.decompress(decoded)
        rows = inspect(decoded)
        assert full == b''.join(r['text'].encode('ascii') for r in rows)
        (OUT/(name+'.all.txt')).write_bytes(full)
        (OUT/(name+'.first.txt')).write_bytes(first)
        report['cases'][name] = dict(input_bytes=len(data), base64_characters=len(encoded),
            sha256=hashlib.sha256(data).hexdigest(), roundtrip_equal=decoded==data,
            all_bytes=len(full), first_bytes=len(first), all_text=full.decode('ascii'),
            first_text=first.decode('ascii'), members=rows)
    (OUT/'measurements.json').write_text(json.dumps(report, indent=2)+'\n', encoding='utf-8')
    print(json.dumps(report, indent=2))

if __name__ == '__main__':
    main()
