#!/bin/bash
set -euo pipefail

# ARM-native QEMU test with framebuffer using Alpine Linux (virtualization, not emulation)

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

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

# Alpine Linux ARM64 (native virtualization on Apple Silicon)
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..."
    
    if ! command -v qemu-system-aarch64 &> /dev/null; then
        error "qemu-system-aarch64 not found"
    fi
    
    log "Dependencies OK"
}

# Setup directories
setup_directories() {
    log "Setting up directories..."
    mkdir -p "$WORK_DIR"
    mkdir -p "$CLOUD_INIT_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..."
    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 startup script that will be run inside the VM
create_vm_setup_script() {
    cat > "${WORK_DIR}/setup-hdmistat.sh" << 'EOF'
#!/bin/sh
set -e

echo "Setting up hdmistat test environment..."

# Install required packages
apk update
apk add --no-cache \
    go \
    git \
    make \
    gcc \
    musl-dev \
    linux-headers \
    bash \
    sudo \
    openrc \
    fbset \
    util-linux

# Enable framebuffer console
rc-update add consolefont boot
rc-update add keymaps boot

# Create test user
adduser -D -s /bin/bash testuser
echo "testuser:hdmistat" | chpasswd
addgroup testuser wheel
echo "%wheel ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/wheel

# Mount shared folder if available
if [ -e /dev/vdb ]; then
    mkdir -p /mnt/hdmistat
    mount /dev/vdb /mnt/hdmistat
fi

# Build hdmistat
if [ -d "/mnt/hdmistat" ]; then
    echo "Building hdmistat from mounted source..."
    cd /mnt/hdmistat
    make build
    cp hdmistat /usr/local/bin/
else
    echo "Installing hdmistat from git..."
    export GOPROXY=https://proxy.golang.org
    go install git.eeqj.de/sneak/hdmistat/cmd/hdmistat@latest
    cp ~/go/bin/hdmistat /usr/local/bin/
fi

# Create init script for hdmistat
cat > /etc/init.d/hdmistat << 'INIT_EOF'
#!/sbin/openrc-run

name="hdmistat"
description="HDMI Statistics Display Daemon"
command="/usr/local/bin/hdmistat"
command_args="daemon"
command_background=true
pidfile="/run/${RC_SVCNAME}.pid"
start_stop_daemon_args="--stdout /var/log/hdmistat.log --stderr /var/log/hdmistat.log"

depend() {
    need localmount
    after bootmisc
}
INIT_EOF

chmod +x /etc/init.d/hdmistat

# Create config directory
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

# Enable services
rc-update add hdmistat default

echo "Setup complete! You can now:"
echo "1. Switch to framebuffer console with Alt+F1"
echo "2. Check hdmistat status: rc-service hdmistat status"
echo "3. View logs: tail -f /var/log/hdmistat.log"
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 with framebuffer support..."
echo ""
echo "After boot:"
echo "1. Login as root (no password)"
echo "2. Run: /mnt/setup-hdmistat.sh"
echo "3. Switch to framebuffer with Alt+F1 to see hdmistat"
echo "4. VNC available on port $VNC_PORT"
echo ""
echo "Press Ctrl+A, X to quit"
echo ""

# Create a FAT filesystem image with our setup script
if [ ! -f "scripts.img" ]; then
    dd if=/dev/zero of=scripts.img bs=1M count=10
    mkfs.vfat scripts.img
    mcopy -i scripts.img setup-hdmistat.sh ::
fi

# Find QEMU firmware files
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

if [ -z "$EFI_CODE" ]; then
    echo "Warning: EFI firmware not found, trying without it"
    BIOS_ARGS=""
else
    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 \\
    -drive file=scripts.img,format=raw,if=virtio \\
    -drive file="${PROJECT_DIR}",if=virtio,format=raw,readonly=on \\
    -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 \\
    $BIOS_ARGS \\
    \${@}
EOF
    chmod +x "${WORK_DIR}/run-qemu.sh"
}

# Create helper scripts
create_helpers() {
    # VNC viewer
    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
EOF
    chmod +x "${WORK_DIR}/view-vnc.sh"
    
    # Instructions
    cat > "${WORK_DIR}/README.md" << EOF
# QEMU Framebuffer Test Environment

This is a lightweight QEMU setup for testing hdmistat with framebuffer support.

## Quick Start

1. Start QEMU:
   \`\`\`bash
   ./run-qemu.sh
   \`\`\`

2. In the Alpine Linux boot menu, select the default option

3. Login as root (no password required)

4. Mount the scripts volume:
   \`\`\`bash
   mkdir -p /mnt
   mount /dev/vdb /mnt
   \`\`\`

5. Run the setup script:
   \`\`\`bash
   /mnt/setup-hdmistat.sh
   \`\`\`

6. Start hdmistat:
   \`\`\`bash
   rc-service hdmistat start
   \`\`\`

7. View the framebuffer output:
   - Press Alt+F1 to switch to the framebuffer console
   - Or use VNC: ./view-vnc.sh

## Tips

- The framebuffer is available at /dev/fb0
- Default resolution is 1024x768
- hdmistat source is mounted at /dev/vdc (mount to /mnt/hdmistat)
- Logs are at /var/log/hdmistat.log

## Troubleshooting

If framebuffer doesn't work:
1. Check if /dev/fb0 exists
2. Try: modprobe fbdev
3. Check dmesg for framebuffer messages
EOF
}

# Print instructions
print_instructions() {
    echo ""
    echo "======================================"
    echo "QEMU Framebuffer Test Setup Complete!"
    echo "======================================"
    echo ""
    echo "To start testing:"
    echo "  cd $WORK_DIR"
    echo "  ./run-qemu.sh"
    echo ""
    echo "See README.md for detailed instructions"
    echo ""
}

# Main
main() {
    log "Setting up QEMU framebuffer test environment..."
    
    check_dependencies
    setup_directories
    download_alpine
    create_disk
    create_vm_setup_script
    create_run_script
    create_helpers
    print_instructions
    
    log "Setup complete!"
}

main "$@"