#
# ** header v3.0
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2018 Research Group Biomedical Physics,
# Max-Planck-Institute for Dynamics and Self-Organization Göttingen
# Copyright (C) 2019-2020 Timm Fitschen (t.fitschen@indiscale.com)
# Copyright (C) 2019-2020 IndiScale GmbH (info@indiscale.com)
# Copyright (C) 2019 Daniel Hornung (d.hornung@indiscale.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# ** end header
#

# Unzip all the external libraries and set up the links in the public folder

SHELL:=/bin/bash
PERCENT=%
BUILD_NUMBER:=$(shell date +$(PERCENT)s)
SQ=\'
ROOT_DIR = $(abspath .)
MISC_DIR = $(abspath misc)
PUBLIC_DIR = $(abspath public)
SSS_BIN_DIR = $(abspath sss_bin)
CONF_CORE_DIR = $(abspath conf/core)
CONF_EXT_DIR = $(abspath conf/ext)
SRC_CORE_DIR = $(abspath src/core)
SRC_EXT_DIR = $(abspath src/ext)
SRC_SSS_DIR = $(abspath src/server_side_scripting)
LIBS_DIR = $(abspath libs)
TEST_CORE_DIR = $(abspath test/core/)
TEST_EXT_DIR = $(abspath test/ext)
TEST_SSS_DIR =$(abspath test/server_side_scripting)
LIBS = fonts css/fonts css/bootstrap.css css/bootstrap-icons.css js/state-machine.js js/jquery.js js/showdown.js js/dropzone.js css/dropzone.css js/loglevel.js js/leaflet.js css/leaflet.css css/images js/leaflet-latlng-graticule.js js/proj4.js js/proj4leaflet.js js/leaflet-coordinates.js css/leaflet-coordinates.css js/leaflet-graticule.js js/bootstrap-select.js css/bootstrap-select.css js/bootstrap-autocomplete.min.js js/plotly.js js/pako.js js/utif.js js/bootstrap.js js/qrcode.js js/ckeditor.js


TEST_LIBS = $(LIBS) js/qunit.js css/qunit.css $(subst $(TEST_CORE_DIR)/,,$(shell find $(TEST_CORE_DIR)/))

LIBS_ZIP = $(wildcard $(LIBS_DIR)/*.zip)
LIBS_SUBDIRS = $(addprefix $(LIBS_DIR)/, js css fonts)

ALL: install

install: clean-ignore-zips install-sss cp-src cp-ext cp-conf $(addprefix $(PUBLIC_DIR)/, $(LIBS)) merge_js build_properties merge_xsl

test: clean-ignore-zips install-sss cp-src cp-ext cp-ext-test cp-conf $(addprefix $(PUBLIC_DIR)/, $(TEST_LIBS)) merge_js build_properties merge_xsl
	@for f in $(shell find $(TEST_EXT_DIR) -type f -iname *.js) ; do \
		sed -i "/EXTENSIONS/a \<script src=\"$${f#$(TEST_EXT_DIR)/}\" ></script>" $(PUBLIC_DIR)/index.html ; \
		echo include $$f; \
	done
	@for f in $(wildcard $(SRC_EXT_DIR)/js/*.js) ; do \
		sed -i "/EXTENSIONS/a \<script src=\"$${f#$(SRC_EXT_DIR)/}\" ></script>" $(PUBLIC_DIR)/index.html ; \
		echo include $$f; \
	done

merge_xsl:
	misc/merge_xsl.sh

merge_js:
	for f in ${BUILDFILELIST} ; do source "$$f" ; done ; \
	JS_DIST_BUNDLE=$${JS_DIST_BUNDLE} AUTO_DISCOVER_MODULES=$$AUTO_DISCOVER_MODULES misc/merge_js.sh $${MODULE_DEPENDENCIES[*]}

EXCLUDE_EXPR = %~ %.backup
BUILDFILELIST = $(sort $(filter-out $(EXCLUDE_EXPR),$(wildcard build.properties.d/*)))
build_properties:
	@set -a -e ; \
	pushd build.properties.files ; \
	for f in ${BUILDFILELIST} ; do echo "processing ../$$f" && source "../$$f" ; done ; \
	popd ; \
	BUILD_NUMBER=$(BUILD_NUMBER) ; \
	PROPS=$$(printenv | grep -e "^BUILD_") ; \
	echo "SET BUILD PROPERTIES:" ; \
	for p in $$PROPS ; do echo "  $$p" ; done; \
	VARS=$$(printenv | grep -e "^BUILD_" | grep -v "^BUILD_NUMBER=" | \
	        sed -E 's/(BUILD_[^=]+)=.*/$${\1}/') ; \
	for f in $$(find $(PUBLIC_DIR) -type f) ; do \
		echo "BUILD FILE: $$f" ; \
		mv "$$f" "$${f}.tmp" ; \
		envsubst "$$VARS" < "$${f}.tmp" | \
		  envsubst "\$${BUILD_NUMBER}" > "$$f" ; \
		rm "$${f}.tmp" ; \
	done
	@echo $(BUILD_NUMBER) > $(PUBLIC_DIR)/.build_number
	@ln -s $(PUBLIC_DIR) $(PUBLIC_DIR)/$(BUILD_NUMBER)
	@ln -s $(PUBLIC_DIR) $(PUBLIC_DIR)/webinterface

TEST_PORT ?= 8000
TIMEOUT = 60
run-test-server: test
	$(MISC_DIR)/unit_test_http_server.py $(TEST_PORT) $(TIMEOUT) False $(PUBLIC_DIR)

keep-test-server: test
	$(MISC_DIR)/unit_test_http_server.py $(TEST_PORT) -1 True $(PUBLIC_DIR)

run-qunit: test
	$(foreach exec, firefox Xvfb xwd,\
	    $(if $(shell which $(exec)),echo "found $(exec)",$(error "No $(exec) in PATH")))

	# start server in background
	$(MISC_DIR)/unit_test_http_server.py $(TEST_PORT) $(TIMEOUT) False $(PUBLIC_DIR) &

	# start firefox with virtual xserver
	Xvfb :1 -screen 0 1024x768x24 &
	DISPLAY=:1 firefox "http://localhost:$(TEST_PORT)/?hidepassed" &

	while [ 1 -eq 1 ]; do \
		sleep 5 ; \
		[ ! -e $(PUBLIC_DIR)/.server_done ] || break; \
	done; \

	# screen shot of firefox
	DISPLAY=:1 xwd -root -out screenshot.xwd

	# stop firefox
	pkill -u $(shell whoami) firefox || true

	# print stuff
	cat $(PUBLIC_DIR)/qunit.log || true
	cat $(PUBLIC_DIR)/.server_done || true
	#
	#
	#
	@if [ ! $$(cat $(PUBLIC_DIR)/.server_done) -eq 0 ] ; then \
		echo "THE TESTS FAILED. PLEASE REVIEW screenshot.xwd FOR DETAILS." ; \
		exit 1; \
	fi

install-sss:
	@set -a -e ; \
	pushd build.properties.files ; \
	for f in ../build.properties.d/* ; do source "$$f" ; done ; \
	popd ; \
	./install-sss.sh $(SRC_SSS_DIR) $(SSS_BIN_DIR)

PYTEST ?= pytest
PIP ?= pip3
test-sss: install-sss
	$(PIP) freeze
	$(PYTEST) -vv $(TEST_SSS_DIR)


CMD_COPY_EXT_FILES = cp -i -r -L
cp-ext:
	# TODO FIXME Base path for not-XSL-expanded files
	mkdir -p $(PUBLIC_DIR)/html
	for f in $(wildcard $(SRC_EXT_DIR)/html/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/html/ ; \
	done
	for f in $(wildcard $(SRC_EXT_DIR)/js/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$f" $(PUBLIC_DIR)/js/ ; \
		sed -i "/JS_EXTENSIONS/a \<xsl:element name=\"script\"><xsl:attribute name=\"src\"><xsl:value-of select=\"concat\(\$$basepath, 'webinterface/${BUILD_NUMBER}$${f#$(SRC_EXT_DIR)}'\)\" /></xsl:attribute></xsl:element>" $(PUBLIC_DIR)/xsl/main.xsl ; \
	done
	for f in $(wildcard $(SRC_EXT_DIR)/css/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$f" $(PUBLIC_DIR)/css/ ; \
		sed -i "/CSS_EXTENSIONS/a \<xsl:element name=\"link\"><xsl:attribute name=\"rel\">stylesheet</xsl:attribute><xsl:attribute name=\"href\"><xsl:value-of select=\"concat\(\$$basepath, 'webinterface/${BUILD_NUMBER}$${f#$(SRC_EXT_DIR)}'\)\" /></xsl:attribute></xsl:element>" $(PUBLIC_DIR)/xsl/main.xsl ; \
		for html in $(PUBLIC_DIR)/html/* ; do \
			echo "$$html"; \
			sed -i "/CSS_EXTENSIONS/a \    <link rel=\"stylesheet\" href=\"$${basepath}/webinterface/${BUILD_NUMBER}$${f#$(SRC_EXT_DIR)}\">" "$$html" ; \
		done \
	done
	for f in $(wildcard $(SRC_EXT_DIR)/pics/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/pics/ ; \
	done
	for f in $(wildcard $(SRC_EXT_DIR)/xsl/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/xsl/ ; \
	done
	for f in $(wildcard $(SRC_EXT_DIR)/include/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" "$(PUBLIC_DIR)/$$(basename "$$f")" ; \
	done

cp-ext-test:
	for f in $(wildcard $(TEST_EXT_DIR)/js/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$f" $(PUBLIC_DIR)/js/ ; \
		sed -i "/JS_EXTENSIONS/a \<xsl:element name=\"script\"><xsl:attribute name=\"src\"><xsl:value-of select=\"concat\(\$$basepath, 'webinterface/${BUILD_NUMBER}$${f#$(SRC_EXT_DIR)}'\)\" /></xsl:attribute></xsl:element>" $(PUBLIC_DIR)/xsl/main.xsl ; \
	done
	mkdir -p $(PUBLIC_DIR)/html
	for f in $(wildcard $(TEST_EXT_DIR)/html/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/html/ ; \
	done
	for f in $(wildcard $(TEST_EXT_DIR)/pics/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/pics/ ; \
	done
	for f in $(wildcard $(TEST_EXT_DIR)/xsl/*) ; do \
		echo "y" | $(CMD_COPY_EXT_FILES) "$$(realpath "$$f")" $(PUBLIC_DIR)/xsl/ ; \
	done

cp-conf: convert-yaml
	mkdir -p $(PUBLIC_DIR)/conf
	if test -d $(CONF_CORE_DIR); then cp -r -t $(PUBLIC_DIR)/conf/ $$(find $(CONF_CORE_DIR)); fi
	if test -d $(CONF_EXT_DIR); then cp -r -t $(PUBLIC_DIR)/conf/ $$(find $(CONF_EXT_DIR)); fi

convert-yaml:
	for f in $$(find $(CONF_EXT_DIR) -type f -iname "*.yaml") ; do \
	  misc/yaml_to_json.py $$f > $${f%.yaml}.json ; \
	done

cp-src:
	cp -r $(SRC_CORE_DIR) $(PUBLIC_DIR)

$(PUBLIC_DIR)/%: $(LIBS_DIR)/%
	ln -s $< $@

$(PUBLIC_DIR)/%: $(TEST_CORE_DIR)/%
	cp -r $< $@

$(PUBLIC_DIR)/%: $(TEST_EXT_DIR)/%
	cp -r $< $@

$(LIBS_DIR)/fonts: unzip
	ln -s $(LIBS_DIR)/bootstrap-icons-1.4.1/fonts/ $@

$(LIBS_DIR)/js/bootstrap.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/bootstrap-5.2.2-dist/js/bootstrap.bundle.min.js $@

$(LIBS_DIR)/css/bootstrap.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/bootstrap-5.2.2-dist/css/bootstrap.min.css $@

$(LIBS_DIR)/css/bootstrap-icons.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/bootstrap-icons-1.4.1/bootstrap-icons.css $@

$(LIBS_DIR)/js/bootstrap-select.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/bootstrap-select-1.14.0-beta3-dev/js/bootstrap-select.min.js $@

$(LIBS_DIR)/css/bootstrap-select.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/bootstrap-select-1.14.0-beta3-dev/css/bootstrap-select.min.css $@

$(LIBS_DIR)/js/jquery.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/jquery-3.6.0.min.js $@

$(LIBS_DIR)/js/showdown.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/showdown-1.8.6/dist/showdown.min.js $@

$(LIBS_DIR)/js/state-machine.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/javascript-state-machine-master/dist/state-machine.min.js $@

$(LIBS_DIR)/css/qunit.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/qunit-2.9.2/qunit-2.9.2.css $@

$(LIBS_DIR)/js/qunit.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/qunit-2.9.2/qunit-2.9.2.js $@

$(LIBS_DIR)/js/dropzone.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/dropzone-5.5.0/dist/dropzone.js $@

$(LIBS_DIR)/css/dropzone.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/dropzone-5.5.0/dist/dropzone.css $@

$(LIBS_DIR)/js/loglevel.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/loglevel-1.6.4/loglevel.min.js $@

$(LIBS_DIR)/js/leaflet.js: unzip $(LIBS_DIR)/js $(LIBS_DIR)/css/leaflet.css
	ln -s $(LIBS_DIR)/leaflet-1.5.1/leaflet.js $@

$(LIBS_DIR)/css/leaflet.css: $(LIBS_DIR)/css/images
	ln -s $(LIBS_DIR)/leaflet-1.5.1/leaflet.css $@

$(LIBS_DIR)/css/images: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/leaflet-1.5.1/images $@

$(LIBS_DIR)/js/leaflet-graticule.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/L.Graticule.js $@

$(LIBS_DIR)/js/bootstrap.bundle.min.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/bootstrap.bundle.min.js $@

$(LIBS_DIR)/js/leaflet-latlng-graticule.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/leaflet.latlng-graticule-20191007/leaflet.latlng-graticule.js $@

$(LIBS_DIR)/js/proj4.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/proj4js-2.5.0/dist/proj4.js $@

$(LIBS_DIR)/js/proj4leaflet.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/Proj4Leaflet-1.0.1/src/proj4leaflet.js $@

$(LIBS_DIR)/js/leaflet-coordinates.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/Leaflet.Coordinates-0.1.5/dist/Leaflet.Coordinates-0.1.5.min.js $@

$(LIBS_DIR)/css/leaflet-coordinates.css: unzip $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/Leaflet.Coordinates-0.1.5/dist/Leaflet.Coordinates-0.1.5.css $@

$(LIBS_DIR)/js/bootstrap-autocomplete.min.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/bootstrap-autocomplete-2.3.5/dist/latest/bootstrap-autocomplete.min.js $@

$(LIBS_DIR)/js/plotly.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/plotly.js-1.52.2/dist/plotly.min.js $@

$(LIBS_DIR)/js/pako.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/pako-dummy/pako.js $@

$(LIBS_DIR)/js/utif.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/UTIF-8205c1f/UTIF.js $@

$(LIBS_DIR)/js/qrcode.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/qrcode-1.4.4/qrcode.min.js $@

$(LIBS_DIR)/js/ckeditor.js: unzip $(LIBS_DIR)/js
	ln -s $(LIBS_DIR)/ckeditor5-build-custom/build/ckeditor.js $@


$(addprefix $(LIBS_DIR)/, js css):
	mkdir $@ || true

$(LIBS_DIR)/css/fonts: $(LIBS_DIR)/css
	ln -s $(LIBS_DIR)/fonts/ $(LIBS_DIR)/css/fonts

.PHONY: clean-ignore-zips
clean-ignore-zips:
	$(RM) -r $(SSS_BIN_DIR)
	$(RM) -r $(PUBLIC_DIR)
	for f in $(LIBS_SUBDIRS); do unlink $$f || $(RM) -r $$f || true; done
	$(RM) .server_done

.PHONY: clean
clean: clean-ignore-zips
	for f in $(patsubst %.zip,%/,$(LIBS_ZIP)); do $(RM) -r $$f; done

.PHONY: unzip
unzip:
	for f in $(LIBS_ZIP); do echo "unzip $$f" ; unzip -u -q -o -d libs $$f; done


PYLINT ?= pylint
PYTHON_FILES = $(subst $(ROOT_DIR)/,,$(shell find $(ROOT_DIR)/ -iname "*.py"))
pylint: $(PYTHON_FILES)
	for f in $(PYTHON_FILES); do $(PYLINT) -d all -e E,F $$f || exit 1; done


# Compile the standalone documentation
.PHONY: doc
doc:
	$(MAKE) -C src/doc html
