#!/usr/bin/env python3
"""Relink a prepared core with optional replacement static library archives."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import subprocess

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--work-dir', type=Path, default=Path(__file__).resolve().parents[1] / 'work')
parser.add_argument('--output-dir', type=Path, help='Defaults to WORK/relinked, preserving the original outputs')
parser.add_argument('--library', action='append', default=[], metavar='NAME=ARCHIVE',
                    help='Replace avcodec, avfilter, avformat, avutil, swresample, mp3lame or opus; may repeat')
args = parser.parse_args()
work = args.work_dir.resolve()
output = args.output_dir.resolve() if args.output_dir else work / 'relinked'
if output == work / 'output':
    parser.error('Use another output directory to preserve the original build outputs.')
output.mkdir(parents=True, exist_ok=True)
command = json.loads((work / 'link-arguments.json').read_text())
allowed = ['avcodec', 'avfilter', 'avformat', 'avutil', 'swresample', 'mp3lame', 'opus']
replacements = {}
for specification in args.library:
    if '=' not in specification:
        parser.error('--library needs NAME=ARCHIVE')
    name, filename = specification.split('=', 1)
    path = Path(filename).resolve()
    if name not in allowed or name in replacements or not path.is_file():
        parser.error('Unknown, duplicate or missing replacement library: ' + specification)
    token = '-l' + name
    if command.count(token) != 1:
        raise SystemExit('Unexpected original link command for ' + name)
    command[command.index(token)] = str(path)
    replacements[name] = {'file': str(path), 'sha256': hashlib.sha256(path.read_bytes()).hexdigest()}
if command.count('-o') != 1:
    raise SystemExit('Unexpected original output argument.')
command[command.index('-o') + 1] = str(output / 'ffmpeg-core.js')
env = dict(os.environ)
env.update(json.loads((work / 'toolchain-env.json').read_text())['environment'])
env['TZ'] = 'UTC'
env['SOURCE_DATE_EPOCH'] = '1736244768'
with (output / 'relink.log').open('w') as log:
    result = subprocess.run(command, cwd=work / 'source/ffmpeg', env=env,
                            stdout=log, stderr=subprocess.STDOUT)
receipt = {'status': 'relink succeeded' if result.returncode == 0 else 'relink failed',
           'exitCode': result.returncode, 'command': command, 'replacementLibraries': replacements,
           'outputs': [], 'reproducibleBuildVerified': False}
if result.returncode == 0:
    for path in sorted(output.glob('ffmpeg-core.*')):
        receipt['outputs'].append({'file': path.name, 'bytes': path.stat().st_size,
                                  'sha256': hashlib.sha256(path.read_bytes()).hexdigest()})
(output / 'relink-receipt.json').write_text(json.dumps(receipt, indent=2) + '\n')
if result.returncode:
    raise SystemExit('Relink failed; see ' + str(output / 'relink.log'))
print(json.dumps(receipt['outputs'], indent=2))
