#!/bin/bash
set -euo pipefail

# Simple ARM64 Alpine Linux QEMU setup for hdmistat testing

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
WORK_DIR="${PROJECT_DIR}/qemu-alpine-test"

# QEMU settings
QEMU_MEM="2G"
QEMU_CPUS="4"
DISK_SIZE="4G"
VNC_PORT="5902"

# Alpine Linux ARM64
ALPINE_VERSION="3.19"
ALPINE_ISO="alpine-virt-${ALPINE_VERSION}.0-aarch64.iso"
ALPINE_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION}/releases/aarch64/${ALPINE_ISO}"

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*"
}

error() {
    echo -e "${RED}[ERROR]${NC} $*" >&2
    exit 1
}

# Check dependencies
check_dependencies() {
    log "Checking dependencies..."
    
    local deps=("qemu-system-aarch64" "wget")
    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            error "$dep not found"
        fi
    done
    
    log "Dependencies OK"
}

# Setup directories
setup_directories() {
    log "Setting up directories..."
    mkdir -p "$WORK_DIR"
}

# Download Alpine Linux
download_alpine() {
    cd "$WORK_DIR"
    
    if [ -f "$ALPINE_ISO" ]; then
        log "Alpine Linux ISO already exists"
        return
    fi
    
    log "Downloading Alpine Linux ARM64..."
    wget -O "$ALPINE_ISO" "$ALPINE_URL" || error "Failed to download Alpine"
}

# Create disk image
create_disk() {
    cd "$WORK_DIR"
    
    if [ -f "hdmistat-test.qcow2" ]; then
        log "Disk image already exists"
        return
    fi
    
    log "Creating disk image..."
    qemu-img create -f qcow2 hdmistat-test.qcow2 $DISK_SIZE
}

# Create setup script
create_setup_script() {
    cat > "${WORK_DIR}/setup-hdmistat.sh" << 'EOF'
#!/bin/sh
set -e

echo "==================================="
echo "hdmistat Alpine Linux Setup Script"
echo "==================================="

# Update packages
echo "Updating packages..."
apk update

# Install required packages
echo "Installing build dependencies..."
apk add --no-cache \
    go \
    git \
    make \
    gcc \
    musl-dev \
    linux-headers \
    bash \
    sudo \
    fbset \
    util-linux

# Install newer Go if needed
GO_VERSION="1.24.4"
if ! go version | grep -q "$GO_VERSION"; then
    echo "Installing Go $GO_VERSION..."
    wget -q -O /tmp/go.tar.gz "https://go.dev/dl/go${GO_VERSION}.linux-aarch64.tar.gz"
    rm -rf /usr/local/go
    tar -C /usr/local -xzf /tmp/go.tar.gz
    rm /tmp/go.tar.gz
    export PATH="/usr/local/go/bin:$PATH"
fi

# Build hdmistat from mounted source
if [ -d "/mnt/hdmistat" ]; then
    echo "Building hdmistat from source..."
    cd /mnt/hdmistat
    make build
    cp hdmistat /usr/local/bin/
    echo "hdmistat installed successfully!"
else
    echo "Warning: hdmistat source not mounted at /mnt/hdmistat"
    echo "Mount with: mount -t 9p -o trans=virtio,version=9p2000.L hdmistat /mnt/hdmistat"
fi

# Create test config
mkdir -p /etc/hdmistat
cat > /etc/hdmistat/config.yaml << 'CONFIG_EOF'
framebuffer_device: /dev/fb0
rotation_interval: 10s
update_interval: 1s
log_level: info
width: 1024
height: 768
screens:
  - overview
  - top_cpu
  - top_memory
CONFIG_EOF

echo ""
echo "Setup complete!"
echo ""
echo "To test hdmistat:"
echo "1. hdmistat info          - Show system information"
echo "2. hdmistat daemon        - Run the framebuffer daemon"
echo "3. hdmistat status        - Check daemon status"
echo ""
echo "Note: Framebuffer access requires appropriate permissions"
EOF
    chmod +x "${WORK_DIR}/setup-hdmistat.sh"
}

# Create run script
create_run_script() {
    cat > "${WORK_DIR}/run-qemu.sh" << EOF
#!/bin/bash
cd "$WORK_DIR"

echo "Starting QEMU ARM64 Alpine Linux..."
echo ""
echo "Instructions:"
echo "1. Boot Alpine Linux and login as root (no password)"
echo "2. Mount the hdmistat source: mkdir -p /mnt/hdmistat && mount -t 9p -o trans=virtio,version=9p2000.L hdmistat /mnt/hdmistat"
echo "3. Run the setup script: sh /mnt/hdmistat/scripts/qemu-alpine-test/setup-hdmistat.sh"
echo ""
echo "VNC available on port $VNC_PORT"
echo "Press Ctrl+A, X to quit"
echo ""

# Find EFI firmware
EFI_CODE=""
for path in /nix/store/*/share/qemu/edk2-aarch64-code.fd /run/current-system/sw/share/qemu/edk2-aarch64-code.fd; do
    if [ -f "\$path" ]; then
        EFI_CODE="\$path"
        break
    fi
done

BIOS_ARGS=""
if [ -n "\$EFI_CODE" ]; then
    BIOS_ARGS="-bios \$EFI_CODE"
fi

qemu-system-aarch64 \\
    -M virt \\
    -accel hvf \\
    -cpu host \\
    -smp $QEMU_CPUS \\
    -m $QEMU_MEM \\
    -drive file=hdmistat-test.qcow2,format=qcow2,if=virtio \\
    -cdrom $ALPINE_ISO \\
    -boot d \\
    -netdev user,id=net0,hostfwd=tcp::2223-:22 \\
    -device virtio-net-pci,netdev=net0 \\
    -device virtio-gpu-pci \\
    -display default,show-cursor=on \\
    -vnc :2 \\
    -serial mon:stdio \\
    -virtfs local,path="${PROJECT_DIR}",mount_tag=hdmistat,security_model=none,id=hdmistat \\
    \$BIOS_ARGS \\
    \${@}
EOF
    chmod +x "${WORK_DIR}/run-qemu.sh"
}

# Create VNC helper
create_vnc_helper() {
    cat > "${WORK_DIR}/view-vnc.sh" << EOF
#!/bin/bash
echo "Opening VNC viewer on localhost:$VNC_PORT"
vncviewer localhost:$VNC_PORT || open vnc://localhost:$VNC_PORT || echo "Connect to VNC at localhost:$VNC_PORT"
EOF
    chmod +x "${WORK_DIR}/view-vnc.sh"
}

# Print instructions
print_instructions() {
    echo ""
    echo "======================================="
    echo "QEMU ARM64 Alpine Setup Complete!"
    echo "======================================="
    echo ""
    echo "To start testing:"
    echo "  cd $WORK_DIR"
    echo "  ./run-qemu.sh"
    echo ""
    echo "This creates a lightweight Alpine Linux ARM64 VM with:"
    echo "  - Native ARM64 virtualization (hvf)"
    echo "  - Framebuffer support"
    echo "  - hdmistat source mounted via 9p"
    echo "  - No cloud-init required"
    echo ""
}

# Main
main() {
    log "Setting up QEMU ARM64 Alpine environment..."
    
    check_dependencies
    setup_directories
    download_alpine
    create_disk
    create_setup_script
    create_run_script
    create_vnc_helper
    print_instructions
    
    log "Setup complete!"
}

main "$@"