# Copyright 2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit cmake desktop flag-o-matic xdg

MY_PN="SpaghettiKart"
# The executable and CMake project are named after neither the repository nor
# the game.
MY_TARGET="Spaghettify"

# Submodules. doxygen-awesome-css and tools/blender/fast64 are documentation
# and Blender tooling and are not part of the build.
LUS_COMMIT="f40cfd33b8bc6237d635d4ed82838a7e3f785386"
# This one is no longer reachable from any branch of HarbourMasters/Torch, but
# GitHub still serves the archive for it.
TORCH_COMMIT="2d474ddb8da8b213fbdbb49d0273ce31fa955f35"
# libultraship looks for this beside the executable and upstream ships no
# copy of it.
GAMECONTROLLERDB_COMMIT="5a12daa568d19344f9b6e9286ef5929833b25c7c"
# Fetched with FetchContent by SpaghettiKart itself.
DR_LIBS_COMMIT="da35f9d6c7374a95353fd1df1d394d44ab66cf01"
# Fetched by SpaghettiKart with a bare file(DOWNLOAD), which leaves an empty
# file behind instead of failing when there is no network. sse2neon.h is
# fetched the same way, but from a branch rather than a tag, so it cannot be
# mirrored; nothing includes it on amd64 and the empty file is harmless there.
SEMVER_PV="1.0.0-rc"
TOMLPLUSPLUS_PV="3.4.0"
# Fetched with FetchContent by libultraship. MPQ support is off by default in
# this revision, so StormLib is not needed.
IMGUI_PV="1.91.9b-docking"
PRISM_COMMIT="bbcbc7e3f890a5806b579361e7aa0336acd547e7"
STB_COMMIT="0bc88af4de5fb022db643c2d8e549a0927749354"
THREADPOOL_PV="4.1.0"
# Fetched with FetchContent by Torch. GSL is not listed: Torch only fetches it
# when it detects it is running under WSL.
LIBGFXD_COMMIT="96fd3b849f38b3a7c7b7f3ff03c5921d328e6cdf"
TINYXML2_PV="10.0.0"
YAML_CPP_COMMIT="2f86d13775d119edbb69af52e5f566fd65c6953b"

DESCRIPTION="Mario Kart 64 port to modern platforms."
HOMEPAGE="https://github.com/HarbourMasters/SpaghettiKart"
SRC_URI="https://github.com/HarbourMasters/${MY_PN}/archive/refs/tags/${PV}.tar.gz
	-> ${P}.tar.gz
	https://github.com/Kenix3/libultraship/archive/${LUS_COMMIT}.tar.gz
	-> libultraship-${LUS_COMMIT}.tar.gz
	https://github.com/HarbourMasters/Torch/archive/${TORCH_COMMIT}.tar.gz
	-> Torch-${TORCH_COMMIT}.tar.gz
	https://github.com/mackron/dr_libs/archive/${DR_LIBS_COMMIT}.tar.gz
	-> dr_libs-${DR_LIBS_COMMIT}.tar.gz
	https://raw.githubusercontent.com/Neargye/semver/refs/tags/v${SEMVER_PV}/include/semver.hpp
	-> semver.hpp-${SEMVER_PV}
	https://github.com/marzer/tomlplusplus/archive/refs/tags/v${TOMLPLUSPLUS_PV}.tar.gz
	-> tomlplusplus-${TOMLPLUSPLUS_PV}.tar.gz
	https://github.com/ocornut/imgui/archive/refs/tags/v${IMGUI_PV}.tar.gz
	-> imgui-${IMGUI_PV}.tar.gz
	https://github.com/KiritoDv/prism-processor/archive/${PRISM_COMMIT}.tar.gz
	-> prism-processor-${PRISM_COMMIT}.tar.gz
	https://github.com/nothings/stb/raw/${STB_COMMIT}/stb_image.h
	-> stb_image.h-${STB_COMMIT}
	https://github.com/bshoshany/thread-pool/archive/refs/tags/v${THREADPOOL_PV}.tar.gz
	-> thread-pool-${THREADPOOL_PV}.tar.gz
	https://github.com/glankk/libgfxd/archive/${LIBGFXD_COMMIT}.tar.gz
	-> libgfxd-${LIBGFXD_COMMIT}.tar.gz
	https://github.com/leethomason/tinyxml2/archive/refs/tags/${TINYXML2_PV}.tar.gz
	-> tinyxml2-${TINYXML2_PV}.tar.gz
	https://github.com/jbeder/yaml-cpp/archive/${YAML_CPP_COMMIT}.tar.gz
	-> yaml-cpp-${YAML_CPP_COMMIT}.tar.gz
	https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/${GAMECONTROLLERDB_COMMIT}/gamecontrollerdb.txt
	-> gamecontrollerdb.txt-${GAMECONTROLLERDB_COMMIT}"
S="${WORKDIR}/${MY_PN}-${PV}"

LICENSE="GPL-3"
SLOT="0"
KEYWORDS="~amd64"

RDEPEND="
	dev-cpp/nlohmann_json
	dev-libs/libzip:=
	dev-libs/spdlog:=
	dev-libs/tinyxml2:=
	media-libs/glew:=
	media-libs/libglvnd
	media-libs/libogg
	media-libs/libsdl2
	media-libs/libvorbis
	media-libs/sdl2-net
"
DEPEND="${RDEPEND}"
BDEPEND="dev-lang/python:*"

PATCHES=(
	"${FILESDIR}/${P}-torch-single-build.patch"
	"${FILESDIR}/${P}-use-torch-cli.patch"
	"${FILESDIR}/${P}-dialogs-via-pfd.patch"
)

src_prepare() {
	rm -rf libultraship torch || die
	mv "${WORKDIR}/libultraship-${LUS_COMMIT}" libultraship || die
	mv "${WORKDIR}/Torch-${TORCH_COMMIT}" torch || die

	# libultraship fetches this header with file(DOWNLOAD). Unlike DOWNLOAD,
	# COPY_FILE does not create the destination directory.
	sed -i -e "s|file(DOWNLOAD \"https://github.com/nothings/stb/raw/[^\"]*\" |file(MAKE_DIRECTORY \"\${STB_DIR}\")\nfile(COPY_FILE \"${DISTDIR}/stb_image.h-${STB_COMMIT}\" |" \
		libultraship/cmake/dependencies/common.cmake || die
	grep -q 'file(COPY_FILE' libultraship/cmake/dependencies/common.cmake ||
		die "failed to redirect the stb_image.h download"

	# Same again for SpaghettiKart's own semver.hpp. file(DOWNLOAD) reports
	# failure only through a STATUS variable, and there is none here, so with
	# no network the configure succeeds and leaves an empty header behind.
	# ModMetadata::version is then dropped and ModManager.cpp fails to compile.
	sed -i -e "s|file(DOWNLOAD \"https://raw.githubusercontent.com/Neargye/semver/[^\"]*\" |file(MAKE_DIRECTORY \"\${SEMVER_DIR}\")\nfile(COPY_FILE \"${DISTDIR}/semver.hpp-${SEMVER_PV}\" |" \
		CMakeLists.txt || die
	grep -q 'file(COPY_FILE' CMakeLists.txt ||
		die "failed to redirect the semver.hpp download"

	cmake_src_prepare

	# FETCHCONTENT_SOURCE_DIR_* skips the patch step, so apply upstream's own
	# ImGui patch here instead.
	pushd "${WORKDIR}/imgui-${IMGUI_PV}" >/dev/null || die
	eapply "${S}/libultraship/cmake/dependencies/patches/imgui-fixes-and-config.patch"
	popd >/dev/null || die
}

src_configure() {
	# The vendored ImGui and prism violate the ODR across translation units.
	filter-lto

	local mycmakeargs=(
		# yaml-cpp and tinyxml2 otherwise build as shared libraries that
		# nothing installs, leaving the executable with sonames it cannot
		# resolve.
		-DBUILD_SHARED_LIBS=OFF
		-DFETCHCONTENT_FULLY_DISCONNECTED=ON
		-DFETCHCONTENT_SOURCE_DIR_DR_LIBS="${WORKDIR}/dr_libs-${DR_LIBS_COMMIT}"
		-DFETCHCONTENT_SOURCE_DIR_IMGUI="${WORKDIR}/imgui-${IMGUI_PV}"
		-DFETCHCONTENT_SOURCE_DIR_LIBGFXD="${WORKDIR}/libgfxd-${LIBGFXD_COMMIT}"
		-DFETCHCONTENT_SOURCE_DIR_PRISM="${WORKDIR}/prism-processor-${PRISM_COMMIT}"
		-DFETCHCONTENT_SOURCE_DIR_THREADPOOL="${WORKDIR}/thread-pool-${THREADPOOL_PV}"
		-DFETCHCONTENT_SOURCE_DIR_TINYXML2="${WORKDIR}/tinyxml2-${TINYXML2_PV}"
		-DFETCHCONTENT_SOURCE_DIR_TOMLPLUSPLUS="${WORKDIR}/tomlplusplus-${TOMLPLUSPLUS_PV}"
		-DFETCHCONTENT_SOURCE_DIR_YAML-CPP="${WORKDIR}/yaml-cpp-${YAML_CPP_COMMIT}"
	)

	cmake_src_configure
}

src_compile() {
	cmake_src_compile

	# spaghetti.o2r holds the port's own assets and is the only thing upstream
	# installs. It is built by a custom target that is not part of all.
	cmake_src_compile GenerateO2R
}

src_install() {
	# libultraship looks for the port's own assets next to the executable and
	# writes everything else relative to the working directory, so the
	# executable goes where spaghetti.o2r can sit beside it and a wrapper picks
	# the writable directory. SHIP_HOME is libultraship's own override for the
	# latter; the cd is for the paths that ignore it.
	exeinto "/usr/libexec/${PN}"
	newexe "${BUILD_DIR}/${MY_TARGET}" "${MY_TARGET}"

	insinto "/usr/libexec/${PN}"
	doins "${BUILD_DIR}/spaghetti.o2r"

	# libultraship looks for the controller database beside the executable
	# and nowhere useful after that, and upstream ships no copy of it.
	newins "${DISTDIR}/gamecontrollerdb.txt-${GAMECONTROLLERDB_COMMIT}" gamecontrollerdb.txt

	# GenerateOTR() hands Torch this directory as its source directory, so the
	# asset definitions have to be here as well: without them it reports "No
	# config file found" and produces nothing. meta/mods.toml is the metadata
	# naming the generated archive mk64-assets, which the game then refuses to
	# start without.
	doins config.yml
	doins -r meta yamls

	cat > "${T}/${PN}" <<-EOF || die
		#!/bin/sh
		SHIP_HOME="\${XDG_DATA_HOME:-\${HOME}/.local/share}/${PN}"
		export SHIP_HOME
		mkdir -p "\${SHIP_HOME}" || exit 1
		cd "\${SHIP_HOME}" || exit 1
		exec "${EPREFIX}/usr/libexec/${PN}/${MY_TARGET}" "\$@"
	EOF
	dobin "${T}/${PN}"

	# Upstream's SpaghettiKart.desktop is written for an AppImage: it runs
	# Spaghettify and asks for the far too generic Icon=icon. Generate an entry
	# for the installed binary instead, with the icon renamed to match.
	newicon -s 256 icon.png "${PN}.png"
	make_desktop_entry "${PN}" "${MY_PN}" "${PN}" Game

	einstalldocs
}

pkg_postinst() {
	xdg_pkg_postinst

	elog "${MY_PN} needs assets extracted from a US Mario Kart 64 ROM. Run it"
	elog "once and it will ask for the ROM, then write mk64.o2r and everything"
	elog "else it saves to \${XDG_DATA_HOME}/${PN}."
	elog
	elog "Asking for the ROM needs one of zenity, kdialog, matedialog or qarma"
	elog "installed; without one ${MY_PN} cannot prompt and will exit."
}