"""Build script for nanoprintf. Configures and runs CMake to build tests."""

import argparse
import os
import pathlib
import shutil
import subprocess
import stat
import sys
import tarfile
import urllib.request
import zipfile

SCRIPT_PATH = pathlib.Path(__file__).resolve().parent

NINJA_URL = 'https://github.com/ninja-build/ninja/releases/download/v1.10.2/{}'
CMAKE_URL = 'https://cmake.org/files/v3.22/{}'


def parse_args():
    """Parse command-line arguments."""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--cfg',
        choices=[
            'Debug',
            'RelWithDebInfo',
            'Release'],
        default='Release',
        const='Release',
        nargs='?',
        help='CMake configuration')
    parser.add_argument(
        '--arch',
        type=int,
        choices=(32, 64),
        default=64,
        const=64,
        nargs='?',
        help='Target architecture')
    parser.add_argument(
        '--paland',
        help='Compile with Paland\'s printf conformance suite',
        action='store_true')
    parser.add_argument(
        '--download',
        help='Download CMake and Ninja, don\'t use local copies',
        action='store_true')
    parser.add_argument('--ubsan', action='store_true', help='Clang UB sanitizer')
    parser.add_argument('--asan', action='store_true', help='Clang addr sanitizer')
    parser.add_argument('-v', '--verbose', action='store_true', help='verbose')
    return parser.parse_args()


def download_file(url, local_path, verbose):
    """Download a file from url to local_path."""
    if verbose:
        print(f'Downloading:\n  Remote: {url}\n  Local: {local_path}')
    with urllib.request.urlopen(url) as rsp, open(local_path, 'wb') as file:
        shutil.copyfileobj(rsp, file)


def get_cmake(download, verbose):
    """Return the path to system CMake, or download and unpack a local copy."""
    if not download:
        cmake = shutil.which('cmake')
        if cmake:
            return cmake

    plat = {
        'darwin': 'macos-universal',
        'linux': 'linux-x86_64',
        'win32': 'win64-x86_64'}[
        sys.platform]
    cmake_prefix = f'cmake-3.22.2-{plat}'
    cmake_local_dir = SCRIPT_PATH / 'external' / 'cmake'
    cmake_file = f'{cmake_prefix}.tar.gz'
    cmake_local_tgz = cmake_local_dir / cmake_file
    cmake_local_exe = cmake_local_dir / cmake_prefix / \
        ('CMake.app/Contents' if sys.platform == 'darwin' else '') / 'bin' / 'cmake'

    if not cmake_local_exe.exists():
        if not cmake_local_tgz.exists():
            cmake_local_dir.mkdir(parents=True, exist_ok=True)
            download_file(
                CMAKE_URL.format(cmake_file),
                cmake_local_tgz,
                verbose)
        with tarfile.open(cmake_local_tgz, 'r') as tar:
            for member in tar.getmembers():
                member_path = pathlib.Path(cmake_local_dir / member.name).resolve()
                if not cmake_local_dir in member_path.parents:
                    raise ValueError('Tar file contents move upwards past sandbox root')
            tar.extractall(path=cmake_local_dir)

    return cmake_local_exe


def get_ninja(download, verbose):
    """Return the path to system Ninja, or download and unpack a local copy."""
    if not download:
        ninja = shutil.which('ninja')
        if ninja:
            return ninja

    ninja_local_dir = SCRIPT_PATH / 'external' / 'ninja'
    plat = {'darwin': 'mac', 'linux': 'linux', 'win32': 'win'}[sys.platform]
    ninja_file = f'ninja-{plat}.zip'
    ninja_local_zip = ninja_local_dir / ninja_file
    ninja_local_exe = ninja_local_dir / f'ninja{".exe" if plat == "win" else ""}'

    if not ninja_local_exe.exists():
        if not ninja_local_zip.exists():
            ninja_local_dir.mkdir(parents=True, exist_ok=True)
            download_file(
                NINJA_URL.format(ninja_file),
                ninja_local_zip,
                verbose)
        with zipfile.ZipFile(ninja_local_zip, 'r') as zip_file:
            zip_file.extractall(ninja_local_dir)
        os.chmod(ninja_local_exe, os.stat(
            ninja_local_exe).st_mode | stat.S_IEXEC)

    return ninja_local_exe


def configure_cmake(cmake_exe, ninja, args):
    """Prepare CMake for building nanoprintf tests under 'build/ninja/<cfg>'."""
    build_path = SCRIPT_PATH / 'build' / 'ninja' / args.cfg
    if (build_path / 'CMakeFiles').exists():
        return True

    sys.stdout.flush()
    build_path.mkdir(parents=True)

    cmake_args = [cmake_exe,
                  SCRIPT_PATH,
                  '-G',
                  'Ninja',
                  '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
                  f'-DCMAKE_MAKE_PROGRAM={ninja}',
                  f'-DCMAKE_BUILD_TYPE={args.cfg}',
                  f'-DNPF_PALAND={"ON" if args.paland else "OFF"}',
                  f'-DNPF_32BIT={"ON" if args.arch == 32 else "OFF"}',
                  f'-DNPF_CLANG_ASAN={"ON" if args.asan else "OFF"}',
                  f'-DNPF_CLANG_UBSAN={"ON" if args.ubsan else "OFF"}']
    try:
        return subprocess.run(
            cmake_args,
            cwd=build_path,
            check=True).returncode == 0
    except subprocess.CalledProcessError as cpe:
        return cpe.returncode == 0


def build_cmake(cmake_exe, args):
    """Run CMake in build mode to compile and run the nanoprintf test suite."""
    sys.stdout.flush()
    build_path = SCRIPT_PATH / 'build' / 'ninja' / args.cfg
    cmake_args = [cmake_exe, '--build', build_path] + \
        (['--', '-v'] if args.verbose else [])
    try:
        return subprocess.run(cmake_args, check=True).returncode == 0
    except subprocess.CalledProcessError as cpe:
        return cpe.returncode == 0


def main():
    """Parse args, find or get tools, configure CMake, build and run tests."""
    args = parse_args()

    cmake = get_cmake(args.download, args.verbose)
    if args.verbose:
        print(f'Found CMake at {cmake}')

    ninja = get_ninja(args.download, args.verbose)
    if args.verbose:
        print(f'Found ninja at {ninja}')

    built_ok = configure_cmake(cmake, ninja, args) and build_cmake(cmake, args)
    return int(not built_ok)  # 0 is success


if __name__ == '__main__':
    sys.exit(main())
