SHELL=bash
export THRUK_CONFIG=$(shell pwd)
export TEST_AUTHOR=1
THRUK=cd ../../.. && ./script/thruk
STARTUPWAIT=300
ERROR_TAIL=50
EXPECTED_BACKENDS=1
INTERACTIVE:=$(shell [ -t 0 ] && echo 1)
ifdef INTERACTIVE
  DOCKER_COMPOSE_TTY=
  DOCKER_COMPOSE_LOGS=
else
  DOCKER_COMPOSE_TTY=-T
  DOCKER_COMPOSE_LOGS=--no-color
endif
export COMPOSE_HTTP_TIMEOUT=180
export COMPOSE_BAKE=true
ifeq ($(shell uname),Linux)
  TIMEOUT_CMD=timeout -v 30m
else
  TIMEOUT_CMD=
endif

wait_start:
	$(THRUK) cache clean
	for x in $$(seq $(STARTUPWAIT)); do \
	   if [ $$(docker compose logs | grep "failed=" | grep -v "failed=0" | wc -l) -gt 0 ]; then $(MAKE) wait_start_failed; exit 1; fi; \
	   if [ $$(docker compose logs | grep "| ERROR" | wc -l) -gt 0 ]; then $(MAKE) wait_start_failed; exit 1; fi; \
	   if [ $$($(THRUK) -l 2>&1 | grep -v ^Def | grep -v ^- | grep -v ERROR | grep OK | wc -l) -eq $(EXPECTED_BACKENDS) ]; then break; else sleep 1; fi; \
	   if [ $$x -eq $(STARTUPWAIT) ]; then $(MAKE) wait_start_failed; exit 1; fi; \
	done
	$(THRUK) -l
	$(MAKE) extra_wait_start
	@$(MAKE) start_info

start_info:
	@echo "***********************************************************"
	@echo "Thruk is available at: http://$$(docker compose exec $$(docker compose config --services | sort | head -n1) ip a | grep 'inet ' | grep -v 127.0 | awk '{ print $$2 }' | head -n1 | sed -e 's/\/.*$$//')/demo/thruk/"
	@echo "***********************************************************"

wait_start_failed: wait_start_short_errors non_interactive_only
	$(MAKE) wait_start_info

wait_start_short_errors:
	@echo "### $@: $$(date "+%FT%T.%N")"
	-echo "ERROR: startup failed"
	-docker compose logs | grep "| ERROR"
	-docker compose logs | grep "failed=" | grep -v "failed=0"

wait_start_info:
	@echo "### $@: $$(date "+%FT%T.%N")"
	-echo "ERROR: startup failed"
	-test -e thruk.conf && $(THRUK) -vvv -l
	-docker ps
	-docker compose logs --tail=30 $(DOCKER_COMPOSE_LOGS) -t | sort
	$(MAKE) wait_start_failed_extra

wait_start_failed_extra:

test: wait_start
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) disable_watcher_from_tests
	cd ../../.. && PERL_DL_NONLAZY=1 /usr/bin/env perl "-MExtUtils::Command::MM" "-e" "test_harness(0)" $(shell pwd)/t/*.t \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) extra_test \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )
	$(MAKE) enable_watcher_from_tests
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) test_docker_logs

test_verbose: wait_start
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) disable_watcher_from_tests
	cd ../../.. && PERL_DL_NONLAZY=1 /usr/bin/env perl "-MExtUtils::Command::MM" "-e" "test_harness(1)" $(shell pwd)/t/*.t \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) extra_test_verbose \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )
	$(MAKE) enable_watcher_from_tests
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) test_docker_logs_verbose

# run thruk commands, ex.: make thruk -- r /services or make thruk ARGS="-l -vv"
thruk:
	$(THRUK) $(ARGS) $(filter-out $@,$(MAKECMDGOALS))

testf:
	$(MAKE) disable_watcher_from_tests
	TESTS=$$(ls -1 $(shell pwd)/t/*.t | grep "$(filter-out $@,$(MAKECMDGOALS))"); \
	if [ "$$TESTS" != "" ]; then \
		cd ../../.. && PERL_DL_NONLAZY=1 /usr/bin/env perl "-MExtUtils::Command::MM" "-e" "test_harness(1)" $$TESTS; \
	fi
	$(MAKE) enable_watcher_from_tests

testfl:
	$(MAKE) disable_watcher_from_tests
	set -x ; \
	TESTS=$$(ls -1 $(shell pwd)/t/local/*.t | grep "$(filter-out $@,$(MAKECMDGOALS))" | sed -e 's=$(PWD)=/test=g'); \
	if [ "$$TESTS" != "" ]; then \
		$(MAKE) extra_test_verbose $$TESTS; \
	fi
	$(MAKE) enable_watcher_from_tests

test_docker_logs:
	cd ../../.. && PERL_DL_NONLAZY=1 /usr/bin/env perl "-MExtUtils::Command::MM" "-e" "test_harness(0)" $(shell pwd)/../_common/t/999*.t \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )

test_docker_logs_verbose:
	cd ../../.. && PERL_DL_NONLAZY=1 /usr/bin/env perl "-MExtUtils::Command::MM" "-e" "test_harness(1)" $(shell pwd)/../_common/t/999*.t \
		|| ( cd $(shell pwd) && $(MAKE) failed_test )

failed_test: non_interactive_only
	$(MAKE) failed_test_info

failed_test_info:
	@echo "### $@: $$(date "+%FT%T.%N")"
	-echo "ERROR: test failed"
	-docker ps
	-docker compose logs --tail=30 $(DOCKER_COMPOSE_LOGS) -t | sort
	for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}:"; \
			if docker exec -t --user root $$container test -d /opt/omd/sites/demo; then \
				echo "**** $${svc}_$${index} - apache/error_log:"; \
				docker exec -t --user root $$container tail -$(ERROR_TAIL) /opt/omd/sites/demo/var/log/apache/error_log; \
				echo "**** $${svc}_$${index} - thruk.log:"; \
				docker exec -t --user root $$container tail -$(ERROR_TAIL) /opt/omd/sites/demo/var/log/thruk.log; \
				echo "**** $${svc}_$${index} - naemon.log:"; \
				docker exec -t --user root $$container tail -$(ERROR_TAIL) /opt/omd/sites/demo/var/log/naemon.log; \
			fi; \
			echo "***"; \
		done; \
	done
	-test -e thruk.conf && $(THRUK) -vvv -l
	-$(MAKE) extra_failed_test
	exit 1

extra_failed_test:
	exit 1

ifdef INTERACTIVE
non_interactive_only:
	exit 1
remove_interactive_only_reload_file:
	$(MAKE) enable_watcher
else
non_interactive_only:
	:
remove_interactive_only_reload_file:
	:
endif

server:
	test -f thruk_local.conf || exit 1
	cd ../../.. && THRUK_PERFORMANCE_DEBUG=1 ./script/thruk_server.pl -r

web:
	@python3 -m webbrowser ${PLACK_TEST_EXTERNALSERVER_URI}thruk/

pre_prepare:

prepare: base_images
	$(MAKE) pre_prepare
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(TIMEOUT_CMD) docker compose --progress plain build
	-mkdir -p ../../../var/tmp && chmod 777 ../../../var/tmp
	docker compose up --remove-orphans -d
	docker ps
	@docker compose logs -t $(DOCKER_COMPOSE_LOGS) -f | while read LOGLINE; do \
		echo "$${LOGLINE}"; \
		[[ "$${LOGLINE}" == *"Starting Apache web server"* ]] && pkill -P $$$$ "docker" -9 && exit 0; \
		[[ "$${LOGLINE}" == *"ci container ready"* ]]         && pkill -P $$$$ "docker" -9 && exit 0; \
		[[ "$${LOGLINE}" == *"ERROR"* ]]                      && pkill -P $$$$ "docker" -9 && exit 1; \
		[[ "$${LOGLINE}" == *"exited with code"* ]]           && pkill -P $$$$ "docker" -9 && exit 1; \
	done
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) extra_prepare
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) remove_interactive_only_reload_file

clean:
	@echo "### $@: $$(date "+%FT%T.%N")"
	docker compose down --volumes --remove-orphans
	docker compose kill
	docker compose rm --force --volumes
	-if test -e thruk.conf; then $(THRUK) cache clean all; fi || :
	@echo "### $@: $$(date "+%FT%T.%N")"
	$(MAKE) extra_clean
	@echo "### $@: $$(date "+%FT%T.%N")"

clean_docker_killall:
	-docker network prune -f
	-[ $$(docker ps -q | wc -l) -eq 0 ] || docker kill $$(docker ps -q)

base_images:
	if $$(grep FROM */Dockerfile | awk '{ print $$2 }' | grep local/ >/dev/null); then make -C ../_common build; fi

update:
	@echo "### $@: $$(date "+%FT%T.%N")"
	docker compose pull --ignore-buildable --include-deps
	for IMG in $$(grep FROM */Dockerfile | awk '{ print $$2 }' | grep -v local/ | sort -u); do docker pull $$IMG; done
	if $$(grep FROM */Dockerfile | awk '{ print $$2 }' | grep local/ >/dev/null); then make -C ../_common update; fi
	@echo "### $@: $$(date "+%FT%T.%N")"

enable_watcher:
	@echo "### $@: $$(date "+%FT%T.%N")"
	@for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}"; \
			if docker exec -t --user root $$container test -d /opt/omd/sites/demo; then \
				docker exec -t --user root $$container rm -f /omd/sites/demo/.THRUK_RESTARTER_DISABLED; \
				docker exec -t --user root $$container /bin/sh -c "omd status demo apache -b >/dev/null apache && omd reload demo apache"; \
			fi || : ; \
		done; \
	done

disable_watcher:
	@echo "### $@: $$(date "+%FT%T.%N")"
	@for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}"; \
			if docker exec -t --user root $$container test -d /opt/omd/sites/demo; then \
				docker exec -t --user root $$container touch /omd/sites/demo/.THRUK_RESTARTER_DISABLED; \
			fi || : ; \
		done; \
	done

disable_watcher_from_tests:
	@echo "### $@: $$(date "+%FT%T.%N")"
	@for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}"; \
			if docker exec -t --user root $$container test -d /opt/omd/sites/demo; then \
				if ! docker exec -t --user root $$container test -e /opt/omd/sites/demo/.THRUK_RESTARTER_DISABLED; then \
					docker exec -t --user root $$container touch /omd/sites/demo/.THRUK_RESTARTER_DISABLED; \
					docker exec -t --user root $$container touch /omd/sites/demo/.THRUK_RESTARTER_DISABLED.TMP; \
				fi; \
			fi || : ; \
		done; \
	done

enable_watcher_from_tests:
	@echo "### $@: $$(date "+%FT%T.%N")"
	@for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}"; \
			if docker exec -t --user root $$container test -e /opt/omd/sites/demo/.THRUK_RESTARTER_DISABLED.TMP; then \
				docker exec -t --user root $$container rm -f /omd/sites/demo/.THRUK_RESTARTER_DISABLED; \
				docker exec -t --user root $$container rm -f /omd/sites/demo/.THRUK_RESTARTER_DISABLED.TMP; \
			fi || : ; \
		done; \
	done

cron_stop:
	@echo "### $@: $$(date "+%FT%T.%N")"
	for svc in $$(docker compose config --services | sort); do \
		index=0; \
		for container in $$(docker compose ps -q $$svc); do \
			index=$$(( index + 1 )); \
			echo "*** $${svc}_$${index}"; \
			if docker exec -t --user root $$container test -d /opt/omd/sites/demo; then \
				echo "***"; \
				echo "*** $${svc}_$${index}"; \
				docker exec -t --user root $$container omd stop demo crontab; \
				echo "***"; \
			fi; \
		done; \
	done


extra_wait_start:

extra_clean:

extra_prepare:

extra_test:

extra_test_verbose:

# just skip unknown make targets
.DEFAULT:
	@if [[ "$(MAKECMDGOALS)" =~ ^(thruk|testf) ]]; then \
		: ; \
	else \
		echo "unknown make target(s): $(MAKECMDGOALS)"; \
		exit 1; \
	fi
