#! /bin/bash

echo
echo "________________________________________"
echo ' Start building ISO file'
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"

DISTPATH=$1
SCRIPT_DIR="/usr/lib/iso-constructor"
SCRIPTS_DIR="$SCRIPT_DIR/scripts"

DESKTOPENV='kde'
if [ -e /usr/bin/startxfce4 ]; then
    DESKTOPENV='xfce'
fi

# Check before continue
if [ -z "$DISTPATH" ] || [ ! -d "$DISTPATH/boot" ] || [ ! -d "$DISTPATH/root" ]; then
    echo 'ERROR: current path must contain root and boot directories'
    exit 1
fi
HOSTEFIARCH=$(ls /usr/lib/grub/ 2>/dev/null | grep efi | cut -d'-' -f1)
if [ -z "$HOSTEFIARCH" ]; then
    echo 'ERROR: cannot find host EFI architecture in /usr/lib/grub'
    exit 2
fi
ISOHDPFX=$(dpkg -S isohdpfx.bin | awk '{print $2}')
if [ -z "$ISOHDPFX" ]; then
    echo 'ERROR: cannot find path to isohdpfx.bin - install isolinux'
    exit 3
fi

# Cleanup offline repository directories
# It never really worked
rm -rf $DISTPATH/dists
rm -rf $DISTPATH/pool

# Chroot into distribution root directory and cleanup first
USERDIR="/home/$(logname)/.config/iso-constructor"
# Packages that must NOT be treated as obsolete - comma separated list
# Set to '*' to keep everything
KEEPPACKAGES=$(cat "$SCRIPTS_DIR/keep-packages" | sed -z 's/\n/,/g;s/,$//;s/ //')
if [ -f "$USERDIR/keep-packages" ]; then
    KEEPPACKAGES=$(cat "$USERDIR/keep-packages" | sed -z 's/\n/,/g;s/,$//;s/ //')
    echo "________________________________________"
    echo " Using custom keep-packages file: $USERDIR/keep-packages"
    echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
fi

echo "________________________________________"
echo " Run configuration scripts"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
CODENAME=$(egrep '^DISTRIB_CODENAME|^VERSION_CODENAME' "$DISTPATH/root/etc/"*release | head -n 1 | cut -d'=' -f 2  | tr -d ' "_\-')
DISTRO_CONFIG="${CODENAME,,}.sh"
if [ -e "$SCRIPTS_DIR/distro_config/$DISTRO_CONFIG" ]; then
    cp -v "$SCRIPTS_DIR/distro_config/$DISTRO_CONFIG" "$DISTPATH/root/"
    bash $SCRIPTS_DIR/chroot-dir.sh "$DISTPATH/root" "bash /$DISTRO_CONFIG"
    rm -f "$DISTPATH/root/$DISTRO_CONFIG"
    echo
fi
if [ -e "$USERDIR/$DISTRO_CONFIG" ]; then
    cp -v "$USERDIR/$DISTRO_CONFIG" "$DISTPATH/root/"
    bash $SCRIPTS_DIR/chroot-dir.sh "$DISTPATH/root" "bash /$DISTRO_CONFIG"
    rm -f "$DISTPATH/root/$DISTRO_CONFIG"
    echo
fi

echo "________________________________________"
echo " Run cleanup script"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
cp -v "$SCRIPTS_DIR/_chroot-cleanup.sh" "$DISTPATH/root/"
bash $SCRIPTS_DIR/chroot-dir.sh "$DISTPATH/root" "bash /_chroot-cleanup.sh \"$KEEPPACKAGES\""
rm -f "$DISTPATH/root/_chroot-cleanup.sh"
echo

# Global variables
DESCRIPTION=$(egrep '^DISTRIB_DESCRIPTION|^PRETTY_NAME' "$DISTPATH/root/etc/"*release | head -n 1 | cut -d'=' -f 2  | sed s'/(.*)//g;s/gnu//I;s/linux//I;s/bit//I;s/[/"\-]//g;s/ \+/ /g')
CODENAME=$(egrep '^DISTRIB_CODENAME|^VERSION_CODENAME' "$DISTPATH/root/etc/"*release | head -n 1 | cut -d'=' -f 2  | tr -d ' "_\-')
SHORTDATE=$(date +"%Y%m")
ISODATE=$(date +"%FT%T")
MODDATE=$(date +"%Y%m%d%H%M%S00")
ISOFILENAME=$(echo $DESCRIPTION | tr ' ' '_' | cut -d'-' -f 1 | tr '[:upper:]' '[:lower:]')"_$SHORTDATE"
LOCALIZED=$(grep -oP '(?<=LANG=).*?(?=_)' "$DISTPATH/root/etc/default/locale" | grep -v 'en')
if [ -n "$LOCALIZED" ]; then
    ISOFILENAME="$ISOFILENAME_$LOCALIZED"
fi
ISOFILENAME="$ISOFILENAME.iso"

echo "________________________________________"
echo " Create disk info directories/files"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
mkdir -p "$DISTPATH/boot/live"
mkdir -p "$DISTPATH/boot/.disk"
touch "$DISTPATH/boot/.disk/base_installable"
touch "$DISTPATH/boot/.disk/udeb_include"
echo "$DESCRIPTION Live $(date +"%Y%m") $DESKTOPENV $ISODATE" > "$DISTPATH/boot/.disk/info"
if [ ! -e "$DISTPATH/boot/.disk/base_components" ]; then
    echo 'main' > "$DISTPATH/boot/.disk/base_components"
fi
if [ ! -e "$DISTPATH/boot/.disk/base_components" ]; then
    echo 'live' > "$DISTPATH/boot/.disk/cd_type"
fi
cat >"$DISTPATH/boot/.disk/udeb_include" <<EOF
netcfg
ethdetect
pcmciautils-udeb
live-installer
EOF

# Copy system boot files (initrd, vmlinuz, etc) to live directory 
rm -r "$DISTPATH/boot/live/"*
cp -vf "$DISTPATH/root/boot/"* "$DISTPATH/boot/live/" 2>/dev/null

echo "________________________________________"
echo " Generate grub.cfg / isolinux.cfg"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
cp "$SCRIPTS_DIR/_grubgen.sh" "$DISTPATH/boot/"
cp "$SCRIPTS_DIR/_isolinuxgen.sh" "$DISTPATH/boot/"
cd "$DISTPATH/boot"
bash _grubgen.sh
bash _isolinuxgen.sh
rm *.sh

# check for custom mksquashfs (for multi-threading, new features, etc.)
echo "________________________________________"
echo " Create squashfs file"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
if [ -z "$MKSQUASHFS" ] || [ "$MKSQUASHFS" == 'mksquashfs' ]; then
    # Use half of the cpu cores
    NRCORES=$(egrep '^cpu cores.*([0-9])' /proc/cpuinfo | head -n 1 | cut -d':' -f 2 | tr -d ' ')
    AVCORES=$((NRCORES / 2))
    if [ -z "$AVCORES" ] || [ "$AVCORES" -lt 1 ]; then
        AVCORES=1
    fi
    CMD="mksquashfs \"$DISTPATH/root/\" \"$DISTPATH/boot/live/filesystem.squashfs\" -comp xz -processors $AVCORES -wildcards -ef \"$SCRIPTS_DIR/excludes\""
    echo $CMD
    eval $CMD
else
    eval "$MKSQUASHFS \"$DISTPATH/root\" \"$DISTPATH/boot/live/filesystem.squashfs\""
fi

echo "________________________________________"
echo " Update isolinux files"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
chmod -R +w "$DISTPATH/boot/isolinux"
cp -vf "/usr/lib/syslinux/modules/bios/"{chain.c32,hdt.c32,libmenu.c32,libgpl.c32,reboot.c32,vesamenu.c32,poweroff.c32,ldlinux.c32,libcom32.c32,libutil.c32} "$DISTPATH/boot/isolinux/"
cp -vf '/usr/lib/ISOLINUX/isolinux.bin' "$DISTPATH/boot/isolinux"
cp -vf '/usr/lib/syslinux/memdisk' "$DISTPATH/boot/isolinux"
cp -vf "$SCRIPT_DIR/isolinux/"* "$DISTPATH/boot/isolinux/"

echo "________________________________________"
echo " Copy ISO boot files"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
if [ -d "$DISTPATH/root/usr/lib/grub/x86_64-efi" ]; then
    mkdir -p "$DISTPATH/boot/boot/grub/x86_64-efi"
    rm -rf "$DISTPATH/boot/boot/grub/x86_64-efi/"*
    echo "Copy /usr/lib/grub/x86_64-efi to $DISTPATH/boot/boot/grub/"
    cp -f "$DISTPATH/root/usr/lib/grub/x86_64-efi/"* "$DISTPATH/boot/boot/grub/x86_64-efi/"
fi
cp -vf "$SCRIPT_DIR/grub/"* "$DISTPATH/boot/boot/grub/"

# Copy the signed efi files
rm -rf "$DISTPATH/boot/EFI"
mkdir -p "$DISTPATH/boot/EFI/boot"
cp -av $DISTPATH/root/usr/lib/shim/shim*.efi.signed $DISTPATH/boot/EFI/boot/bootx64.efi
cp -av $DISTPATH/root/usr/lib/grub/x86_64-efi-signed/gcdx64.efi.signed $DISTPATH/boot/EFI/boot/grubx64.efi

echo "________________________________________"
echo " Create img file"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
if [ -f $DISTPATH/boot/EFI/boot/grubx64.efi ]; then
    cat > $DISTPATH/grub.cfg << EOF
search --set=root --file /.disk/info
if [ -e (\$root)/boot/grub/grub.cfg ]; then
    set prefix=(\$root)/boot/grub
    configfile \$prefix/grub.cfg
else
    echo 'Could not find /boot/grub/grub.cfg!'
fi
EOF
    dd if=/dev/zero of=$DISTPATH/boot/boot/grub/efi.img bs=1M count=5
    mkfs.vfat $DISTPATH/boot/boot/grub/efi.img 
    mmd -i $DISTPATH/boot/boot/grub/efi.img EFI EFI/boot boot boot/grub
    mcopy -vi $DISTPATH/boot/boot/grub/efi.img "$DISTPATH/boot/EFI/boot/bootx64.efi" ::EFI/boot/
    mcopy -vi $DISTPATH/boot/boot/grub/efi.img "$DISTPATH/boot/EFI/boot/grubx64.efi" ::EFI/boot/
    mcopy -vi $DISTPATH/boot/boot/grub/efi.img "$DISTPATH/grub.cfg" ::boot/grub/
    rm $DISTPATH/grub.cfg
fi

# remove existing iso
rm "$DISTPATH/"*.iso* 2>/dev/null

# Create an md5sum file for the isolinux/grub integrity check
cat >'md5sum.txt' <<EOF
## This file contains the list of md5 checksums of all files on this medium.
## You can verify them automatically with the 'verify-checksums' boot parameter
## or manually with: 'md5sum -c md5sum.txt'.
EOF
for F in $(find . -type f ! -name "md5sum.txt" ! -name "isolinux.bin" ! -name "boot.cat"); do
    md5sum "$F" >> 'md5sum.txt'
done

echo "________________________________________"
echo " Build the iso file"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
cd "$DISTPATH"
CMD="xorriso -as mkisofs -R -r -J -joliet-long -l -iso-level 3 -isohybrid-mbr ${ISOHDPFX} -partition_offset 16 -A \"${CODENAME} Live\" -publisher \"${CODENAME} Live project\" -V \"${CODENAME^^}\" --modification-date=${MODDATE} -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus -o \"${ISOFILENAME}\" boot"
echo $CMD
eval $CMD

# Save the xorriso command to mkisofs file
echo "$CMD" > "./boot/.disk/mkisofs"

# Create sha256 file
sha256sum "$ISOFILENAME" > "$ISOFILENAME.sha256"

echo
echo "________________________________________"
echo " Building $ISOFILENAME finished"
echo "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
exit 0
