#!/usr/bin/env python3

import json
import math
import sys
import wave
from pathlib import Path


def generate_peaks(input_file: Path, output_file: Path, points: int = 1400) -> None:
    with wave.open(str(input_file), "rb") as wav:
        channels = wav.getnchannels()
        sample_width = wav.getsampwidth()
        frame_rate = wav.getframerate()
        frame_count = wav.getnframes()

        if sample_width != 2:
            raise RuntimeError(
                f"Unsupported WAV sample width: {sample_width * 8}-bit"
            )

        raw = wav.readframes(frame_count)

    import array

    samples = array.array("h")
    samples.frombytes(raw)

    if sys.byteorder != "little":
        samples.byteswap()

    if channels > 1:
        mono = []

        for index in range(0, len(samples), channels):
            frame = samples[index:index + channels]

            if frame:
                mono.append(sum(abs(value) for value in frame) / len(frame))
    else:
        mono = [abs(value) for value in samples]

    total_samples = len(mono)

    if total_samples == 0:
        peaks = [0.0] * points
    else:
        bucket_size = max(1, math.ceil(total_samples / points))
        peaks = []

        for start in range(0, total_samples, bucket_size):
            bucket = mono[start:start + bucket_size]
            peak = max(bucket) if bucket else 0
            peaks.append(round(peak / 32768, 5))

        if len(peaks) < points:
            peaks.extend([0.0] * (points - len(peaks)))

        peaks = peaks[:points]

    duration = frame_count / frame_rate if frame_rate else 0

    payload = {
        "version": 1,
        "duration": round(duration, 4),
        "points": len(peaks),
        "peaks": peaks,
    }

    output_file.parent.mkdir(parents=True, exist_ok=True)

    temporary = output_file.with_suffix(".tmp")
    temporary.write_text(
        json.dumps(payload, separators=(",", ":")),
        encoding="utf-8",
    )
    temporary.replace(output_file)


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(
            "Usage: generate_waveform.py input.wav output.json",
            file=sys.stderr,
        )
        sys.exit(2)

    generate_peaks(
        Path(sys.argv[1]),
        Path(sys.argv[2]),
    )
