override SHELL := /bin/sh
override MAKEFLAGS += --no-print-directory

.DEFAULT_GOAL := help
.DELETE_ON_ERROR:

override FIRMWARE_DIR := firmware
override DOCS_DIR := docs
override SITL_DIR := firmware/tools/sitl
override CONFIGURATOR_DIR := firmware/tools/configurator
override BOARD_DIRS := $(patsubst %/,%,$(wildcard firmware/boards/*/))

override COMPONENT_TARGETS := $(FIRMWARE_DIR) $(DOCS_DIR) firmware/boards $(BOARD_DIRS) \
	$(SITL_DIR) $(CONFIGURATOR_DIR)

override PRIMARY_GOAL := $(firstword $(MAKECMDGOALS))
override ROUTED_GOAL := $(filter $(PRIMARY_GOAL),$(COMPONENT_TARGETS))

ifneq ($(ROUTED_GOAL),)

# The dispatcher reads the original argv so application arguments retain their
# ordering and boundaries even when Make interprets them as goals or variables.
override ROUTE_DEFAULT_TARGET := run
override ROUTE_LOCAL_TARGETS := help
ifeq ($(PRIMARY_GOAL),$(FIRMWARE_DIR))
override ROUTE_LOCAL_TARGETS += fmt clippy test docs pre-commit check clean
endif
ifeq ($(PRIMARY_GOAL),$(DOCS_DIR))
override ROUTE_DEFAULT_TARGET := check
override ROUTE_LOCAL_TARGETS += check
endif
ifneq ($(filter $(PRIMARY_GOAL),$(BOARD_DIRS)),)
override ROUTE_LOCAL_TARGETS += flash
endif

.PHONY: $(PRIMARY_GOAL)

$(PRIMARY_GOAL):
	+@exec python3 scripts/make-argv.py route "$(PRIMARY_GOAL)" make \
		$(ROUTE_DEFAULT_TARGET) $(ROUTE_LOCAL_TARGETS)

# Additional command-line words are application arguments, not outer targets.
.DEFAULT:
	@:

else

.PHONY: help nix-shell build fmt test pre-commit check clean

help: ## Show the command interface (the default)
	@printf '%s\n' 'Kaptan developer commands' '' \
		'Usage: make <directory> -- [arguments...]' \
		'       make <directory> help' \
		'' 'The -- is the standard end of Make options; application flags follow it.' \
		'' 'Repository workflows' \
		'  help                         Show this help' \
		'  nix-shell                    Enter the Nix development shell' \
		'  build                        Build all firmware and documentation' \
		'  fmt                          Check Rust, shell, Python, Nix, and TOML formatting' \
		'  test                         Run Rust, script, and SITL tests' \
		'  pre-commit                   Run fmt, firmware clippy/test/docs, and mdBook checks' \
		'  check                        Run pre-commit plus whitespace checks' \
		'  clean                        Remove generated build artifacts' \
		'' 'Directory targets' \
		'  firmware <target>            fmt, clippy, test, docs, pre-commit, check, or clean' \
		'  firmware -- <cargo args...>  Pass other arguments to cargo' \
		'  firmware/boards -- <args...>' \
		'                               Build and package every board; args go to cargo build' \
		'  firmware/boards/<board> -- <args...>' \
		'                               Build and package one board; args go to cargo build' \
		'  firmware/boards/<board> flash -- <dfu-util args...>' \
		'                               Build, package, and flash one board over DFU' \
		'  docs                         Test and build the mdBook project' \
		'  docs -- <mdbook args...>     Pass explicit arguments to mdbook' \
		'  firmware/tools/configurator -- <args...>' \
		'                               Pass args to kaptan-configurator' \
		'  firmware/tools/sitl -- <args...>' \
		'                               Pass args to kaptan-sim' \
		'' 'Examples' \
		'  make firmware -- test --workspace --locked --offline' \
		'  make firmware clippy' \
		'  make firmware docs' \
		'  make firmware/boards/kakute-f7-mini-v3' \
		'  make firmware/boards/kakute-f7-mini-v3 flash' \
		'  make docs -- build' \
		'  make firmware/tools/configurator -- --source-system 255 --serial /dev/ttyUSB0 --baud 115200' \
		'  make firmware/tools/sitl -- move 5 3 1 --wait'

nix-shell: ## Enter the reproducible Nix development shell
	nix develop

build: ## Build all firmware boards and documentation
	+@$(MAKE) -C firmware/boards run
	+@$(MAKE) -C $(DOCS_DIR) run -- build

fmt:
	+@$(MAKE) -C $(FIRMWARE_DIR) fmt
	shfmt -d $$(rg --files -g '*.sh')
	ruff format --check firmware/tools/sitl/kaptan-sim $$(rg --files -g '*.py')
	nixfmt --check $$(rg --files -g '*.nix')
	taplo format --check $$(rg --files -g '*.toml')

test:
	python3 -m unittest scripts/test-make-argv.py
	+@$(MAKE) -C $(FIRMWARE_DIR) test
	+@$(MAKE) -C $(SITL_DIR) _check

pre-commit: fmt test
	+@$(MAKE) -C $(FIRMWARE_DIR) clippy
	+@$(MAKE) -C $(FIRMWARE_DIR) docs
	+@$(MAKE) -C $(DOCS_DIR) check

check: pre-commit ## Run pre-commit plus whitespace checks
	git diff HEAD --check

clean: ## Remove firmware and documentation build artifacts
	+@$(MAKE) -C $(FIRMWARE_DIR) clean
	+@$(MAKE) -C $(DOCS_DIR) run -- clean

endif
