"""Compare real resampling with an intentionally incorrect WAV rate label.

Run with a Python environment containing Open-SSTV's dependencies:
  python reproduce.py ORIGINAL.wav OPEN_SSTV_REPO NEW_OUTPUT_DIRECTORY
"""
import hashlib
import json
import os
from pathlib import Path
import shutil
import subprocess
import sys
import wave

import numpy as np
from PIL import Image

source, repository, output = map(lambda p: Path(p).resolve(), sys.argv[1:])
source_hash = hashlib.sha256(source.read_bytes()).hexdigest()
assert source_hash == "dbb64c8cb34d3599c5aa7c36144746039632832da554eefff324a9fc68ae0166", "Use the published generated Robot 36 practice WAV"
subprocess.run(["git", "diff", "--exit-code", "f773bd4fcb9da0c68ab915e9a1fa2c024bfdcc98", "--", "src"],
               cwd=repository, check=True, capture_output=True)
output.mkdir(parents=True, exist_ok=False)
with wave.open(str(source)) as wav:
    assert (wav.getframerate(), wav.getnchannels(), wav.getsampwidth()) == (48000, 1, 2)
    frames = wav.readframes(wav.getnframes())

shutil.copyfile(source, output / "original-48000.wav")
conversion = ["ffmpeg", "-hide_banner", "-nostdin", "-loglevel", "error", "-i",
              str(source), "-ar", "44100", "-ac", "1", "-c:a", "pcm_s16le",
              str(output / "resampled-44100.wav")]
subprocess.run(conversion, check=True, capture_output=True, text=True)
with wave.open(str(output / "header-only-44100.wav"), "wb") as wav:
    wav.setparams((1, 2, 44100, 0, "NONE", "not compressed"))
    wav.writeframes(frames)

report = {
    "source_sha256": source_hash,
    "source_is_generated_practice_audio_not_RF": True,
    "decoder_revision": subprocess.check_output(
        ["git", "rev-parse", "HEAD"], cwd=repository, text=True).strip(),
    "decoder_base": "f773bd4fcb9da0c68ab915e9a1fa2c024bfdcc98",
    "decoder_version_scope": "Pinned Open-SSTV v0.6.18; not an SSTV Signal Desk or GUI test",
    "python": sys.version,
    "ffmpeg": subprocess.check_output(["ffmpeg", "-version"], text=True).splitlines()[0],
    "conversion_command": conversion,
    "cases": [],
}
for name in ["original-48000", "resampled-44100", "header-only-44100"]:
    path = output / (name + ".wav")
    with wave.open(str(path)) as wav:
        rate, count = wav.getframerate(), wav.getnframes()
        samples = np.frombuffer(wav.readframes(count), dtype="<i2").astype(float)
    start = int(np.flatnonzero(np.abs(samples) > 100)[0])
    tone = samples[start:start + int(rate * 0.1)]
    spectrum = np.abs(np.fft.rfft(tone * np.hanning(len(tone))))
    peak = float(np.fft.rfftfreq(len(tone), 1 / rate)[np.argmax(spectrum)])
    command = [sys.executable, "-m", "open_sstv.cli.decode", str(path),
               "-o", str(output / (name + ".png"))]
    result = subprocess.run(command, cwd=repository,
        env={**os.environ, "PYTHONPATH": str(repository / "src")},
        capture_output=True, text=True, timeout=180)
    (output / (name + ".log")).write_text(result.stdout + result.stderr)
    image = output / (name + ".png")
    case = {"name": name, "rate_hz": rate, "frames": count,
            "duration_seconds": count / rate, "leading_tone_peak_hz": peak,
            "sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
            "command": command, "exit_code": result.returncode,
            "stdout": result.stdout, "stderr": result.stderr,
            "decoded_dimensions": list(Image.open(image).size) if image.exists() else None}
    report["cases"].append(case)
    (output / "report.json").write_text(json.dumps(report, indent=2) + "\n")
    print(json.dumps({k: case[k] for k in ["name", "duration_seconds", "leading_tone_peak_hz", "exit_code", "decoded_dimensions"]}), flush=True)

assert hashlib.sha256(source.read_bytes()).hexdigest() == source_hash
