#!/bin/bash
set -e

MAX_IMG_SECTORS=7217792 # 4GB

echo "==== StartOS Image Build ===="

echo "Building for architecture: $IB_TARGET_ARCH"

base_dir="$(dirname "$(readlink -f "$0")")"
prep_results_dir="$base_dir/images-prep"
if systemd-detect-virt -qc; then
	RESULTS_DIR="/srv/artifacts"
else
	RESULTS_DIR="$base_dir/results"
fi
echo "Saving results in: $RESULTS_DIR"

IMAGE_BASENAME=startos-${VERSION_FULL}_${IB_TARGET_PLATFORM}

mkdir -p $prep_results_dir

cd $prep_results_dir

QEMU_ARCH=${IB_TARGET_ARCH}
BOOTLOADERS=grub-efi,syslinux
if [ "$QEMU_ARCH" = 'amd64' ]; then
	QEMU_ARCH=x86_64
elif [ "$QEMU_ARCH" = 'arm64' ]; then
	QEMU_ARCH=aarch64
	BOOTLOADERS=grub-efi
fi
NON_FREE=
if [[ "${IB_TARGET_PLATFORM}" =~ -nonfree$ ]] || [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	NON_FREE=1
fi
IMAGE_TYPE=iso
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ] || [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
	IMAGE_TYPE=img
fi

ARCHIVE_AREAS="main contrib"
if [ "$NON_FREE" = 1 ]; then
	if [ "$IB_SUITE" = "bullseye" ]; then
		ARCHIVE_AREAS="$ARCHIVE_AREAS non-free"
	elif [ "$IB_SUITE" = "bookworm" ]; then
		ARCHIVE_AREAS="$ARCHIVE_AREAS non-free-firmware"
	fi
fi

PLATFORM_CONFIG_EXTRAS=
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-binary false"
	PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-chroot false"
	# BEGIN stupid ugly hack
	# The actual name of the package is `raspberrypi-kernel`
	# live-build determines thte name of the package for the kernel by combining the `linux-packages` flag, with the `linux-flavours` flag
	# the `linux-flavours` flag defaults to the architecture, so there's no way to remove the suffix.
	# So we're doing this, cause thank the gods our package name contains a hypen. Cause if it didn't we'd be SOL
	PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-packages raspberrypi"
	PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours kernel"
	# END stupid ugly hack
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
	PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours rockchip64"
fi

cat > /etc/wgetrc << EOF
retry_connrefused = on
tries = 100
EOF
lb config \
	--iso-application "StartOS v${VERSION_FULL} ${IB_TARGET_ARCH}" \
	--iso-volume "StartOS v${VERSION} ${IB_TARGET_ARCH}" \
	--iso-preparer "START9 LABS; HTTPS://START9.COM" \
	--iso-publisher "START9 LABS; HTTPS://START9.COM" \
	--backports true \
	--bootappend-live "boot=live noautologin" \
	--bootloaders $BOOTLOADERS \
	--mirror-bootstrap "https://deb.debian.org/debian/" \
	--mirror-chroot "https://deb.debian.org/debian/" \
	--mirror-chroot-security "https://security.debian.org/debian-security" \
	-d ${IB_SUITE} \
	-a ${IB_TARGET_ARCH} \
	--bootstrap-qemu-arch ${IB_TARGET_ARCH} \
	--bootstrap-qemu-static /usr/bin/qemu-${QEMU_ARCH}-static \
	--archive-areas "${ARCHIVE_AREAS}" \
	$PLATFORM_CONFIG_EXTRAS

# Overlays

mkdir -p config/includes.chroot/deb
cp $base_dir/deb/${IMAGE_BASENAME}.deb config/includes.chroot/deb/

if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	cp -r $base_dir/raspberrypi/squashfs/* config/includes.chroot/
fi

mkdir -p config/includes.chroot/etc
echo start > config/includes.chroot/etc/hostname
cat > config/includes.chroot/etc/hosts << EOT
127.0.0.1       localhost start
::1             localhost start ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters
EOT

# Bootloaders

rm -rf config/bootloaders
cp -r /usr/share/live/build/bootloaders config/bootloaders

cat > config/bootloaders/syslinux/syslinux.cfg << EOF
include menu.cfg
default vesamenu.c32
prompt 0
timeout 50
EOF

cat > config/bootloaders/isolinux/isolinux.cfg << EOF
include menu.cfg
default vesamenu.c32
prompt 0
timeout 50
EOF

rm config/bootloaders/syslinux_common/splash.svg
cp $base_dir/splash.png config/bootloaders/syslinux_common/splash.png
cp $base_dir/splash.png config/bootloaders/isolinux/splash.png
cp $base_dir/splash.png config/bootloaders/grub-pc/splash.png

sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg

# Archives

mkdir -p config/archives

if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	curl -fsSL https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o config/archives/raspi.key
	echo "deb https://archive.raspberrypi.org/debian/ bullseye main" > config/archives/raspi.list
fi

if [ "${IB_SUITE}" = "bullseye" ]; then
	cat > config/archives/backports.pref <<- EOF
	Package: *
	Pin: release a=bullseye-backports
	Pin-Priority: 500
	EOF
fi

if [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
	curl -fsSL https://apt.armbian.com/armbian.key | gpg --dearmor -o config/archives/armbian.key
	echo "deb https://apt.armbian.com/ ${IB_SUITE} main" > config/archives/armbian.list
fi

curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc > config/archives/tor.key
echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/tor.key.gpg] https://deb.torproject.org/torproject.org ${IB_SUITE} main" > config/archives/tor.list

curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o config/archives/docker.key
echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/docker.key.gpg] https://download.docker.com/linux/debian ${IB_SUITE} stable" > config/archives/docker.list

echo "deb http://deb.debian.org/debian/ trixie main contrib" > config/archives/trixie.list
cat > config/archives/trixie.pref <<- EOF
Package: *
Pin: release n=trixie
Pin-Priority: 100

Package: podman
Pin: release n=trixie
Pin-Priority: 600
EOF

# Dependencies

## Base dependencies
dpkg-deb --fsys-tarfile $base_dir/deb/${IMAGE_BASENAME}.deb | tar --to-stdout -xvf - ./usr/lib/startos/depends > config/package-lists/embassy-depends.list.chroot

## Firmware
if [ "$NON_FREE" = 1 ]; then
	echo 'firmware-iwlwifi firmware-misc-nonfree firmware-brcm80211 firmware-realtek firmware-atheros firmware-libertas firmware-amd-graphics' > config/package-lists/nonfree.list.chroot
fi

if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	echo 'raspberrypi-bootloader rpi-update parted' > config/package-lists/bootloader.list.chroot
else
	echo 'grub-efi grub2-common' > config/package-lists/bootloader.list.chroot
fi
if [ "${IB_TARGET_ARCH}" = "amd64" ] || [ "${IB_TARGET_ARCH}" = "i386" ]; then
	echo 'grub-pc-bin' >> config/package-lists/bootloader.list.chroot
fi

cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF
#!/bin/bash

set -e

apt-get install -y /deb/${IMAGE_BASENAME}.deb
rm -rf /deb

if [ "${IB_SUITE}" = bookworm ]; then
	echo 'deb https://deb.debian.org/debian/ bullseye main' > /etc/apt/sources.list.d/bullseye.list
	apt-get update
	apt-get install -y postgresql-13
	rm /etc/apt/sources.list.d/bullseye.list
	apt-get update
fi

if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
	for f in /usr/lib/modules/*; do
    	v=\${f#/usr/lib/modules/}
		echo "Configuring raspi kernel '\$v'"
    	extract-ikconfig "/usr/lib/modules/\$v/kernel/kernel/configs.ko.xz" > /boot/config-\$v
		update-initramfs -c -k \$v
	done
	ln -sf /usr/bin/pi-beep /usr/local/bin/beep
fi

useradd --shell /bin/bash -G embassy -m start9
echo start9:embassy | chpasswd
usermod -aG sudo start9

echo "start9 ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/010_start9-nopasswd"

if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
	/usr/lib/startos/scripts/enable-kiosk
fi

if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
	passwd -l start9
fi

EOF

SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}"

lb bootstrap
lb chroot
lb installer
lb binary_chroot
lb chroot_prep install all mode-apt-install-binary mode-archives-chroot
ln -sf /run/systemd/resolve/stub-resolv.conf chroot/chroot/etc/resolv.conf
lb binary_rootfs

cp $prep_results_dir/binary/live/filesystem.squashfs $RESULTS_DIR/$IMAGE_BASENAME.squashfs

if [ "${IMAGE_TYPE}" = iso ]; then

	lb binary_manifest
	lb binary_package-lists
	lb binary_linux-image
	lb binary_memtest
	lb binary_grub-legacy
	lb binary_grub-pc
	lb binary_grub_cfg
	lb binary_syslinux
	lb binary_disk
	lb binary_loadlin
	lb binary_win32-loader
	lb binary_includes
	lb binary_grub-efi
	lb binary_hooks
	lb binary_checksums
	find binary -newermt "$(date -d@${SOURCE_DATE_EPOCH} '+%Y-%m-%d %H:%M:%S')" -printf "%y %p\n" -exec touch '{}' -d@${SOURCE_DATE_EPOCH} --no-dereference ';' > binary.modified_timestamps
	lb binary_iso
	lb binary_onie
	lb binary_netboot
	lb binary_tar
	lb binary_hdd
	lb binary_zsync
	lb chroot_prep remove all mode-archives-chroot
	lb source

	mv $prep_results_dir/live-image-${IB_TARGET_ARCH}.hybrid.iso $RESULTS_DIR/$IMAGE_BASENAME.iso

elif [ "${IMAGE_TYPE}" = img ]; then

	function partition_for () {
		if [[ "$1" =~ [0-9]+$ ]]; then
			echo "$1p$2"
		else
			echo "$1$2"
		fi
	}

	ROOT_PART_END=$MAX_IMG_SECTORS
	TARGET_NAME=$prep_results_dir/${IMAGE_BASENAME}.img
	TARGET_SIZE=$[($ROOT_PART_END+1)*512]
	truncate -s $TARGET_SIZE $TARGET_NAME
	(
		echo o
		echo x
		echo i
		echo "0xcb15ae4d"
		echo r
		echo n
		echo p
		echo 1
		echo 2048
		echo 526335
		echo t
		echo c
		echo n
		echo p
		echo 2
		echo 526336
		echo $ROOT_PART_END
		echo a
		echo 1
		echo w
	) | fdisk $TARGET_NAME
	OUTPUT_DEVICE=$(losetup --show -fP $TARGET_NAME)
	mkfs.ext4 `partition_for ${OUTPUT_DEVICE} 2`
	mkfs.vfat `partition_for ${OUTPUT_DEVICE} 1`

	TMPDIR=$(mktemp -d)

	mount `partition_for ${OUTPUT_DEVICE} 2` $TMPDIR
	mkdir $TMPDIR/boot
	mount `partition_for ${OUTPUT_DEVICE} 1` $TMPDIR/boot
	unsquashfs -f -d $TMPDIR $prep_results_dir/binary/live/filesystem.squashfs

	if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
		sed -i 's| boot=embassy| init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt
		rsync -a $base_dir/raspberrypi/img/ $TMPDIR/
	fi

	umount $TMPDIR/boot
	umount $TMPDIR

	e2fsck -fy `partition_for ${OUTPUT_DEVICE} 2`
	resize2fs -M `partition_for ${OUTPUT_DEVICE} 2`

	BLOCK_COUNT=$(dumpe2fs -h `partition_for ${OUTPUT_DEVICE} 2` | awk '/^Block count:/ { print $3 }')
	BLOCK_SIZE=$(dumpe2fs -h `partition_for ${OUTPUT_DEVICE} 2` | awk '/^Block size:/ { print $3 }')
	SECTOR_LEN=$[$BLOCK_COUNT*$BLOCK_SIZE/512]

	losetup -d $OUTPUT_DEVICE

	(
		echo d
		echo 2
		echo n
		echo p
		echo 2
		echo 526336
		echo +$SECTOR_LEN
		echo w
	) | fdisk $TARGET_NAME

	ROOT_PART_END=$[526336+$SECTOR_LEN]
	TARGET_SIZE=$[($ROOT_PART_END+1)*512]
	truncate -s $TARGET_SIZE $TARGET_NAME

	mv $TARGET_NAME $RESULTS_DIR/$IMAGE_BASENAME.img

fi
