BASE_PATH:=$(shell git rev-parse --show-toplevel)
COMMON_PATH:=$(BASE_PATH)/_common

binaries:=$(sort $(binaries) generator checker solver)
include $(COMMON_PATH)/Makefile.base

TESTS?=\
	$(shell $(COMMON_PATH)/gen-tests.sh samples.txt samp-) \
	$(shell $(COMMON_PATH)/gen-tests.sh tests.txt)
TESTS:=$(TESTS)
TEST_GEN_FILES:=$(foreach i, $(TESTS), tests/$(i).gen)
TEST_IN_FILES:=$(foreach i, $(TESTS), tests/$(i).in)
TEST_OUT_FILES:=$(foreach i, $(TESTS), tests/$(i).out)
export SOLUTION?=$(BUILD_PATH)/solver
CUSTOM_GRADER_SOURCE:=
DEFAULT_GRADER_NEEDED:=

ifneq ($(filter grader, $(binaries)), )
export GRADER?=$(BUILD_PATH)/grader
CUSTOM_GRADER_SOURCE:=grader.cpp
else ifndef GRADER

ifneq ($(INTERACTIVE), )
$(error Custom grader required for interactive task)
endif

export GRADER:=$(COMMON_PATH)/default-grader/build/grader
DEFAULT_GRADER_NEEDED:=$(GRADER)
endif

export GENERATOR_BIN:=$(BUILD_PATH)/generator
export CHECKER_BIN:=$(BUILD_PATH)/checker
export SOLVER_BIN:=$(BUILD_PATH)/solver

export INTERACTIVE_HANDLER:=$(COMMON_PATH)/default-grader/build/discussion

# Never delete these even if they're intermediary files
.SECONDARY: $(TEST_GEN_FILES) $(TEST_IN_FILES) $(TEST_OUT_FILES)

# These are usually generated automatically, but not in all scenarios
$(TEST_GEN_FILES) &: tests.txt
	$(COMMON_PATH)/gen-tests.sh samples.txt samp- > /dev/null
	$(COMMON_PATH)/gen-tests.sh tests.txt > /dev/null

tests/%.in: tests/%.gen $(GENERATOR_BIN) $(CHECKER_BIN)
	@test="$$(cat $<)"; \
	if [[ $$test = @* ]]; then \
		manual="$${test#@}"; \
		echo -- Checking manual test $* input $$manual; \
		cp $$manual $@.tmp; \
	else \
    	echo -- Generating and checking test $* input; \
    	echo "$(GENERATOR_BIN) $(shell cat $<) > $@.tmp"; \
    	$(GENERATOR_BIN) $(shell cat $<) > $@.tmp; \
	fi
	@$(COMMON_PATH)/run-checker.sh $(CHECKER_BIN) $@.tmp
	mv $@.tmp $@

ifeq ($(INTERACTIVE), )
tests/%.out: tests/%.in tests/%.gen $(SOLVER_BIN)
	@echo -- Generating test $* output
	$(SOLVER_BIN) $(shell cat tests/$*.gen) < $< > $@
else
# Empty outputs to appease CSES importer
tests/%.out: tests/%.gen
	@touch $@
endif

.PHONY: test-inputs test-outputs
test-inputs: $(TEST_IN_FILES)
test-outputs: $(TEST_OUT_FILES)

.PHONY: tests
tests: test-inputs test-outputs

$(COMMON_PATH)/default-grader/build/%: $(wildcard $(COMMON_PATH)/default-grader/*)
	$(MAKE) -C $(COMMON_PATH)/default-grader build/$*

.PHONY: run-tests
ifeq ($(INTERACTIVE), )
run-tests: tests all $(DEFAULT_GRADER_NEEDED)
	@echo -- Running tests on $(SOLUTION) graded by $(GRADER)
	$(COMMON_PATH)/run-tests.sh $(TESTS)
else
run-tests: tests all $(INTERACTIVE_HANDLER)
	@echo -- Running tests on $(SOLUTION) graded by $(GRADER) '(interactive)'
	$(COMMON_PATH)/run-tests-interactive.sh $(TESTS)
endif

PACKAGE_FILES=problem.yaml checker.cpp statement*.md $(CUSTOM_GRADER_SOURCE) \
	$(TEST_IN_FILES) $(TEST_OUT_FILES) $(wildcard files/*)

.PHONY: package package-update
package: tests
	@echo -- Packaging $(words $(TESTS)) tests and auxiliary files
	rm -f package.zip
	zip package.zip $(PACKAGE_FILES)

package-update: tests
	@echo -- 'Updating package (extra tests will not be removed)'
	zip -u package.zip $(PACKAGE_FILES)

# alias
.PHONY: package-tests
package-tests: package

.PHONY: clean-tests
clean-tests:
	rm tests/*

FMT?=%
BRUTE_FILE?=brute
export BRUTE_FILE

.PHONY: brutetest
brutetest: all $(DEFAULT_GRADER_NEEDED)
	@echo -- Brute testing $(SOLUTION) against $(SOLVER_BIN) graded by $(GRADER)
	@echo -- Using FMT=\''$(FMT)'\' to generate tests, % replaced by test no.
	$(COMMON_PATH)/brutetest.sh
