#!/usr/bin/env bash
#
# Manage a nix vm for testing.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

: ${VM_ROOT_ZFS:="zroot/linux/archmain/vm/nix"}
: ${VM_ROOT_MOUNT:="/vm/nix"}
: ${VM_DISK_SIZE:="100G"}

# Manual Steps:
#
#   Download the nixos livecd from https://channels.nixos.org/nixos-24.11/latest-nixos-gnome-x86_64-linux.iso

############## Setup #########################

function die {
    local status_code="$1"
    shift
    (>&2 echo "${@}")
    exit "$status_code"
}

function log {
    (>&2 echo "${@}")
}

############## Program #########################

function main {
    local cmd="$1"
    shift 1
    if [ "$cmd" = "init" ]; then
        vm_init "${@}"
    elif [ "$cmd" = "install" ]; then
        vm_install "${@}"
    elif [ "$cmd" = "run" ]; then
        vm_run "${@}"
    elif [ "$cmd" = "iso_ssh" ]; then
        vm_iso_ssh "${@}"
    elif [ "$cmd" = "iso_sync" ]; then
        vm_iso_sync "${@}"
    elif [ "$cmd" = "ssh" ]; then
        vm_ssh "${@}"
    elif [ "$cmd" = "sync" ]; then
        vm_sync "${@}"
    else
        die 1 "Unknown command: $cmd"
    fi
}

function vm_init {
    zfs create -o mountpoint=none -o canmount=off "$VM_ROOT_ZFS"
    zfs create -u -o "mountpoint=$VM_ROOT_MOUNT" -o canmount=on "$VM_ROOT_ZFS/settings"
    zfs create -s "-V${VM_DISK_SIZE}" -o volmode=dev -o primarycache=metadata -o secondarycache=none -o volblocksize=64K "${VM_ROOT_ZFS}/disk0"

    zfs snapshot -r "$VM_ROOT_ZFS@empty"

    zfs mount "$VM_ROOT_ZFS/settings"

    # Empty EFI variables
    cp /usr/share/edk2/x64/OVMF_VARS.4m.fd "${VM_ROOT_MOUNT}/"
}

function vm_install {
    VM_CDROM="$1"
    shift 1
    vm_run "${@}"
}

function vm_run {
    local additional_args=()

    if [ -n "${VM_CDROM:-}" ]; then
        log "Using CD $VM_CDROM"
        additional_args+=("-cdrom" "$VM_CDROM")
    fi

    exec qemu-system-x86_64 \
         -accel kvm \
         -cpu host \
         -smp cores=8 \
         -m 32768 \
         -drive file=/usr/share/edk2/x64/OVMF_CODE.4m.fd,if=pflash,format=raw,readonly=on \
         -drive if=pflash,format=raw,file="$(readlink -f "${VM_ROOT_MOUNT}/OVMF_VARS.4m.fd")" \
         -drive "if=none,file=/dev/zvol/${VM_ROOT_ZFS}/disk0,format=raw,id=hd0" \
         -device nvme,serial=deadbeef,drive=hd0 \
         -nic user,hostfwd=tcp::60022-:22 \
         -boot order=d \
         "${additional_args[@]}"
}

function vm_iso_ssh {
    exec gpg_auth ssh -p 60022 nixos@127.0.0.1
}

function vm_iso_sync {
    gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" nixos@127.0.0.1:~/
    gpg_auth ssh -p 60022 nixos@127.0.0.1 'sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount ./configuration/hosts/odo/disk-config.nix'
    gpg_auth ssh -t -p 60022 nixos@127.0.0.1 sudo nixos-install --flake ./configuration#odovm
}

function vm_ssh {
    exec gpg_auth ssh -p 60022 127.0.0.1
}

function vm_sync {
    gpg_auth rsync -av --delete --progress -e 'ssh -p 60022' "$DIR/../configuration" 127.0.0.1:~/
    gpg_auth ssh -t -p 60022 127.0.0.1 doas nixos-rebuild boot --flake ./configuration#odovm
}

main "${@}"
