#!/usr/bin/env python3
"""Turn upstream mpv-winbuild-cmake into Lumen's libmpv recipe (D193).

Upstream (shinchiro) builds a GPL mpv with x264/x265 and friends. Lumen
ships closed-source, so the DLL must stay LGPL — the exact posture of the
media-kit build we replace: `--disable-gpl --disable-nonfree
--enable-version3` for FFmpeg and `-Dgpl=false` for mpv. Unlike that
build, NO decoder allowlist: every LGPL FFmpeg decoder is in (TrueHD, MLP,
ProRes, FFV1, …), the Windows twin of the Android "full" jars (D162).

What this drops, and why:
  GPL-only : x264, x265, davs2, rubberband, libdvdnav, libdvdread
  unneeded : avisynth/vapoursynth script demuxers, uavs3d, cuda-llvm
             (replaced by cuda + ffnvcodec, the nvdec/cuvid path the old
             DLL had; cuda-llvm needs a host clang with an nvptx target
             only to compile CUDA *filters* a player never uses)
  broken   : libvpl (Intel oneVPL, the *_qsv codecs). Its dispatcher
             defines wcscpy_s as a statement macro and mingw-w64's
             stralign.h uses wcscpy_s in an expression — both float on
             master and the 2026-09 pair doesn't compile. Lumen decodes
             through D3D11VA, which covers Intel GPUs too, so QSV is not
             a loss for the player.
  broken   : mpv's optional libcurl stream backend and its HTTP/3 chain
             (curl, ngtcp2, nghttp3, nghttp2, brotli, c-ares, libpsl):
             ngtcp2 needs a QUIC-capable TLS API the recipe's floating
             OpenSSL (4.1) doesn't expose. Lumen streams through FFmpeg's
             HTTP stack (`stream_lavf`), never libcurl — disabled.
  trimmed  : every FFmpeg ENCODER except the image ones mpv's screenshot
             feature uses (mjpeg, png, jpegls, ljpeg, jpeg2000) and every
             MUXER, plus the encoder-only libraries that only existed to
             feed them (SVT-AV1, aom, libvpx, lame, libwebp — FFmpeg's own
             decoders cover VP8/VP9/MP3/WebP and dav1d covers AV1). A
             player never encodes; media-kit's build shipped the same
             posture. Cuts the DLL by roughly a third with all decoders
             kept.
Everything left is LGPL/BSD/MIT/MPL/Apache — see THIRD-PARTY-NOTICES.md.

Usage: lgpl_full.py <recipe-dir> <mpv-tag> <ffmpeg-tag>   (idempotent)
"""
import io
import re
import sys

recipe, mpv_tag, ffmpeg_tag = sys.argv[1:4]


def edit(path, fn):
    s = io.open(path, encoding='utf-8').read()
    io.open(path, 'w', encoding='utf-8', newline='\n').write(fn(s))


def drop_lines(s, needles):
    return ''.join(
        line for line in s.splitlines(keepends=True)
        if line.strip() not in needles
    )


def replace_line(s, old, new_lines):
    lines = s.splitlines(keepends=True)
    hit = False
    for i, line in enumerate(lines):
        if line.strip() == old:
            indent = line[:len(line) - len(line.lstrip())]
            lines[i] = ''.join(f'{indent}{n}\n' for n in new_lines)
            hit = True
    return ''.join(lines), hit


def pin(s, tag):
    if re.search(r'^\s*GIT_TAG\s', s, re.M):
        return re.sub(r'^(\s*)GIT_TAG\s+\S+', r'\1GIT_TAG ' + tag, s, count=1, flags=re.M)
    return re.sub(r'^(\s*)(GIT_REPOSITORY\s+\S+)\n',
                  r'\1\2\n\1GIT_TAG ' + tag + '\n', s, count=1, flags=re.M)


def ffmpeg(s):
    s = drop_lines(s, {
        'avisynth-headers', 'libdvdnav', 'libdvdread', 'x264', '${ffmpeg_x265}',
        '${ffmpeg_uavs3d}', '${ffmpeg_davs2}', 'rubberband', 'vapoursynth',
        '--enable-avisynth', '--enable-vapoursynth', '--enable-libdvdnav',
        '--enable-libdvdread', '--enable-librubberband', '--enable-libx264',
        '--enable-libx265', '${ffmpeg_davs2_cmd}', '${ffmpeg_uavs3d_cmd}',
        'libvpl', '--enable-libvpl',
        # encoder-only libraries and their flags (see "trimmed" above)
        'svtav1', 'aom', 'libvpx', 'lame', 'libwebp',
        '--enable-libsvtav1', '--enable-libaom', '--enable-libvpx',
        '--enable-libmp3lame', '--enable-libwebp', '--disable-decoder=libaom_av1',
    })
    s, _ = replace_line(s, '--enable-gpl', ['--disable-gpl', '--disable-nonfree'])
    s, _ = replace_line(s, '--enable-cuda-llvm', ['--enable-cuda', '--enable-ffnvcodec'])
    if '--disable-encoders' not in s:
        s, hit = replace_line(s, '--enable-version3', [
            '--enable-version3',
            '--disable-encoders',
            '--enable-encoder=mjpeg',
            '--enable-encoder=png',
            '--enable-encoder=jpegls',
            '--enable-encoder=ljpeg',
            '--enable-encoder=jpeg2000',
            '--disable-muxers',
        ])
        assert hit, 'could not anchor the encoder trim'
    assert '--enable-gpl' not in s, 'GPL flag survived'
    assert '--disable-decoders' not in s, 'a decoder allowlist crept in'
    assert 'enable-version3' in s, 'version3 missing'
    return pin(s, ffmpeg_tag)


def mpv(s):
    # subrandr (Rust subtitle renderer) and libcurl (stream backend) are
    # master-only meson options; mpv v0.41.0 rejects them as unknown, so
    # they and their packages go rather than get disabled.
    s = drop_lines(s, {'libdvdnav', 'libdvdread', 'rubberband', 'vapoursynth', 'curl',
                       'subrandr', '-Dsubrandr=enabled', '-Dsubrandr=disabled',
                       '-Dlibcurl=enabled', '-Dlibcurl=disabled'})
    for old, new in [('-Ddvdnav=enabled', '-Ddvdnav=disabled'),
                     ('-Drubberband=enabled', '-Drubberband=disabled'),
                     ('-Dvapoursynth=enabled', '-Dvapoursynth=disabled')]:
        s, _ = replace_line(s, old, [new])
    if '-Dgpl=false' not in s:
        s, hit = replace_line(s, '-Dlibmpv=true', ['-Dlibmpv=true', '-Dgpl=false'])
        assert hit, 'could not anchor -Dgpl=false'
    return pin(s, mpv_tag)


edit(f'{recipe}/packages/ffmpeg.cmake', ffmpeg)
edit(f'{recipe}/packages/mpv.cmake', mpv)
print(f'recipe patched: LGPL, full decoders, mpv {mpv_tag}, ffmpeg {ffmpeg_tag}')
