#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p nix-prefetch-github -p git
#nix-shell -I nixpkgs=../../../../ -i python3 -p "python3.withPackages (ps: with ps; [ nix-prefetch-github ])" -p "git"

import json
import re
import subprocess
import sys

import fetch_sources

def get_github_hash(owner, repo, revision):
    result = subprocess.run(
        ["nix-prefetch-github", owner, repo, "--json", "--rev", revision],
        check=True,
        capture_output=True,
        text=True,
    )
    j = json.loads(result.stdout)
    # Remove False values
    return {k: v for k, v in j.items() if v}

def main():
    pkgs = fetch_sources.PACKAGES
    pkgs.sort(key = lambda pkg: pkg.baseDir)
    existing_sources = {}

    # Fetch hashes from existing sources file
    with open("sources.nix") as f:
        existing_file = f.read()

    source_re = re.compile("(?P<name>[^ ]+) = fetchFromGitHub[^\n]*\n"
        "[^\n]+\n" # owner
        "[^\n]+\n" # repo
        " *rev = \"(?P<rev>[^\"]+)\";\n"
        " *hash = \"(?P<hash>[^\"]+)\";\n"
    )

    for m in source_re.finditer(existing_file):
        if m.group("hash").startswith("sha"):
            print(f"Found {m.group('name')}: {m.group('rev')} -> {m.group('hash')}")
            existing_sources[m.group("name")] = (m.group("rev"), m.group("hash"))
    print()


    # Write new sources file
    with open("sources.nix", "w") as f:
        f.write("# Autogenerated from vk-cts-sources.py\n")
        f.write("{ fetchurl, fetchFromGitHub }:\n")
        f.write("rec {");

        github_re = re.compile("https://github.com/(?P<owner>[^/]+)/(?P<repo>[^/]+).git")

        for pkg in pkgs:
            if isinstance(pkg, fetch_sources.GitRepo):
                ms = github_re.match(pkg.httpsUrl)

                # Check for known hash
                hash = None
                if pkg.baseDir in existing_sources:
                    existing_src = existing_sources[pkg.baseDir]
                    if existing_src[0] == pkg.revision:
                        hash = existing_src[1]

                if hash is None:
                    print(f"Fetching {pkg.baseDir}: {pkg.revision}")
                    hash = get_github_hash(ms.group("owner"), ms.group("repo"), pkg.revision)["hash"]
                    print(f"Got {pkg.baseDir}: {pkg.revision} -> {hash}")

                f.write(f"\n  {pkg.baseDir} = fetchFromGitHub {{\n");
                f.write(f"    owner = \"{ms.group('owner')}\";\n");
                f.write(f"    repo = \"{ms.group('repo')}\";\n");
                f.write(f"    rev = \"{pkg.revision}\";\n");
                f.write(f"    hash = \"{hash}\";\n");
                f.write(f"  }};\n");

        f.write("\n  prePatch = ''\n");
        f.write("    mkdir -p");
        for pkg in pkgs:
            if isinstance(pkg, fetch_sources.GitRepo):
                f.write(f" external/{pkg.baseDir}")
        f.write("\n\n");

        for pkg in pkgs:
            if isinstance(pkg, fetch_sources.GitRepo):
                f.write(f"    cp -r ${{{pkg.baseDir}}} external/{pkg.baseDir}/{pkg.extractDir}\n");

        f.write("  '';\n");

        f.write("}\n");

if __name__ == "__main__":
    main()
