SHELL=/bin/bash -o pipefail
INTERACTIVE:=$(shell [ -t 0 ] && echo 1)

ifdef INTERACTIVE
CLEAN_ANSI=
else
CLEAN_ANSI=| sed -r 's/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g'
endif

CXX := clang++

CXX_FLAGS := -Wall -Wextra -Werror -std=c++20 \
	     -isystem include/ -I/opt/homebrew/opt/icu4c/include \
	     -DJVALIDATE_USE_EXCEPTIONS -DJVALIDATE_LOAD_FAILURE_AS_FALSE_SCHEMA

LD_FLAGS := -L/opt/homebrew/lib -L/opt/homebrew/opt/icu4c/lib -licuuc -licui18n -lada-idna

TEST_DIR := tests/
INCLUDE_DIR := include/

HEADERS := $(shell find $(INCLUDE_DIR) -name *.h)

TEST_HEADERS := $(wildcard $(TEST_DIR)*.h)
TEST_SOURCES := $(wildcard $(TEST_DIR)*.cxx)
TEST_OBJECTS := $(patsubst %.cxx, .build/%.o, $(TEST_SOURCES))
TEST_BINARIES := .build/bin/selfvalidate .build/bin/annotation_test .build/bin/extension_test
EXECUTE_TESTS := $(patsubst %, %.done, $(TEST_BINARIES))

EXCLUDED_FORMAT_TESTS :=
EXCLUDED_FORMAT_TESTS := $(shell printf ":*optional_format_%s*" $(EXCLUDED_FORMAT_TESTS) | cut -c2-)
EXCLUDED_TESTS := content *ecmascript_regex zeroTerminatedFloats
EXCLUDED_TESTS := $(shell printf ":*optional_%s" $(EXCLUDED_TESTS) | cut -c2-):$(EXCLUDED_FORMAT_TESTS)
EXCLUDED_TEST_CASES = "*leap second*"

.PHONY: all
all: validate
all: run-test

.PHONY: debug
debug: CXX_FLAGS := $(CXX_FLAGS) -g -fsanitize=address
debug: LD_FLAGS := $(LD_FLAGS) -fsanitize=address
debug: test

.PHONY: clean
clean:
	@ rm -rf .build

.PHONY: test
test: $(TEST_BINARIES)

.PHONY: run-test
run-test: test
run-test: $(EXECUTE_TESTS)

.PHONY: validate
validate: .build/bin/validate

.PHONY: annotation_test
annotation_test: .build/bin/annotation_test.done

.PHONY: extension_test
extension_test: .build/bin/extension_test.done

.PHONY: selfvalidate_test
selfvalidate_test: .build/bin/selfvalidate_test.done

# Actual Definitions (non-phony)
.build/tests/%.o: tests/%.cxx $(HEADERS) $(TEST_HEADERS)
	@ mkdir -p .build/tests
	$(CXX) $(CXX_FLAGS) -c $< -o $@ -Wno-character-conversion


.build/bin/validate: src/validate.cxx $(HEADERS)
	@ mkdir -p .build/bin
	$(CXX) $< -o $@ $(CXX_FLAGS) $(LD_FLAGS) -ljsoncpp -lcurl


.build/bin/selfvalidate: .build/tests/selfvalidate_test.o
	@ mkdir -p .build/bin
	@ rm -f $@.done
	$(CXX) $< -o $@ $(LD_FLAGS) -ljsoncpp -lgmock -lcurl -lgtest

.build/bin/selfvalidate.done: .build/bin/selfvalidate
	.build/bin/selfvalidate --gtest_filter=-$(EXCLUDED_TESTS) \
		--json_case_filter=-$(EXCLUDED_TEST_CASES) $(CLEAN_ANSI)
	@ touch $@


.build/bin/annotation_test: .build/tests/annotation_test.o
	@ mkdir -p .build/bin
	@ rm -f .build/test/annotation_test.done
	$(CXX) $< -o $@ $(LD_FLAGS) -ljsoncpp -lgmock -lgtest

.build/bin/annotation_test.done: .build/bin/annotation_test
	.build/bin/annotation_test $(CLEAN_ANSI)
	@ touch $@


.build/bin/extension_test: .build/tests/extension_test.o
	@ mkdir -p .build/bin
	@ rm -f .build/test/extension_test.done
	$(CXX) $< -o $@ $(LD_FLAGS) -ljsoncpp -lgmock -lgtest

.build/bin/extension_test.done: .build/bin/extension_test
	.build/bin/extension_test $(CLEAN_ANSI)
	@ touch $@
