.PHONY: check test clean out validation-output dist-clean release-check help

IMPLEMENTATIONS = php node ecmascript perl lua ruby python go c csharp rust java

check:
	php -l aip-56-reference.php
	./aip-56-reference.php --check
	@set -e; for language in $(IMPLEMENTATIONS); do \
		$(MAKE) -C "implementations/$$language" check; \
	done

test:
	@set -e; for language in $(IMPLEMENTATIONS); do \
		$(MAKE) -C "implementations/$$language" test; \
	done

clean:
	@set -e; for language in $(IMPLEMENTATIONS); do \
		$(MAKE) -C "implementations/$$language" clean; \
	done

out: check
	@set -e; \
	rm -rf out; \
	mkdir -p out/{php,node,ecmascript,perl,lua,ruby,python,go,c,csharp,rust/src,java,test-vectors}; \
	cp aip-56-reference.php implementations/php/Aip56.php implementations/php/README.md out/php/; \
	cp implementations/node/aip56.js implementations/node/README.md out/node/; \
	cp implementations/ecmascript/aip56.mjs implementations/ecmascript/README.md out/ecmascript/; \
	cp implementations/perl/aip56.pl implementations/perl/README.md out/perl/; \
	cp implementations/lua/aip56.lua implementations/lua/README.md out/lua/; \
	cp implementations/ruby/aip56.rb implementations/ruby/README.md out/ruby/; \
	cp implementations/python/aip56.py implementations/python/README.md out/python/; \
	cp implementations/go/aip56.go implementations/go/go.mod implementations/go/README.md out/go/; \
	cp implementations/c/aip56.c implementations/c/README.md out/c/; \
	cp implementations/csharp/Aip56.cs implementations/csharp/Aip56.csproj implementations/csharp/README.md out/csharp/; \
	cp -R implementations/rust/src implementations/rust/Cargo.toml implementations/rust/Cargo.lock implementations/rust/README.md out/rust/; \
	cp implementations/java/Aip56.java implementations/java/README.md out/java/; \
	$(MAKE) -C implementations/c clean check; cp implementations/c/aip56 out/c/aip56; \
	(cd implementations/go && GOEXPERIMENT="" GOCACHE="/tmp/aip56-go-cache" go build -o ../../out/go/aip56 .); \
	$(MAKE) -C implementations/java check; cp implementations/java/*.class out/java/; \
	(cd implementations/rust && cargo build --release); cp implementations/rust/target/release/aip56 out/rust/aip56; \
	if command -v dotnet >/dev/null 2>&1; then dotnet publish implementations/csharp/Aip56.csproj -c Release -f net8.0 -o out/csharp/publish/net8.0 --no-restore; dotnet publish implementations/csharp/Aip56.csproj -c Release -f net10.0 -o out/csharp/publish/net10.0 --no-restore; mkdir -p out/csharp/bin; cp -R implementations/csharp/bin/Release/. out/csharp/bin/; else echo "SKIP C# publish: dotnet is not installed"; fi; \
	cp README.md LICENSE.md AIP-56.md README.wordlist.md wordlist.json wordlist.json.sig wordlist.json.sig.b64 compressed-wordlist.json out/; \
	cp -R test-vectors/. out/test-vectors/; \
	printf '%s\n' '# AIP-56 generated distribution' '' 'Generated by `make out`; this directory is not the source of truth.' '' 'Each language directory contains a self-contained reference implementation. Runtime code embeds the compressed canonical wordlist data; no runtime wordlist file is required.' '' 'The signed wordlist artifacts are included for independent verification and release audit.' > out/README.md; \
	( cd out && find . -type f ! -name SHA256SUMS -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS )

validation-output: out
	@set -e; \
	phrases=$$(mktemp); document=$$(mktemp); \
	trap 'rm -f "$$phrases" "$$document"' EXIT; \
	printf 'PHP canonical: %s\n' "$$(php out/php/aip-56-reference.php --no-pgp)" >> "$$phrases"; \
	printf 'PHP class: %s\n' "$$(php -r 'require "out/php/Aip56.php"; echo \Akadata\Aip56\Aip56::selfContained()->generate();')" >> "$$phrases"; \
	printf 'Node: %s\n' "$$(node out/node/aip56.js)" >> "$$phrases"; \
	printf 'ECMAScript: %s\n' "$$(node --input-type=module -e "import { Aip56 } from './out/ecmascript/aip56.mjs'; console.log((await Aip56.selfContained()).generate())")" >> "$$phrases"; \
	printf 'Perl: %s\n' "$$(perl out/perl/aip56.pl)" >> "$$phrases"; \
	printf 'Lua: %s\n' "$$(lua out/lua/aip56.lua)" >> "$$phrases"; \
	printf 'Ruby: %s\n' "$$(ruby out/ruby/aip56.rb)" >> "$$phrases"; \
	printf 'Python: %s\n' "$$(python3 out/python/aip56.py)" >> "$$phrases"; \
	printf 'Go: %s\n' "$$(out/go/aip56)" >> "$$phrases"; \
	printf 'C: %s\n' "$$(out/c/aip56)" >> "$$phrases"; \
	printf 'C# net8.0: %s\n' "$$(out/csharp/publish/net8.0/Aip56)" >> "$$phrases"; \
	printf 'C# net10.0: %s\n' "$$(out/csharp/publish/net10.0/Aip56)" >> "$$phrases"; \
	printf 'Rust: %s\n' "$$(out/rust/aip56)" >> "$$phrases"; \
	printf 'Java: %s\n' "$$(java -cp out/java Aip56)" >> "$$phrases"; \
	php scripts/validate_phrase_output.php "$$phrases"; \
	printf '%s\n\n' '# AIP-56 Validation Output' > "$$document"; \
	printf '%s\n' 'Generated phrases are random examples from each implementation.' 'They are not deterministic test vectors and must not be used as recovery keys.' '' >> "$$document"; \
	cat "$$phrases" >> "$$document"; \
	php scripts/validate_phrase_output.php "$$document"; \
	mv "$$document" VALIDATION.md

dist-clean:
	rm -rf out

release-check:
	@set -e; \
	if command -v php >/dev/null 2>&1; then \
		php -l aip-56-reference.php; \
		./aip-56-reference.php --check; \
	else \
		echo "SKIP php: php is not installed"; \
	fi; \
	for language in $(IMPLEMENTATIONS); do \
		case "$$language" in \
			php) tools="php" ;; \
			node) tools="node" ;; \
			ecmascript) tools="node php" ;; \
			perl) tools="perl" ;; \
			lua) tools="lua" ;; \
			ruby) tools="ruby" ;; \
			python) tools="python3" ;; \
			go) tools="go" ;; \
			c) tools="cc pkg-config" ;; \
			csharp) tools="dotnet" ;; \
			rust) tools="cargo" ;; \
			java) tools="javac java" ;; \
		esac; \
		missing=""; \
		for tool in $$tools; do \
			if ! command -v "$$tool" >/dev/null 2>&1; then missing="$$missing $$tool"; fi; \
		done; \
		if [ -n "$$missing" ]; then \
			echo "SKIP $$language: missing$$missing"; \
			continue; \
		fi; \
		if [ "$$language" = c ] && ! pkg-config --exists zlib openssl; then \
			echo "SKIP c: zlib or OpenSSL development files are missing"; \
			continue; \
		fi; \
		$(MAKE) -C "implementations/$$language" check; \
	done; \
	git diff --check

help:
	@printf '%s\n' \
		'make check          Run PHP and all implementation checks (strict)' \
		'make test           Run all implementation tests (strict)' \
		'make clean          Remove implementation build/cache artifacts' \
		'make out            Build the generated distributable out/ tree' \
		'make validation-output  Generate and validate VALIDATION.md phrases' \
		'make dist-clean     Remove the generated out/ tree' \
		'make release-check  Check available platforms and report skipped toolchains' \
		'make help           Show these targets'
