PORTNAME=	vscode
DISTVERSION=	${VSCODE_VERSION}
CATEGORIES=	editors
MASTER_SITES=	https://github.com/tagattie/FreeBSD-VSCode/releases/download/${DISTVERSION}/:node_modules \
		https://registry.npmjs.org/@github/copilot-linux-${NODEJS_ARCH}/-/:copilot_cli \
		https://registry.npmjs.org/@github/copilot-sdk-linux-${NODEJS_ARCH}/-/:copilot_sdk
PKGNAMESUFFIX=	-reh
DISTFILES=	vscode-node-modules-${DISTVERSION}-${NODEJS_ARCH}${EXTRACT_SUFX}:node_modules \
		copilot-linux-${NODEJS_ARCH}-${COPILOT_CLI_VERSION}.tgz:copilot_cli \
		copilot-sdk-linux-${NODEJS_ARCH}-${COPILOT_SDK_VERSION}.tgz:copilot_sdk
DIST_SUBDIR=	${PORTNAME}

MAINTAINER=	tagattie@FreeBSD.org
COMMENT=	Visual Studio Code - Open Source ("Code - OSS")
WWW=		https://code.visualstudio.com/

LICENSE=	MIT
LICENSE_FILE=	${WRKSRC}/LICENSE.txt

ONLY_FOR_ARCHS=	aarch64 amd64

EXTRACT_DEPENDS=jq:textproc/jq \
		node${NODEJS_VERSION}>0:www/node${NODEJS_VERSION}
BUILD_DEPENDS=	jq:textproc/jq \
		rg:textproc/ripgrep \
		tgrep:textproc/tgrep
LIB_DEPENDS=	libbrotlidec.so:archivers/brotli \
		libcares.so:dns/c-ares \
		libicui18n.so:devel/icu \
		libllhttp.so:www/llhttp \
		libnghttp2.so:www/libnghttp2 \
		libnghttp3.so:www/libnghttp3 \
		libngtcp2.so:net/libngtcp2 \
		libsimdjson.so:devel/simdjson \
		libuv.so:devel/libuv \
		libzstd.so:archivers/zstd \
		libsqlite3.so:databases/sqlite3 \
		libsecret-1.so:security/libsecret

USES=		cargo gssapi:mit localbase:ldflags nodejs:24,build npm:npm \
		pkgconfig python:build shebangfix

USE_GITHUB=	yes
GH_ACCOUNT=	microsoft
GH_TUPLE=	web-infra-dev:rspack:v${RSPACK_VERSION}:rspack/rspack

CARGO_CARGOTOML=${WRKSRC}/rspack/Cargo.toml
CARGO_CARGOLOCK=${WRKSRC}/rspack/Cargo.lock
CARGO_BUILDDEP=	any-version
CARGO_BUILD=	no
CARGO_INSTALL=	no
CARGO_TEST=	no

CFLAGS+=	-Wno-error=implicit-function-declaration

USE_CXXSTD=	c++20

SHEBANG_REGEX=	./(extensions|node_modules|resources|scripts|src)/.*(\.(pl|py|sh)|makeBlacker|makeFF)$$
PATHFIX_FILES=	src/vs/workbench/contrib/debug/node/terminals.ts

MAKE_ENV=	BUILD_SOURCEVERSION=${SOURCE_COMMIT_HASH} \
		VSCODE_QUALITY=stable \
		NODE_OPTIONS="--max-old-space-size=8192"

BINARY_ALIAS=	python=${PYTHON_CMD}

.include "Makefile.version"
.include <bsd.port.pre.mk>

NODEJS_ARCH=	${ARCH:S/aarch64/arm64/:S/amd64/x64/}
NODEJS_DIR=	${PORTSDIR}/www/node${NODEJS_VERSION}
.include "${NODEJS_DIR}/Makefile.version"

ELECTRON_VER_MAJOR=	43
ELECTRON_DIR=		${PORTSDIR}/devel/electron${ELECTRON_VER_MAJOR}
.include "${ELECTRON_DIR}/Makefile.version"

post-fetch:
	@if [ ! -r ${DISTDIR}/${DIST_SUBDIR}/electron.d.ts-${ELECTRON_VER} ]; then \
		${SETENV} ${FETCH_ENV} ${FETCH_CMD} -o ${DISTDIR}/${DIST_SUBDIR}/electron.d.ts-${ELECTRON_VER} \
			https://github.com/electron/electron/releases/download/v${ELECTRON_VER}/electron.d.ts; \
	fi

post-extract:
	@${CP} ${WRKSRC}/build/.moduleignore.linux \
		${WRKSRC}/build/.moduleignore.freebsd
	@${MKDIR} ${WRKSRC}/.build/typings
	@${CP} ${DISTDIR}/${DIST_SUBDIR}/electron.d.ts-${ELECTRON_VER} \
		${WRKSRC}/.build/typings/electron.d.ts
	@${ECHO_MSG} "===>  Installing node modules in ${WRKSRC}"
	@${TAR} -xzf ${WRKDIR}/vscode-.-node-modules${EXTRACT_SUFX} -C ${WRKSRC}
	@for dir in `node --input-type=module -e "console.log(JSON.stringify((await import('${WRKSRC}/build/npm/dirs.ts')).dirs))" | jq -r '.[]'`; do \
		if [ -f ${WRKDIR}/vscode-`echo $${dir} | tr _ __ | tr / _`-node-modules${EXTRACT_SUFX} ]; then \
			${ECHO_MSG} "===>  Installing node modules in ${WRKSRC}/$${dir}"; \
			${TAR} -xzf ${WRKDIR}/vscode-`echo $${dir} | tr _ __ | tr / _`-node-modules${EXTRACT_SUFX} \
				-C ${WRKSRC}/$${dir}; \
		fi; \
	done
	# extract contents of @github/copilot-linux-x64
	# note: this is just for the build process to pass. GitHub Copilot CLI
	# is a closed-source product and not usable on FreeBSD without Linuxulator
	@${MKDIR} ${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH}
	@(DISTFILE_copilot=${DISTDIR}/${DIST_SUBDIR}/copilot-linux-${NODEJS_ARCH}-${COPILOT_CLI_VERSION}.tgz; \
	${TAR} -xzf $${DISTFILE_copilot} \
		--strip-components 1 -C ${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH})
	# extract contents of @github/copilot-sdk-linux-x64
	# note: again, this is just for the build process to pass
	@${MKDIR} ${WRKSRC}/remote/node_modules/@github/copilot-sdk-linux-${NODEJS_ARCH}
	@(DISTFILE_copilot_sdk=${DISTDIR}/${DIST_SUBDIR}/copilot-sdk-linux-${NODEJS_ARCH}-${COPILOT_SDK_VERSION}.tgz; \
	${TAR} -xzf $${DISTFILE_copilot_sdk} \
		--strip-components 1 -C ${WRKSRC}/remote/node_modules/@github/copilot-sdk-linux-${NODEJS_ARCH})

post-patch:
	@${REINPLACE_CMD} -E 's|^(target=").*(")$$|\1${NODEJS_PORTVERSION}\2|' \
		${WRKSRC}/remote/.npmrc
	@${REINPLACE_CMD} -e 's/%%DISTVERSION%%/${DISTVERSION}/g' \
		${WRKSRC}/build/gulpfile.reh.ts \
		${WRKSRC}/build/gulpfile.vscode.ts
	@(cd ${WRKSRC} && \
	${FIND} -E . -type f -iregex '${SHEBANG_REGEX}' \
		-exec ${SED} -i '' -e "s|/usr/bin/pgrep|/bin/pgrep|g" {} ';')
	@(cd ${WRKSRC} && \
	${FIND} ${PATHFIX_FILES} -type f \
		-exec ${SED} -i '' -e "s|/usr/bin/pgrep|/bin/pgrep|g" {} ';')
	@${SETENV} FILESDIR=${FILESDIR} \
		${SH} ${FILESDIR}/update-product-json.sh ${WRKSRC}

pre-build:
# rebuild native node modules in subdirectories
	@for dir in `node --input-type=module -e "console.log(JSON.stringify((await import('${WRKSRC}/build/npm/dirs.ts')).dirs))" | jq -r '.[]'`; do \
		for subdir in `${FIND} ${WRKSRC}/$${dir}/node_modules -type f -name binding.gyp -exec ${DIRNAME} {} ';' 2> /dev/null`; do \
			${ECHO_MSG} "===>   Rebuilding native modules in $${subdir}"; \
			if [ "`${ECHO_CMD} $${subdir} | ${GREP} /build/`" ]; then \
				cd $${subdir} && \
				npm_env="npm_config_runtime=node \
					npm_config_target=${NODEJS_PORTVERSION} \
					npm_config_nodedir=${LOCALBASE}" && \
				${SETENV} ${MAKE_ENV} $${npm_env} \
					npm --userconfig=${WRKSRC}/build/.npmrc run install --if-present && \
				${SETENV} ${MAKE_ENV} $${npm_env} \
					node-gyp --userconfig=${WRKSRC}/build/.npmrc \
					--jobs ${MAKE_JOBS_NUMBER} rebuild; \
			elif [ "`${ECHO_CMD} $${subdir} | ${GREP} /remote/`" ]; then \
				cd $${subdir} && \
				npm_env="npm_config_runtime=node \
					npm_config_target=${NODEJS_PORTVERSION} \
					npm_config_nodedir=${LOCALBASE}" && \
				${SETENV} ${MAKE_ENV} $${npm_env} \
					npm --userconfig=${WRKSRC}/remote/.npmrc run install --if-present && \
				${SETENV} ${MAKE_ENV} $${npm_env} \
					node-gyp --userconfig=${WRKSRC}/remote/.npmrc \
					--jobs ${MAKE_JOBS_NUMBER} rebuild; \
			fi; \
		done; \
	done
	# # build native node module for @rspack/binding
	# @${CARGO_CARGO_RUN} build \
	#	--manifest-path ${CARGO_CARGOTOML_RSPACK} \
	#	--verbose --verbose \
	#	${CARGO_BUILD_ARGS}
	# ${CP} ${CARGO_TARGET_DIR}/*/librspack.so \
	#	${WRKSRC}/build/rspack/node_modules/@rspack/binding/rspack.freebsd-${NODEJS_ARCH}.node
# copy rg binary file
	@${MKDIR} ${WRKSRC}/build/node_modules/@vscode/ripgrep-universal/bin/freebsd-${NODEJS_ARCH} \
		${WRKSRC}/remote/node_modules/@vscode/ripgrep-universal/bin/freebsd-${NODEJS_ARCH} \
		${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH}/ripgrep/bin/freebsd-${NODEJS_ARCH}
	${CP} ${LOCALBASE}/bin/rg ${WRKSRC}/build/node_modules/@vscode/ripgrep-universal/bin/freebsd-${NODEJS_ARCH}
	${CP} ${LOCALBASE}/bin/rg ${WRKSRC}/remote/node_modules/@vscode/ripgrep-universal/bin/freebsd-${NODEJS_ARCH}
	${CP} ${LOCALBASE}/bin/rg ${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH}/ripgrep/bin/freebsd-${NODEJS_ARCH}
# copy tgrep binary file
	@${MKDIR} ${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH}/tgrep/bin/freebsd-${NODEJS_ARCH}
	${CP} ${LOCALBASE}/bin/tgrep ${WRKSRC}/extensions/copilot/node_modules/@github/copilot-freebsd-${NODEJS_ARCH}/tgrep/bin/freebsd-${NODEJS_ARCH}

do-build:
# setup download cache for node
	@${MKDIR} ${WRKSRC}/.build/node/v${NODEJS_PORTVERSION}/linux-${NODEJS_ARCH}
	@${CP} ${LOCALBASE}/bin/node \
		${WRKSRC}/.build/node/v${NODEJS_PORTVERSION}/linux-${NODEJS_ARCH}
# remove backup files so that they are not included in the package
	@${FIND} ${WRKSRC} -type f \( -name '*.bak' -o -name '*.orig' -o -name '*~' \) -delete
# build vscode remote extension host
	@cd ${WRKSRC} && \
	npm_env="npm_config_runtime=node \
		npm_config_target=${NODEJS_PORTVERSION} \
		npm_config_nodedir=${LOCALBASE}"; \
	max_tries=3; \
	count=0; \
	while true; do \
		${SETENV} ${MAKE_ENV} $${npm_env} \
			npm --userconfig=${WRKSRC}/remote/.npmrc run \
				gulp vscode-reh-linux-${NODEJS_ARCH}-min && break; \
		count=$$((count + 1)); \
		if [ $${count} -ge $${max_tries} ]; then \
			${ECHO_MSG} "Failed to build after $${max_tries} attempts."; \
			exit 1; \
		fi; \
		${ECHO_MSG} "Build failed, retrying... (attempt $${count})"; \
	done
# strip native node modules
	@${FIND} ${WRKDIR}/vscode-reh-linux-${NODEJS_ARCH} -type f -exec ${FILE} {} + | \
		${GREP} 'ELF.*FreeBSD' | ${AWK} -F ': ' '{print $$1}' | ${XARGS} ${STRIP_CMD}
	${TAR} -czf ${WRKDIR}/vscode-reh-${OPSYS:tl}-${NODEJS_ARCH}-${DISTVERSION}.tar.gz \
		-C ${WRKDIR}/vscode-reh-linux-${NODEJS_ARCH} .

.include <bsd.port.post.mk>
