# This file is run by shell scripts generated by the aos_downloader Skylark
# macro. Everything before the first -- is a hard-coded list of files to
# download.

from __future__ import print_function

import argparse
import sys
from tempfile import TemporaryDirectory
import subprocess
import re
import stat
import os
import shutil


def install(ssh_target, pkg, channel, ssh_path, scp_path):
    """Installs a package from NI on the ssh target."""
    print("Installing", pkg)
    PKG_URL = f"http://download.ni.com/ni-linux-rt/feeds/academic/2023/arm/{channel}/cortexa9-vfpv3/{pkg}"
    subprocess.check_call(["wget", PKG_URL, "-O", pkg])
    try:
        subprocess.check_call(
            [scp_path, "-S", ssh_path, pkg, ssh_target + ":/tmp/" + pkg])
        subprocess.check_call(
            [ssh_path, ssh_target, "opkg", "install", "/tmp/" + pkg])
        subprocess.check_call([ssh_path, ssh_target, "rm", "/tmp/" + pkg])
    finally:
        subprocess.check_call(["rm", pkg])


def main(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument("--target",
                        type=str,
                        default="roborio-971-frc.local",
                        help="Target to deploy code to.")
    parser.add_argument("--type",
                        type=str,
                        choices=["roborio", "pi"],
                        required=True,
                        help="Target type for deployment")
    parser.add_argument("srcs",
                        type=str,
                        nargs='+',
                        help="List of files to copy over")
    args = parser.parse_args(argv[1:])

    srcs = args.srcs

    destination = args.target

    result = re.match("(?:([^:@]+)@)?([^:@]+)(?::([^:@]+))?", destination)
    if not result:
        print("Not sure how to parse destination \"%s\"!" % destination,
              file=sys.stderr)
        return 1
    user = None
    if result.group(1):
        user = result.group(1)
    hostname = result.group(2)

    if result.group(3):
        target_dir = result.group(3)

    if user is None:
        if args.type == "pi":
            user = "pi"
        elif args.type == "roborio":
            user = "admin"
    target_dir = "/home/" + user + "/bin"

    ssh_target = "%s@%s" % (user, hostname)

    ssh_path = "external/ssh/ssh"
    scp_path = "external/ssh/scp"

    # install jq
    try:
        subprocess.check_call([ssh_path, ssh_target, "jq", "--version"],
                              stdout=subprocess.DEVNULL)
    except subprocess.CalledProcessError as e:
        if e.returncode == 127:
            print("Didn't find jq on roboRIO, installing jq.")
            install(ssh_target, "jq-lic_1.5-r0.35_cortexa9-vfpv3.ipk", 'extra',
                    ssh_path, scp_path)
            install(ssh_target, "libonig-lic_5.9.6-r0.27_cortexa9-vfpv3.ipk",
                    'extra', ssh_path, scp_path)
            install(ssh_target, "libonig2_5.9.6-r0.27_cortexa9-vfpv3.ipk",
                    'extra', ssh_path, scp_path)
            install(ssh_target, "jq_1.5-r0.35_cortexa9-vfpv3.ipk", 'extra',
                    ssh_path, scp_path)

            subprocess.check_call([ssh_path, ssh_target, "jq", "--version"],
                                  stdout=subprocess.DEVNULL)

    # Since rsync is pretty fixed in what it can do, build up a temporary
    # directory with the exact contents we want the target to have.  This
    # is faster than multiple SSH connections.
    with TemporaryDirectory() as temp_dir:
        pwd = os.getcwd()
        # Bazel gives us the same file twice, so dedup here rather than
        # in starlark
        copied = set()
        for s in srcs:
            if ":" in s:
                folder = os.path.join(temp_dir, s[s.find(":") + 1:])
                os.makedirs(folder, exist_ok=True)
                s = os.path.join(pwd, s[:s.find(":")])
                destination = os.path.join(folder, os.path.basename(s))
            else:
                s = os.path.join(pwd, s)
                destination = os.path.join(temp_dir, os.path.basename(s))

            if s in copied:
                continue
            copied.add(s)
            if s.endswith(".stripped"):
                destination = destination[:destination.find(".stripped")]
            shutil.copy2(s, destination)
        # Make sure the folder that gets created on the roboRIO has open
        # permissions or the executables won't be visible to init.
        os.chmod(temp_dir, 0o775)
        # Starter needs to be SUID so we transition from lvuser to admin.
        if args.type != "pi":
            os.chmod(os.path.join(temp_dir, "starterd"), 0o775 | stat.S_ISUID)

        rsync_cmd = ([
            "external/rsync/usr/bin/rsync",
            "-e",
            ssh_path,
            "-c",
            "-r",
            "-v",
            "--perms",
            "-l",
            temp_dir + "/",
        ])

        # If there is only 1 file to transfer, we would overwrite the destination
        # folder.  In that case, specify the full path to the target.
        if len(srcs) == 1:
            rsync_cmd += ["%s:%s/%s" % (ssh_target, target_dir, srcs[0])]
        else:
            rsync_cmd += ["%s:%s" % (ssh_target, target_dir)]

        try:
            subprocess.check_call(rsync_cmd)
        except subprocess.CalledProcessError as e:
            if e.returncode == 127 or e.returncode == 12:
                print("Unconfigured roboRIO, installing rsync.")
                install(ssh_target, "libacl1_2.2.52-r0.310_cortexa9-vfpv3.ipk",
                        'main', ssh_path, scp_path)
                install(ssh_target, "rsync-lic_3.1.3-r0.23_cortexa9-vfpv3.ipk",
                        'extra', ssh_path, scp_path)
                install(ssh_target, "rsync_3.1.3-r0.23_cortexa9-vfpv3.ipk",
                        'extra', ssh_path, scp_path)
                subprocess.check_call(rsync_cmd)
            elif e.returncode == 11:
                # Directory wasn't created, make it and try again.  This keeps the happy path fast.
                subprocess.check_call(
                    [ssh_path, ssh_target, "mkdir", "-p", target_dir])
                subprocess.check_call(rsync_cmd)
            else:
                raise e


if __name__ == "__main__":
    main(sys.argv)
