#!/usr/bin/env python3

import argparse
import hashlib
from pathlib import Path
import requests
import subprocess
import sys

def get_hydra_store_path(url):
    """
    Accepts an url to a hydra build.
    Can be:
    https://hydra.clerie.de/job/nixfiles/nixfiles/iso/latest-finished
    Or:
    https://hydra.clerie.de/build/917
    """

    r = requests.get(url, headers={"Accept": "application/json"})
    r.raise_for_status()

    return Path(r.json()["buildoutputs"]["out"]["path"])


def cli():
    parser = argparse.ArgumentParser(
        prog="update-from-hydra",
        description="Fetch the latest build of a Hydra job and set it as a specified symlink",
    )
    parser.add_argument("hydra_url")
    parser.add_argument("update_path")
    parser.add_argument("cache_store_uri")
    args = parser.parse_args()
    hydra_url = args.hydra_url
    update_path = Path(args.update_path).absolute()
    cache_store_uri = args.cache_store_uri

    print("Update url:", hydra_url)
    print("Path to update:", update_path)

    current_store_path = None

    if update_path.exists():
        if not update_path.is_symlink():
            print("Path to update is not a symlink")
            exit(1)

        current_store_path = update_path.readlink()
        print("Current store path:", current_store_path)
    else:
        print("No current store path, update path does not exist")

    print("Look up Hydra build metadata")
    hydra_store_path = get_hydra_store_path(hydra_url)
    print("Store path in hydra:", hydra_store_path)

    if current_store_path == hydra_store_path:
        print("Current store path is up to date")
        exit()

    print("Downloading new store paths")
    subprocess.run(["nix", "copy", "--from", cache_store_uri, hydra_store_path])
    print("Finished downloading")

    print("Updating path to update")
    update_path.parent.mkdir(parents=True, exist_ok=True)
    tmp_update_path = update_path.parent / ( update_path.name + ".new")
    print("Creating temporary symlink:", tmp_update_path)
    tmp_update_path.symlink_to(hydra_store_path)
    print("Rename symlink to:", update_path)
    tmp_update_path.rename(update_path)

    print("Adding to gcroot")
    try:
        gcroots_dir = Path("/nix/var/nix/gcroots/update-from-hydra")
        update_dir_hash = hashlib.sha256(bytes(update_path)).hexdigest()
        gcroots_dir.mkdir(parents=True, exist_ok=True)
        gcroots_symlink = gcroots_dir / update_dir_hash
        tmp_gcroots_symlink = gcroots_dir / (update_dir_hash + ".new")
        print("Creating temporary symlink:", tmp_gcroots_symlink)
        tmp_gcroots_symlink.symlink_to(update_path)
        print("Rename symlink to:", gcroots_symlink)
        tmp_gcroots_symlink.rename(gcroots_symlink)
    except PermissionError:
        print("Unable to create garbage collector root") 


if __name__ == "__main__":
    cli()