#!/usr/bin/env dash
#──────────────────────────────────────────────────────────────────────────────┐
# SPDX-FileCopyrightText: 2025 toastal <https://toast.al/contact/>             │
# SPDX-License-Identifier: MPL-2.0                                             │
#──────────────────────────────────────────────────────────────────────────────┘
# Generates a build.ninja from a Nickel schema
#
# Required tools:
# • POSIX shell
# • fd
# • jq
# • nickel
# • xargs (findutils)
set -eu

NCL_FILE="${1:-"ninja.ncl"}"

# Resolve queries (glob or regex) into a JSON object piped in as a
# NUL-separated string
#
# Arguments:
#    $1 = mode ("glob" or "regex")
# Returns:
#    JSON object mapping query → space-separated results
resolve_query() {
	mode="$1"

	xargs -0 -I{} sh -c '
		q="{}"

		nul_to_json_array() {
			jq -Rs "split(\"\u0000\") | map(select(length > 0))"
		}

		json_kv_array() {
			jq -c --arg k "$1" "{ (\$k): . }"
		}

		case "'"$mode"'" in
			realpath)
				if [ -f "$q" ]; then
					realpath "$q" | tr -d "\n"
				else
					printf ""
				fi
				;;
			glob)
				dir="$(dirname "$q")"
				if [ -d "$dir" ]; then
					pattern="$(basename "$q")"
					fd --color never --absolute-path --glob "$pattern" "$dir" --print0
				else
					printf ""
				fi
				;;
			regex)
				pattern="$(basename "$q")"
				if [ -d "$dir" ]; then
					dir="$(dirname "$q")"
					fd --color never --absolute-path --regex "$pattern" "$dir" --print0
				else
					printf ""
				fi
				;;
			*) exit 1 ;;
		esac |
		nul_to_json_array |
		json_kv_array "$q"
	' |
		jq -s 'add // {}'
}

realpaths_JSON_file="$(mktemp "${TMPDIR:-/tmp}/ninja-realpaths.XXXXXX.json")"
globs_JSON_file="$(mktemp "${TMPDIR:-/tmp}/ninja-globs.XXXXXX.json")"
regexes_JSON_file="$(mktemp "${TMPDIR:-/tmp}/ninja-regexes.XXXXXX.json")"
tmp_out="$(mktemp "${TMPDIR:-/tmp}/ninja-build.XXXXXX")"
trap 'rm -f "$globs_JSON_file" "$regexes_JSON_file" "$tmp_out"' EXIT INT TERM HUP

# Export queries from Nickel & resolve queries into JSON temp files to avoid
# escaping issues
nickel export --format text "$NCL_FILE" --field realpaths_query |
	resolve_query realpath >"$realpaths_JSON_file"

nickel export --format text "$NCL_FILE" --field globs_query |
	resolve_query glob >"$globs_JSON_file"

nickel export --format text "$NCL_FILE" --field regexes_query |
	resolve_query regex >"$regexes_JSON_file"

# Generate ninja.build by merging NCL_FILE with resolved JSON temp files
cat <<EOF | nickel export --format text --field "to_build_ninja"
let { InjectedPaths, Schema, .. } = import "build-ninja.ncl" in
let original_schema = import "$NCL_FILE" in
let injected_paths | InjectedPaths =  {
	realpaths = import "$realpaths_JSON_file" as 'Json,
	globs = import "$globs_JSON_file" as 'Json,
	regexes = import "$regexes_JSON_file" as 'Json,
}
in
original_schema & injected_paths | Schema
EOF
