"""Compare whole and early-stopped generated Robot 36 recordings.

Usage: python reproduce.py robot36.wav /path/to/Open-SSTV NEW_OUTPUT_DIRECTORY
Requires Python 3.11+, Pillow and the pinned Open-SSTV dependencies.
"""
from hashlib import sha256
from pathlib import Path
import json
import os
import subprocess
import sys
import tomllib
import wave

from PIL import Image, ImageChops

source, repo, output = (Path(arg).resolve() for arg in sys.argv[1:])
base = 'f773bd4fcb9da0c68ab915e9a1fa2c024bfdcc98'
source_hash = sha256(source.read_bytes()).hexdigest()
assert source_hash == 'dbb64c8cb34d3599c5aa7c36144746039632832da554eefff324a9fc68ae0166'
subprocess.run(['git', 'diff', '--exit-code', base, '--', 'src'], cwd=repo, check=True)
output.mkdir()
with wave.open(str(source)) as wav:
    params = wav.getparams()
    assert (params.nchannels, params.sampwidth, params.framerate) == (1, 2, 48000)
    pcm = wav.readframes(params.nframes)

cut = pcm[:20 * params.framerate * params.sampwidth]
rows = []
control = None
for name, data in [('full', pcm), ('first-20s', cut),
                   ('first-20s-padded', cut + bytes(len(pcm) - len(cut)))]:
    wav_path = output / f'{name}.wav'
    image_path = output / f'{name}.png'
    with wave.open(str(wav_path), 'wb') as wav:
        wav.setparams(params)
        wav.writeframes(data)
    command = [sys.executable, '-m', 'open_sstv.cli.decode', str(wav_path), '-o', str(image_path)]
    decoded = subprocess.run(command, cwd=repo, env={**os.environ, 'PYTHONPATH': str(repo / 'src')},
                             capture_output=True, text=True, timeout=180)
    log = (decoded.stdout + decoded.stderr).replace(str(output), 'OUTPUT').replace(str(repo), 'OPEN_SSTV_REPO')
    (output / f'{name}.log').write_text(log)
    dimensions, matching_rows = None, None
    if image_path.exists():
        with Image.open(image_path) as image:
            rgb = image.convert('RGB')
        dimensions = list(rgb.size)
        if name == 'full':
            control = rgb
        if control is not None and rgb.size == control.size:
            diff = ImageChops.difference(control, rgb)
            matching_rows = sum(diff.crop((0, y, rgb.width, y + 1)).getbbox() is None for y in range(rgb.height))
    rows.append({'name': name, 'seconds': len(data)/(params.sampwidth*params.framerate),
                 'input_sha256': sha256(wav_path.read_bytes()).hexdigest(),
                 'exit_code': decoded.returncode, 'decoded_dimensions': dimensions,
                 'pixel_identical_rows_vs_full': matching_rows, 'decoder_output': log,
                 'decode_command': ['python','-m','open_sstv.cli.decode',wav_path.name,'-o',image_path.name]})

report = {'experiment': 'Early stop and zero padding with a complete VIS header',
          'scope': 'Generated PCM WAV with pinned Open-SSTV CLI. No RF, microphone or mobile app test.',
          'source_sha256': source_hash, 'sample_rate_hz': params.framerate,
          'decoder_source_base': base,
          'decoder_checkout': subprocess.check_output(['git','rev-parse','HEAD'],cwd=repo,text=True).strip(),
          'decoder_version': tomllib.loads((repo/'pyproject.toml').read_text())['project']['version'],
          'python': sys.version.split()[0], 'cases': rows}
(output/'report.json').write_text(json.dumps(report,indent=2)+'\n')
assert rows[0]['exit_code'] == 0 and rows[0]['decoded_dimensions'] == [320,240]
print(json.dumps(report,indent=2))
