# NetSurf for MontaukOS -- native window browser frontend
#
# Upstream: https://github.com/netsurf-browser/netsurf (official mirror of
# git.netsurf-browser.org; submodule at upstream/, pinned).
#
# The port reuses NetSurf's compact monkey frontend glue, but MontaukOS builds
# enter a native Window Server event loop with browser chrome and render into a
# shared surface. The line-oriented monkey protocol remains available off-OS.
#
# CONFIGURATION
#   NETSURF_USE_CURL=NO      no libcurl port; fetch_montauk uses MontaukOS DNS,
#                            TCP, and the native BearSSL TLS helper.
#   NETSURF_USE_OPENSSL=NO   HTTPS is implemented by fetch_montauk via BearSSL.
#   NETSURF_USE_DUKTAPE=NO   no JavaScript; also avoids the nsgenbind host tool.
#   NETSURF_USE_JPEG=YES     enables the port-local stb_image JPEG/PNG handler.
#   JPEGXL/WEBP/SVG=NO       those optional decoder libraries are not ported.
#   NETSURF_FS_BACKING_STORE=YES  NOT optional for monkey: frontends/monkey/
#                            main.c references filesystem_llcache_table
#                            unconditionally, and that lives in
#                            content/fs_backing_store.c. The config.h patch
#                            already tells NetSurf we lack dirfd/unlinkat/
#                            fstatat, so it uses its portable fallbacks.
#   NETSURF_USE_LIBICONV_PLUG=YES means "iconv is already available, do not
#                            link -liconv" -- true here, since compat/iconv.c
#                            provides it inside libnscompat.a.
#
# COMPAT SHIMS (compat/) stand in for headers MontaukOS has no equivalent of:
# sockets, select, inet, and a stub <curl/curl.h> that exists only because
# content/fetch.c includes curl's header unguarded. See those files -- each
# says what it does and does not do.
#
# HOST TOOLS: perl, python3. (gperf is needed by libhubbub, not here.)

UPSTREAM := upstream
# Absolute: the sub-make runs with -C upstream, so a relative include path
# would resolve against the checkout rather than this port.
COMPAT   := $(CURDIR)/compat

PORT_NAME := netsurf

include ../../mk/port.mk

# NetSurf's own Makefile derives HOST from uname and picks its own build
# directory, so BUILDDIR/HOST from port.mk do not apply here. The binary is
# dropped at the top of the checkout, not inside build/.
NS_BUILD_OUT := $(UPSTREAM)/nsmonkey

# NetSurf cannot start without its resources (Messages, default.css,
# quirks.css ...). Keep the compile-time fallback inside the app bundle; the
# MontaukOS frontend normally derives this directory from argv[0] at runtime.
NS_RESPATH  := 0:/apps/netsurf/res/
APP_INSTALL := $(MONTAUKOS)/programs/bin/apps/netsurf
LEGACY_INSTALL := $(MONTAUKOS)/programs/bin/os

# libutf8proc installs its header to include/libutf8proc/ but its .pc
# advertises only -I${includedir}, while utils/idna.c includes <utf8proc.h>.
# Add the subdirectory here rather than staging a duplicate copy of the header.
NETSURF_CFLAGS := \
    $(PORT_CFLAGS_COMMON) \
    -DWITH_MONTAUK_FETCHER \
    -DWITH_JPEG \
    -I $(COMPAT) \
    -I $(PORT_SYSROOT_INC)/libutf8proc

NETSURF_ARGS := \
    TARGET=monkey \
    NSSHARED=$(NS_BUILDSYSTEM) \
    CC=$(CC) \
    AR=$(AR) \
    NETSURF_USE_CURL=NO \
    NETSURF_USE_MONTAUK=YES \
    NETSURF_USE_OPENSSL=NO \
    NETSURF_USE_DUKTAPE=NO \
    NETSURF_USE_PNG=NO \
    NETSURF_USE_JPEG=YES \
    NETSURF_USE_JPEGXL=NO \
    NETSURF_USE_WEBP=NO \
    NETSURF_USE_VIDEO=NO \
    NETSURF_USE_LIBICONV_PLUG=YES \
    NETSURF_MONKEY_RESOURCES=$(NS_RESPATH) \
    NETSURF_FS_BACKING_STORE=YES

# compat/iconv.c is the only shim needing a translation unit of its own (the
# rest are header-only). It goes into a small archive placed FIRST in LDFLAGS:
# NetSurf appends its own pkg-config libraries after the environment's value,
# so -lparserutils lands to the right of this archive and resolves the symbols
# it references.
COMPAT_LIB := $(CURDIR)/compat/libnscompat.a
BRIDGE_OBJ := $(CURDIR)/compat/montauk_bridge.o
STB_OBJ := $(CURDIR)/compat/stb_truetype_impl.o
STB_IMAGE_OBJ := $(CURDIR)/compat/stb_image_impl.o

# NetSurf formats floats (page load time in the status bar, plot coordinates).
# The Montauk libc keeps %e/%f/%g in a separate archive member reached by a
# WEAK reference, and a weak undefined ref does not extract a member -- without
# this the status bar reads "Done (%fs)". See programs/lib/libc/printf_float.c.
# Link the SDK libc explicitly as well. The cross compiler has a libc snapshot
# in its private sysroot, but that snapshot is only for bootstrapping the
# toolchain and can lag the OS tree. In particular, the older allocator is not
# safe for NetSurf's worker-thread allocation traffic.
NS_LDFLAGS := $(COMPAT_LIB) -L$(MONTAUKOS)/programs/lib/libjpeg \
    $(MONTAUKOS)/programs/lib/libloader/liblibloader.a \
    $(LIBTLS_A) $(LIBBEARSSL_A) $(LIBC_A) -Wl,-u,_pf_putfloat

$(COMPAT_LIB): compat/iconv.c compat/iconv.h $(BRIDGE_OBJ) $(STB_OBJ) $(STB_IMAGE_OBJ)
	$(CC) $(NETSURF_CFLAGS) -std=gnu99 -c compat/iconv.c -o compat/iconv.o
	$(AR) rcs $@ compat/iconv.o $(BRIDGE_OBJ) $(STB_OBJ) $(STB_IMAGE_OBJ)
	@echo "Built: $@"

$(BRIDGE_OBJ): files/montauk_bridge.cpp files/montauk_bridge.h
	$(CXX) $(PORT_CFLAGS_COMMON) -std=gnu++20 -fno-exceptions -fno-rtti \
	    -I $(MONTAUKOS)/programs/lib/bearssl/inc -I files -c $< -o $@

$(STB_OBJ): files/stb_truetype_impl.cpp
	$(CXX) $(PORT_CFLAGS_COMMON) -std=gnu++20 -fno-exceptions -fno-rtti -c $< -o $@

$(STB_IMAGE_OBJ): compat/stb_image_impl.c
	$(CC) $(PORT_CFLAGS_COMMON) -std=gnu11 -c $< -o $@

.PHONY: all clean netsurf-build
all: netsurf-build

netsurf-build: $(COMPAT_LIB)
	@$(call ns_patch,$(UPSTREAM))
	cp files/montauk.c files/montauk.h files/montauk_bridge.h $(UPSTREAM)/content/fetchers/
	cp files/montauk_ui.c files/montauk_ui.h $(UPSTREAM)/frontends/monkey/
	cp files/montauk_image.c $(UPSTREAM)/content/handlers/image/jpeg.c
	CFLAGS="$(NETSURF_CFLAGS)" LDFLAGS="$(NS_LDFLAGS)" $(NS_ENV) \
	    $(NS_MAKE) -C $(UPSTREAM) $(NETSURF_ARGS)
	@test -f $(NS_BUILD_OUT) || { echo "netsurf: expected $(NS_BUILD_OUT)" >&2; exit 1; }
	@echo "Built: $(NS_BUILD_OUT) ($$(stat -c%s $(NS_BUILD_OUT)) bytes)"

# Install a self-contained app bundle, including NetSurf's resource tree.
.PHONY: install uninstall
install: netsurf-build
	rm -rf $(LEGACY_INSTALL)/nsmonkey.elf $(LEGACY_INSTALL)/netsurf
	mkdir -p $(APP_INSTALL)/res
	cp $(NS_BUILD_OUT) $(APP_INSTALL)/netsurf.elf
	cp files/manifest.toml $(APP_INSTALL)/manifest.toml
	cp $(MONTAUKOS)/programs/bin/os/icons/web-browser.svg $(APP_INSTALL)/web-browser.svg
	# -L, not -r alone: nearly everything in a NetSurf frontend res/ dir is a
	# symlink into ../../../resources/. Copied as links they dangle outside
	# the installed tree, and the ramdisk turns a symlink into a ZERO-LENGTH
	# FILE (Fs/Ramdisk.cpp only handles typeflag '5'), so default.css and
	# welcome.html arrive empty and every page lays out to nothing.
	cp -rL $(UPSTREAM)/frontends/monkey/res/. $(APP_INSTALL)/res/
	@echo "installed: self-contained NetSurf app bundle"

uninstall:
	rm -rf $(APP_INSTALL) $(LEGACY_INSTALL)/nsmonkey.elf $(LEGACY_INSTALL)/netsurf
	@echo "removed NetSurf app bundle"

clean:
	@$(NS_ENV) $(NS_MAKE) -C $(UPSTREAM) $(NETSURF_ARGS) clean >/dev/null 2>&1 || true
	@git -C $(UPSTREAM) checkout -- . 2>/dev/null || true
	rm -rf $(UPSTREAM)/build-Linux-monkey
