PREFIX    ?= /usr
DESTDIR   ?=

BINDIR     = $(DESTDIR)$(PREFIX)/bin
SHAREDIR   = $(DESTDIR)$(PREFIX)/share/eydos-loginmanager
SYSCONFDIR = $(DESTDIR)/etc
SYSTEMDDIR = $(DESTDIR)/lib/systemd/system

# Cross-compilation: set CARGO_TARGET to a Rust target triple to build and
# install for another architecture; empty builds natively into target/release.
CARGO_TARGET      ?=
CARGO_TARGET_FLAG  = $(if $(CARGO_TARGET),--target $(CARGO_TARGET),)
RELEASE_DIR        = target/$(if $(CARGO_TARGET),$(CARGO_TARGET)/,)release

.PHONY: all daemon install install-smartcast uninstall clean distclean \
        daemon-auth daemon-vt-info daemon-spawn daemon-run daemon-client \
        start-ipc

all:
	cargo build --release $(CARGO_TARGET_FLAG)

daemon:
	cargo build --release $(CARGO_TARGET_FLAG) -p loginmanager-daemon

# --- daemon dev runs -------------------------------------------------------
#
# All daemon subcommands need root for /dev/tty0 ioctls and PAM session bring-up.
# Override the PAM service / target user / login shell on the make line:
#   make daemon-spawn PAM_SERVICE=loginmanager-daemon DAEMON_USER=alice SPAWN_SHELL=/bin/zsh

PAM_SERVICE  ?= login
DAEMON_USER  ?= $$USER
SPAWN_SHELL  ?= /bin/bash
DAEMON_CONFIG?= $(CURDIR)/loginmanager.toml
DAEMON_BIN    = $(CURDIR)/$(RELEASE_DIR)/loginmanager-daemon

daemon-auth: daemon
	sudo $(DAEMON_BIN) auth $(DAEMON_USER) --pam-service $(PAM_SERVICE)

daemon-vt-info: daemon
	sudo $(DAEMON_BIN) vt-info

daemon-spawn: daemon
	@echo "Spawning $(SPAWN_SHELL) as $(DAEMON_USER) on a fresh VT."
	@echo "When you're done in the spawned shell, type 'exit'."
	@echo "If you need to come back manually: Ctrl+Alt+F<original-VT>."
	sudo $(DAEMON_BIN) spawn $(DAEMON_USER) --pam-service $(PAM_SERVICE) --shell $(SPAWN_SHELL) --config $(DAEMON_CONFIG)

DAEMON_SOCKET ?= /tmp/loginmanager-test.sock

daemon-run: daemon
	@echo "Server listens on $(DAEMON_SOCKET). On AuthAccepted it will fork the"
	@echo "session command from $(DAEMON_CONFIG) — use a wrong password in"
	@echo "daemon-client if you only want to test IPC."
	sudo $(DAEMON_BIN) run --socket $(DAEMON_SOCKET) --config $(DAEMON_CONFIG)

daemon-client: daemon
	sudo $(DAEMON_BIN) client $(DAEMON_USER) --socket $(DAEMON_SOCKET)

# Greeter wired against the daemon IPC. Run `make daemon-run` in another
# terminal first so the socket at $(DAEMON_SOCKET) exists. The greeter
# autodetects the path via LOGINMANAGER_SOCK and picks daemon IPC over
# greetd / PAM-fallback when it is reachable.
start-ipc: all
	FORGE_MOBILE=1 LOCKSCREEN_MODE=greeter LOCKSCREEN_THEME=light LOGINMANAGER_SOCK=$(DAEMON_SOCKET) LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config dbus-run-session forge --winit --size 480x960 --exec $(LOCKSCREEN_BIN)

FORGE_TEST_DIR = /tmp/forge-test-config/forge
LOCKSCREEN_BIN = $(CURDIR)/$(RELEASE_DIR)/lockscreen

# Pass `THEME=light` or `THEME=dark` on the make line to force a mode.
THEME_FLAG = $(if $(THEME),--$(THEME),)

arm64-deps:
	sudo dpkg --add-architecture arm64
	sudo apt-get install crossbuild-essential-arm64 libstd-rust-dev:arm64 libstd-rust-1.85:arm64 libwayland-dev:arm64 libwayland-egl1:arm64 libxkbcommon-dev:arm64 libegl-dev:arm64 libgles2-mesa-dev:arm64 libpam0g-dev:arm64 libdbus-1-dev:arm64 libssl-dev:arm64

arm64:
	CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
	PKG_CONFIG=aarch64-linux-gnu-pkg-config PKG_CONFIG_ALLOW_CROSS=1 \
	cargo build --release --target aarch64-unknown-linux-gnu

# Mobile-mode targets pass FORGE_MOBILE=1 so forge skips its built-in
# sm.puri.OSK0 shim and squeekboard (launched by the greeter) owns the name.
# `dbus-run-session` gives forge --winit its own session bus instead of
# inheriting the host's — without it, in a host that already runs
# forge+crustace, the host forge owns sm.puri.OSK0 on the user bus and
# both the nested forge's property writes and squeekboard's registration
# attempt collide with that owner.
start: all
	FORGE_MOBILE=1 LOCKSCREEN_MODE=greeter LOCKSCREEN_THEME=light LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config dbus-run-session forge --winit --size 480x960 --exec $(LOCKSCREEN_BIN)

start-dark: all
	FORGE_MOBILE=1 LOCKSCREEN_MODE=greeter LOCKSCREEN_THEME=dark LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config dbus-run-session forge --winit --size 480x960 --exec $(LOCKSCREEN_BIN)

# Session-lock variant (no username field, no power buttons): current user
# verified via local PAM. Swipe up reveals the password field.
start-lock: all
	FORGE_MOBILE=1 LOCKSCREEN_MODE=lock LOCKSCREEN_THEME=light LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config dbus-run-session forge --winit --size 480x960 --exec $(LOCKSCREEN_BIN)

start-lock-dark: all
	FORGE_MOBILE=1 LOCKSCREEN_MODE=lock LOCKSCREEN_THEME=dark LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config dbus-run-session forge --winit --size 480x960 --exec $(LOCKSCREEN_BIN)

start-desktop: all
	LOCKSCREEN_MODE=greeter LOCKSCREEN_THEME=light LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config forge --winit --size 1600x900 --exec $(LOCKSCREEN_BIN)

start-desktop-dark: all
	LOCKSCREEN_MODE=greeter LOCKSCREEN_THEME=dark LTK_THEMES_DIR=$(CURDIR)/../ltk/themes XDG_CONFIG_HOME=/tmp/forge-test-config forge --winit --size 1600x900 --exec $(LOCKSCREEN_BIN)

smartcast: all
	mkdir -p $(FORGE_TEST_DIR)
	printf '#!/bin/sh\nLTK_THEMES_DIR=$(CURDIR)/../ltk/themes $(CURDIR)/target/release/smartcast $(THEME_FLAG) &\n' > $(FORGE_TEST_DIR)/initrc
	chmod +x $(FORGE_TEST_DIR)/initrc
	XDG_CONFIG_HOME=/tmp/forge-test-config forge --winit --size 1600x900

install:
	install -Dm755 $(RELEASE_DIR)/loginmanager-daemon $(BINDIR)/loginmanager-daemon
	install -Dm755 $(RELEASE_DIR)/loginmanager-splash $(BINDIR)/loginmanager-splash
	install -Dm755 $(RELEASE_DIR)/lockscreen          $(BINDIR)/lockscreen
	install -Dm755 data/loginmanager-greeter          $(BINDIR)/loginmanager-greeter
	install -Dm644 loginmanager.toml                  $(SYSCONFDIR)/eydos/loginmanager.toml
	@if [ -z "$(DESTDIR)" ] && getent group _loginmanager >/dev/null 2>&1; then \
		chown root:_loginmanager $(SYSCONFDIR)/eydos/loginmanager.toml && \
		chmod 664 $(SYSCONFDIR)/eydos/loginmanager.toml ; \
	fi
	install -Dm644 data/pam.d/loginmanager-daemon     $(SYSCONFDIR)/pam.d/loginmanager-daemon
	install -Dm644 data/pam.d/loginmanager-greeter    $(SYSCONFDIR)/pam.d/loginmanager-greeter
	install -Dm644 loginmanager-daemon.service        $(SYSTEMDDIR)/loginmanager-daemon.service
	# Best-effort symlink for the splash logo: point at the active theme's
	# branding/dark/logo/horizontal.svg. Themes ship under $(PREFIX)/share/ltk/themes,
	# not /share/themes — the latter is reserved for GTK themes. Missing
	# theme is not fatal: the splash falls back to a clean `execv` if the
	# SVG doesn't exist on disk.
	install -d $(SHAREDIR)
	@for theme in Eydos eydos liberux default; do \
		src="$(DESTDIR)$(PREFIX)/share/ltk/themes/$$theme/branding/dark/logo/horizontal.svg"; \
		if [ -e "$$src" ]; then \
			ln -sf "$(PREFIX)/share/ltk/themes/$$theme/branding/dark/logo/horizontal.svg" \
				$(SHAREDIR)/splash-logo.svg && \
			echo "splash logo symlinked from theme $$theme"; \
			break; \
		fi; \
	done

install-smartcast:
	install -Dm755 $(RELEASE_DIR)/smartcast $(BINDIR)/smartcast

uninstall:
	rm -f $(BINDIR)/loginmanager-daemon
	rm -f $(BINDIR)/loginmanager-splash
	rm -f $(BINDIR)/lockscreen
	rm -f $(BINDIR)/loginmanager-greeter
	rm -f $(SYSCONFDIR)/eydos/loginmanager.toml
	rm -f $(SYSCONFDIR)/pam.d/loginmanager-daemon
	rm -f $(SYSCONFDIR)/pam.d/loginmanager-greeter
	rm -f $(SYSTEMDDIR)/loginmanager-daemon.service
	rm -f $(SHAREDIR)/splash-logo.svg

clean:
	dh_clean
	cargo clean

distclean: clean
	rm -f Cargo.lock
