#!/bin/zsh
#
# Copyright (C) 2023-2024 Dyne.org Foundation
#
# Designed, written and maintained by Denis Roio <jaromil@dyne.org>
#
# This source code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	Please refer
# to the GNU Public License for more details.
#
# You should have received a copy of the GNU Public License along with
# this source code; if not, , see <https://www.gnu.org/licenses/>.

#!/bin/bash

source /etc/boot.d/_dyne_utils
_log "dyne-install $*: $(date)"

set -e

COMMAND="${1:-persist}"
DEVICE=$(pwd)

# Check if the device is writable and mounted
if [ ! -w "$DEVICE" ]; then
    _log "Needs super-user powers: sudo dyne-install"
    _log "Volume not writable: $DEVICE"
    exit 1
fi

if ! findmnt -M "${DEVICE}" > /dev/null; then
    _log "Needs the root of a storage volume"
    _log "Invalid location: $DEVICE"
    exit 1
fi

function create_iso() {
    local iso_dir="${DEVICE}/dyne"
    local iso_file="${iso_dir}/dynebolic.iso"

    if [ -r "$iso_file" ]; then
        _log "Cannot overwrite ISO: $iso_file"
        exit 1
    fi

    mkdir -p "$iso_dir"
    xorriso -as mkisofs -iso-level 3 -o "$iso_file" \
        -full-iso9660-filenames -volid "DYNEIV" --mbr-force-bootable \
        -partition_offset 16 -joliet -joliet-long -rational-rock \
        -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -eltorito-boot \
        isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 \
        -boot-info-table --eltorito-catalog isolinux/isolinux.cat \
        -eltorito-alt-boot -e --interval:appended_partition_2:all:: \
        -no-emul-boot -isohybrid-gpt-basdat -append_partition 2 \
        $(cat /proc/sys/kernel/random/uuid) \
        /var/run/live/medium/efiboot.img /var/run/live/medium

    _log "--"
    _log "ISO successfully created! Reboot to activate."
    _log "--"
}

function create_persistence() {
    local size=${size:-3900}  # Default size is 3.9GiB
    local persist_file="${DEVICE}/dyne/dyne.nst"

    if [ -r "$persist_file" ]; then
        _log "Cannot overwrite nest: $persist_file"
        exit 1
    fi

    [[ -n "$size" ]] || _log "Size argument missing, use -s"
    [[ $size =~ ^[0-9]+$ ]] || _log "Size must be an integer (MB)"
    [[ $size -ge 512 ]] || _log "Size can't be smaller than 512 MB"

    _log "Creating nest of $size MiB in $persist_file"
    mkdir -p "${DEVICE}/dyne"
    dd if=/dev/zero of="$persist_file" bs=1048576 count="$size" oflag=direct status=progress

    local loop_device=$(losetup -f)
    losetup "$loop_device" "$persist_file"
    mkfs.ext4 -L persistence "$loop_device"

    local mount_point="/mnt/dynebolic-persistence-temp"
    mkdir -p "$mount_point"
    mount "$loop_device" "$mount_point"

    cat << EOF > "${mount_point}/persistence.conf"
/home union
/root union
/etc union
/var union
/usr union
EOF

    umount "$mount_point"
    rmdir "$mount_point"
    losetup -d "$loop_device"

    _log "--"
    _log "Nest successfully created! Reboot to activate."
    _log "--"
}

function setup_guix() {
    local guix_dir="${DEVICE}/dyne/guix-nest"

    if [ -r "/var/guix/.dyne" ]; then
        _log "Cannot overwrite Guix:"
        ls -l /var/guix
        _log "Last access: $(cat /var/guix/.dyne)"
        exit 1
    fi

    mkdir -p "${guix_dir}/var/guix" "${guix_dir}/gnu"
    mount -o bind "${guix_dir}/var/guix" /var/guix
    mount -o bind "${guix_dir}/gnu" /gnu

    _log "Executing guix-setup script"
    /usr/local/sbin/guix-setup
    date > /var/guix/.dyne
    date > /gnu/.dyne

    if [ ! -x /root/.config/guix/current ]; then
        _log "Something went wrong with linking Guix profile in /root/.config/guix/current"
    else
        _log "Guix profile is linked from ${guix_dir}/var/guix/profiles/per-user/root/current-guix to ~root/.config/guix/current"
        _log "It will be sourced from /etc/profile for new shells"
    fi

    _log "--"
    _log "Guix repository successfully configured!"
    _log "Start a new shell or reboot."
    _log "--"
}

function setup_flatpak() {
    local flatpak_dir="${DEVICE}/dyne/flatpak"

    if [ -r "/var/lib/flatpak/.dyne" ]; then
        _log "Cannot overwrite Flatpak:"
        ls -l /var/lib/flatpak
        _log "Last access: $(cat /var/lib/flatpak/.dyne)"
        exit 1
    fi

    mkdir -p "$flatpak_dir"
    mount -o bind "$flatpak_dir" /var/lib/flatpak
    flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
    date > /var/lib/flatpak/.dyne

    _log "--"
    _log "Flatpak repository successfully configured!"
    _log "--"
}

case "$COMMAND" in
    init|scan) ;;
    iso|dock) create_iso ;;
    persist|nest) create_persistence ;;
    flatpak) setup_flatpak ;;
    guix) setup_guix ;;
    *)
        _log "Command not found: $COMMAND"
        exit 1 ;;
esac

