# SPDX-FileCopyrightText: 2023-2025 KUNBUS GmbH
#
# SPDX-License-Identifier: GPL-2.0-or-later

# extract name from package.json
# PACKAGE_NAME := $(shell awk '/"name":/ {gsub(/[",]/, "", $$2); print $$2}' package.json)


# On Unix systems like macOS overwrite BSD tools with GNU implementation (e.g. /opt/homebrew/bin/gtar)
HOST_OS := $(shell uname)
TAR := /usr/bin/tar
AWK := /usr/bin/awk

ifeq ($(HOST_OS),Darwin)
TAR := $(shell whereis -bq gtar)
AWK := $(shell whereis -bq gawk)
endif

RPM_NAME := cockpit-revpi-$(PACKAGE_NAME)
VERSION := $(shell T=$$(git describe 2>/dev/null) || T=1; echo $$T | tr '-' '.')
ifeq ($(TEST_OS),)
TEST_OS = centos-8-stream
endif
export TEST_OS
TARFILE=$(RPM_NAME)-$(VERSION).tar.xz
NODE_CACHE=$(RPM_NAME)-node-$(VERSION).tar.xz
SPEC=$(RPM_NAME).spec
PREFIX ?= /usr/local
APPSTREAMFILE=com.revolutionpi.cockpit.$(PACKAGE_NAME).metainfo.xml
APPSTREAMFILE_PATH=src/$(PACKAGE_NAME)/$(APPSTREAMFILE)
VM_IMAGE=$(CURDIR)/test/images/$(TEST_OS)
# check for node_modules/
NODE_MODULES_TEST=node_modules/
# one example file in dist/ from bundler to check if that already ran
DIST_TEST=dist/$(PACKAGE_NAME)/manifest.json
# one example file in pkg/lib to check if it was already checked out
COCKPIT_REPO_STAMP=pkg/lib/cockpit-po-plugin.js
# common arguments for tar, mostly to make the generated tarballs reproducible
TAR_ARGS = --sort=name --mtime "@$(shell git show --no-patch --format='%at')" --mode=go=rX,u+rw,a-s --numeric-owner --owner=0 --group=0

all: $(DIST_TEST)

# checkout common files from Cockpit repository required to build this project;
# this has no API stability guarantee, so check out a stable tag when you start
# a new project, use the latest release, and update it from time to time
COCKPIT_REPO_FILES = \
	pkg/lib \
	pkg/shell \
	test/common \
	test/static-code \
	$(NULL)

COCKPIT_REPO_URL = https://github.com/cockpit-project/cockpit.git
# This defines the version of the imported cockpit.js library. Update with care and thorough testing only!
COCKPIT_REPO_COMMIT = 2aebbbf2cc0302f21287bd278f5a3161aa149cbb # 311 + 1 commits

$(COCKPIT_REPO_FILES): $(COCKPIT_REPO_STAMP)
COCKPIT_REPO_TREE = '$(strip $(COCKPIT_REPO_COMMIT))^{tree}'
$(COCKPIT_REPO_STAMP): Makefile
	@git rev-list --quiet --objects $(COCKPIT_REPO_TREE) -- 2>/dev/null || \
	    git fetch --no-tags --no-write-fetch-head --depth=1 $(COCKPIT_REPO_URL) $(COCKPIT_REPO_COMMIT)
	git archive $(COCKPIT_REPO_TREE) -- $(COCKPIT_REPO_FILES) | tar x

#
# i18n
#

LINGUAS=$(basename $(notdir $(wildcard src/$(PACKAGE_NAME)/po/*.po)))

src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).js.pot:
	xgettext --default-domain=$(PACKAGE_NAME) --output=$@ --language=C --keyword= \
		--add-comments=Translators: \
		--keyword=_:1,1t --keyword=_:1c,2,2t --keyword=C_:1c,2 \
		--keyword=N_ --keyword=NC_:1c,2 \
		--keyword=gettext:1,1t --keyword=gettext:1c,2,2t \
		--keyword=ngettext:1,2,3t --keyword=ngettext:1c,2,3,4t \
		--keyword=gettextCatalog.getString:1,3c --keyword=gettextCatalog.getPlural:2,3,4c \
		--from-code=UTF-8 $$(find src/$(PACKAGE_NAME) -name '*.js' -o -name '*.jsx')

src/common/po/common.js.pot:
	# This can not be integrated so the package js.pot target. It must be a target of itself,
	# which is at the end of the hole .pot process.
	mkdir -p src/common/po
	xgettext --default-domain=common --output=$@ --language=C --keyword= \
		--add-comments=Translators: \
		--keyword=_:1,1t --keyword=_:1c,2,2t --keyword=C_:1c,2 \
		--keyword=N_ --keyword=NC_:1c,2 \
		--keyword=gettext:1,1t --keyword=gettext:1c,2,2t \
		--keyword=ngettext:1,2,3t --keyword=ngettext:1c,2,3,4t \
		--keyword=gettextCatalog.getString:1,3c --keyword=gettextCatalog.getPlural:2,3,4c \
		--from-code=UTF-8 $$(find src/common -name '*.js' -o -name '*.jsx')

src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).html.pot: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
	pkg/lib/html2po.js -o $@ $$(find src/$(PACKAGE_NAME) -name '*.html')

src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).manifest.pot: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
	pkg/lib/manifest2po.js src/$(PACKAGE_NAME)/manifest.json -o $@

src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).metainfo.pot: $(APPSTREAMFILE_PATH)
	xgettext --default-domain=$(PACKAGE_NAME) --output=$@ $<

src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).pot: src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).html.pot src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).js.pot src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).manifest.pot src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).metainfo.pot src/common/po/common.js.pot
	msgcat --sort-output --output-file=$@ $^

src/$(PACKAGE_NAME)/po/LINGUAS:
	echo $(LINGUAS) | tr ' ' '\n' > $@

pot: src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).pot

potclean:
	# Remove all autogenerated pot files
	rm -f src/**/po/*.pot

pocheck:
	# Check for missing translation / fuzzy translations (search for `#, fuzzy` tag)
	$(foreach LANG,$(LINGUAS), \
		printf "$(LANG): " ; msgfmt --statistics -o /dev/null src/$(PACKAGE_NAME)/po/$(LANG).po  ; \
	)

pomerge: pot
	# Merge translations form .pot files to all .po files
	$(foreach LANG,$(LINGUAS), \
		msgmerge --backup=none -q -U src/$(PACKAGE_NAME)/po/$(LANG).po src/$(PACKAGE_NAME)/po/$(PACKAGE_NAME).pot  ; \
	)

poupdate: pomerge pocheck

#
# Build/Install/dist
#

$(SPEC): packaging/$(SPEC).in $(NODE_MODULES_TEST)
	provides=$$(npm ls --omit dev --package-lock-only --depth=Infinity | grep -Eo '[^[:space:]]+@[^[:space:]]+' | sort -u | sed 's/^/Provides: bundled(npm(/; s/\(.*\)@/\1)) = /'); \
	$(AWK) -v p="$$provides" '{gsub(/%{VERSION}/, "$(VERSION)"); gsub(/%{NPM_PROVIDES}/, p)}1' $< > $@

$(DIST_TEST): $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP) $(shell find src/$(PACKAGE_NAME)/ -type f) package.json build.js
	NODE_ENV=$(NODE_ENV) SRCDIR=src/$(PACKAGE_NAME) ./build.js $(PACKAGE_NAME)

build-with-metainfo: $(DIST_TEST) src/$(PACKAGE_NAME)/po/LINGUAS
	# Create meta info XML file in dist directory, used in debian package branch
	msgfmt --xml -d src/$(PACKAGE_NAME)/po \
		--template $(APPSTREAMFILE_PATH) \
		-o dist/$(APPSTREAMFILE)

watch: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
	NODE_ENV=$(NODE_ENV) SRCDIR=src/$(PACKAGE_NAME) ./build.js --watch $(PACKAGE_NAME)

clean:
	rm -rf dist/
	rm -f cockpit-revpi-*.{spec,tar.xz}
	rm -f src/**/po/LINGUAS

distclean: clean
	# Delete all node modules that were installed for the build process
	rm -rf node_modules

	# Delete checked out files from cockpit repository for the build process
	rm -rf pkg
	rm -rf test/common
	rm -rf test/static-code

install: $(DIST_TEST) src/$(PACKAGE_NAME)/po/LINGUAS
	mkdir -p $(DESTDIR)$(PREFIX)/share/cockpit/
	cp -r dist/* $(DESTDIR)$(PREFIX)/share/cockpit/
	mkdir -p $(DESTDIR)$(PREFIX)/lib/tmpfiles.d/
	ln -fs \
		$(DESTDIR)$(PREFIX)/share/cockpit/$(PACKAGE_NAME)/systemd/cockpit-revpi-pictory-sso.tmpfiles.conf \
		$(DESTDIR)$(PREFIX)/lib/tmpfiles.d/
	mkdir -p $(DESTDIR)$(PREFIX)/share/metainfo/
	msgfmt --xml -d src/$(PACKAGE_NAME)/po \
		--template $(APPSTREAMFILE_PATH) \
		-o $(DESTDIR)$(PREFIX)/share/metainfo/$(APPSTREAMFILE)

# this requires a built source tree and avoids having to install anything system-wide
# Note: You must copy cockpit-revpi-pictory-sso.tmpfiles.conf manually {@see ./README.md#L19}
devel-install: $(DIST_TEST)
	mkdir -p ~/.local/share/cockpit
	ln -s `pwd`/dist/$(PACKAGE_NAME) ~/.local/share/cockpit/$(PACKAGE_NAME)

# assumes that there was symlink set up using the above devel-install target,
# and removes it
devel-uninstall:
	rm -f ~/.local/share/cockpit/$(PACKAGE_NAME)

print-version:
	@echo "$(VERSION)"

$(NODE_MODULES_TEST): package.json
	# install devDependencies no matter what NODE_ENV is set
	npm install --ignore-scripts --include dev
	npm run prepare

.PHONY: all clean install devel-install devel-uninstall print-version dist
