#!/usr/bin/env python3 -B
"""
Script for collecting distribution archives needed for doing a release.

This collects "sdist" and "wheel" archives, the latter for a number of
Python versions (see below).
"""

import fnmatch
import os
import shutil
import subprocess
import sys

from _common_definitions import (
    DIST_DIR,
    PY_VERSIONS,
    TOP_DIR,
    setup_variant,
    system_report,
    variants,
)


def files_matching(pattern, dirname):
    return fnmatch.filter(os.listdir(dirname), pattern)


_detected_versions = None


def is_usable_release(ver):
    path = os.path.join("/Library/Frameworks/Python.framework/Versions", ver)

    if not os.path.exists(path):
        return False

    output = subprocess.check_output([f"{path}/bin/python3", "--version"]).decode()
    if "a" in output.strip():
        # Alpha release
        return False

    return True


def detect_pyversions():
    global _detected_versions
    if _detected_versions is not None:
        return _detected_versions

    result = []
    for ver in PY_VERSIONS:
        if is_usable_release(ver):
            result.append(ver)

    _detected_versions = result
    return _detected_versions


def main():
    if os.path.exists(DIST_DIR):
        shutil.rmtree(DIST_DIR)
    os.mkdir(DIST_DIR)

    # Information about this build:
    system_report(os.path.join(TOP_DIR, "build-info.txt"), detect_pyversions())

    # Collect the list of subprojects to build
    names = ["pyobjc", "pyobjc-core"]
    for nm in sorted(os.listdir(TOP_DIR)):
        if nm.startswith("pyobjc-framework-"):
            names.append(nm)

    failed = []
    for nm in names:
        # Collect sdist archive with most recent python version.
        status = subprocess.call(
            [
                f"python{detect_pyversions()[-1]}",
                "setup.py",
                "sdist",
                f"--dist-dir={DIST_DIR}",
            ],
            cwd=os.path.join(TOP_DIR, nm),
        )
        if status != 0:
            print(f"WARNING: Building wheel for {nm} failed")
            failed.append((nm, "sdist", ""))

        for ver in detect_pyversions():
            for variant in variants(ver):
                if ver == "3.8":
                    pass
                elif any(variant.endswith(x) for x in ("-x86_64", "-arm64")):
                    # Don't create single architecture wheels for anything other than
                    # Python 3.8 (where the universal2 build is only for macOS 11 or later)
                    continue
                setup_variant(ver, variant)
                status = subprocess.call(
                    [
                        f"python{ver}",
                        "setup.py",
                        "build_ext", "-j", str(os.cpu_count()),
                        "bdist_wheel",
                        f"--dist-dir={DIST_DIR}",
                    ],
                    cwd=os.path.join(TOP_DIR, nm),
                )

                if status != 0:
                    print(
                        "WARNING: Building wheel for {} failed (python {})".format(
                            nm, variant
                        )
                    )
                    failed.append((nm, "wheel", variant))

    print()
    print("Collected files")
    print("===============")
    print()
    for nm in names:
        if nm == "pyobjc":
            continue
        pattern = nm.replace("-", "?") + "-*"
        print(f"{nm}:")
        for fn in sorted(files_matching(pattern, DIST_DIR)):
            print(f"  {fn}")
        print()

    if failed:
        print()
        print("Build failures")
        print("==============")
        print()
        for nm, command, ver in failed:
            if ver:
                print(f"{nm} {command}@{ver}")
            else:
                print(f"{nm} {command}")

        sys.exit(0)

    sys.exit(0)


if __name__ == "__main__":
    main()
