#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import argparse
import json
import logging as log
import re
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
from urllib.request import urlopen, urlretrieve

log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")

# the keys in this dictionary specify valid toolchain kinds
ASSET_PREFIXES = {
    # kind : prefix,
    "combined": "lowrisc-toolchain-rv32imc-",
    "gcc-only": "lowrisc-toolchain-gcc-rv32imc-",
}
ASSET_SUFFIX = ".tar.xz"
RELEASES_URL_BASE = 'https://api.github.com/repos/lowRISC/lowrisc-toolchains/releases'

TARGET_DIR = '/tools/riscv'
TOOLCHAIN_VERSION = 'latest'
TOOLCHAIN_KIND = 'combined'

FILE_PATTERNS_TO_REWRITE = [
    "riscv32-unknown-elf-*.cmake",
    "meson-riscv32-unknown-elf-*.txt",
]


def get_available_toolchain_info(version, kind):
    assert kind in ASSET_PREFIXES

    if version == 'latest':
        releases_url = '%s/%s' % (RELEASES_URL_BASE, version)
    else:
        releases_url = '%s/tags/%s' % (RELEASES_URL_BASE, version)

    with urlopen(releases_url) as f:
        release_info = json.loads(f.read().decode('utf-8'))

    for asset in release_info["assets"]:
        if (asset["name"].startswith(ASSET_PREFIXES[kind]) and
                asset["name"].endswith(ASSET_SUFFIX)):
            return {
                'download_url': asset['browser_download_url'],
                'name': asset['name'],
                'version': release_info['tag_name'],
                'kind': kind
            }

    # No matching asset found for the toolchain kind requested
    log.error("No available downloads found for %s toolchain version: %s",
              kind, release_info['tag_name'])
    raise SystemExit(1)


def get_installed_toolchain_info(install_path):

    # Try new-style buildinfo.json first
    try:
        buildinfo = {}
        with open(str(install_path / 'buildinfo.json'), 'r') as f:
            buildinfo = json.loads(f.read())

        # Toolchains before 20200602-4 contained a `buildinfo.json` without a
        # 'kind' field. Setting it to 'unknown' will ensure we never skip
        # updating because we think it's the same as the existing toolchain.
        if 'kind' not in buildinfo:
            buildinfo['kind'] = 'unknown'

        return buildinfo
    except Exception as e:
        # buildinfo.json might not exist in older builds
        log.info("Unable to parse buildinfo.json: %s", str(e))
        pass

    # If that wasn't successful, try old-style plaintext buildinfo
    version_re = r"(lowRISC toolchain version|Version):\s*\n?(?P<version>[^\n\s]+)"
    buildinfo_txt_path = install_path / 'buildinfo'
    try:
        with open(str(buildinfo_txt_path), 'r') as f:
            match = re.match(version_re, f.read(), re.M)
        if not match:
            log.warning("Unable extract version from %s",
                        str(buildinfo_txt_path))
            return None
        return {'version': match.group("version"), 'kind': 'unknown'}
    except Exception as e:
        log.error("Unable to read %s: %s", str(buildinfo_txt_path), str(e))
        return None


def download(url):
    log.info("Downloading toolchain from %s", url)
    tmpfile = tempfile.mkstemp()[1]
    urlretrieve(url, tmpfile)
    log.info("Download complete")
    return Path(tmpfile)


def install(archive_file, target_dir):
    target_dir.mkdir(parents=True, exist_ok=True)

    cmd = [
        'tar', '-x', '-f', str(archive_file), '--strip-components=1', '-C', str(target_dir),
    ]
    subprocess.run(cmd, check=True)


def postinstall_rewrite_configs(install_path):
    """This rewrites the toolchain configuration files to point to install_path"""
    if str(install_path) == TARGET_DIR:
        return

    for file_pattern in FILE_PATTERNS_TO_REWRITE:
        for config_file_path in install_path.glob(file_pattern):
            # Rewrite TARGET_DIR to the requested target dir.
            log.info("Updating toolchain paths in %s",
                        str(config_file_path))
            with open(str(config_file_path)) as f:
                original = f.read()
            with open(str(config_file_path), "w") as f:
                f.write(original.replace(TARGET_DIR, str(install_path)))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--target-dir',
                        '-t',
                        required=False,
                        default=TARGET_DIR,
                        help="Target directory (default: %(default)s)")
    parser.add_argument('--release-version',
                        '-r',
                        required=False,
                        default=TOOLCHAIN_VERSION,
                        help="Toolchain version (default: %(default)s)")
    parser.add_argument('--kind',
                        required=False,
                        default=TOOLCHAIN_KIND,
                        choices=ASSET_PREFIXES.keys(),
                        help="Toolchain kind (default: %(default)s)")
    parser.add_argument(
        '--update',
        '-u',
        required=False,
        default=False,
        action='store_true',
        help="Update to target version if needed (default: %(default)s)")
    args = parser.parse_args()

    target_dir = Path(args.target_dir)

    available_toolchain = get_available_toolchain_info(args.release_version,
                                                       args.kind)
    log.info("Found available %s toolchain version %s, %s",
             available_toolchain['kind'], available_toolchain['version'],
             available_toolchain['name'])

    if args.update and target_dir.is_dir():
        installed_toolchain = get_installed_toolchain_info(target_dir)
        if installed_toolchain is None:
            sys.exit('Unable to extract current toolchain version. '
                     'Delete target directory %s and try again.' %
                     str(target_dir))

        version_matches = available_toolchain['version'] == installed_toolchain['version']
        kind_matches = available_toolchain['kind'] == installed_toolchain['kind']

        if installed_toolchain['kind'] != 'unknown' and version_matches and kind_matches:
            log.info(
                'Downloaded %s toolchain is version %s, '
                'same as the %s toolchain installed at %s (version %s).',
                available_toolchain['kind'], available_toolchain['version'],
                installed_toolchain['kind'], installed_toolchain['version'],
                str(target_dir))
            log.warning("Skipping install.")
            sys.exit(0)

        log.info(
            "Found installed %s toolchain version %s, updating to %s toolchain version %s.",
            installed_toolchain['kind'], installed_toolchain['version'],
            available_toolchain['kind'], available_toolchain['version'])
    else:
        if target_dir.exists():
            sys.exit('Target directory %s already exists. '
                     'Delete it first, or use --update.' % str(target_dir))

    archive_file = None
    try:
        archive_file = download(available_toolchain['download_url'])

        if args.update and target_dir.exists():
            # We only reach this point if |target_dir| contained a toolchain
            # before, so removing it is reasonably safe.
            shutil.rmtree(str(target_dir))

        install(archive_file, target_dir)
        postinstall_rewrite_configs(target_dir.resolve())
    finally:
        if archive_file:
            archive_file.unlink()

    log.info('Installed %s toolchain version %s to %s.',
             available_toolchain['kind'], available_toolchain['version'],
             str(target_dir))


if __name__ == "__main__":
    main()
