#!/usr/bin/env python3
"""Text-admin entry point for desktop VM templates and persistent instances."""
import argparse
import getpass
import json
from pathlib import Path
import sys

source = Path(__file__).resolve().parents[1] / 'services/helpers'
sys.path.insert(0, str(source) if source.is_dir() else '/usr/local/sbin')
import mykos_vm as vm


def show(data):
    print(json.dumps(data, indent=2))


def ubuntu_swap_instructions(os_name):
    ram = vm.read(os_name).get('ram_mib', 4096)
    print('Configure 12 GiB swap inside the installed Ubuntu VM before capturing:')
    print('  curl --fail --show-error --location https://YOUR_MYKOS_HOST/mykos/image-setup/ubuntu.py -o /tmp/mykos-ubuntu-setup.py')
    print('  sudo python3 /tmp/mykos-ubuntu-setup.py --ram-mib ' + str(ram))
    print('This also enables the direct guest serial console running su - root (no SSH).')
    print('Replace YOUR_MYKOS_HOST with this MYKOS server hostname. Verify with: swapon --show')


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('action', choices=['create','prepare','start','stop','resume','info','list','toggle','checkpoint-enable','cleanup','memory','memory-configure'])
    parser.add_argument('selection', nargs='?')
    parser.add_argument('os', nargs='?')
    parser.add_argument('--replace', action='store_true', help='Replace an existing prepared checkpoint')
    parser.add_argument('--target-mib', type=int, help='Guarded balloon target; omit to inspect driver support')
    parser.add_argument('--confirm', help='Exact instance ID confirming a cold restart for RAM resizing')
    parser.add_argument('--ram-mib', type=int, help='RAM allocation for a new image and its state capture')
    args = parser.parse_args()
    if args.ram_mib is not None and args.action != 'create': parser.error('--ram-mib requires create')
    if args.target_mib is not None and args.action not in ('memory','memory-configure'): parser.error('--target-mib requires memory')
    if args.action == 'list':
        for path in vm.ROOT.glob('*.json'): show(vm.links(vm.read(path.stem)))
        return
    if not args.selection: parser.error('Select an OS template or eight-digit code')
    if args.action == 'create':
        os_name = args.selection
        if os_name not in vm.VERSIONS: parser.error('OS must be one of: ' + ', '.join(vm.VERSIONS))
        username = password = None
        if vm.VERSIONS[os_name][0] == 'windows':
            username = input('Windows username: ').strip()
            password = getpass.getpass('Windows password: ')
            if password != getpass.getpass('Confirm password: '): raise ValueError('Passwords do not match')
        ram_mib = args.ram_mib
        if ram_mib is None and sys.stdin.isatty():
            default = vm.image_memory(os_name)
            entered = input('Image RAM in MiB [' + str(default) + ']: ').strip()
            if entered:
                if not entered.isascii() or not entered.isdigit(): raise ValueError('Enter RAM as integer MiB')
                ram_mib = int(entered)
        show(vm.create(os_name, username, password, ram_mib))
        print('Complete installation in console_url. Then run: ./vm prepare ' + os_name)
        print('For macOS/Ubuntu, complete account setup in the browser console.')
        if os_name.startswith('ubuntu'):
            print('Inside Ubuntu before capture: sudo apt-get update && sudo apt-get install -y isc-dhcp-client iproute2 net-tools')
            ubuntu_swap_instructions(os_name)
    elif args.action == 'memory-configure':
        if args.confirm != args.selection or args.target_mib is None:
            parser.error('Cold memory resize requires --target-mib and --confirm INSTANCE_ID')
        show(vm.configure_memory(args.selection, args.target_mib))
    elif args.action == 'memory': show(vm.memory(args.selection, args.target_mib))
    elif args.action == 'checkpoint-enable':
        if input('Restart this template with CPU settings for memory checkpoints? [y/N] ').lower() == 'y':
            show(vm.checkpoint_enable(args.selection))
    elif args.action == 'prepare':
        if args.selection.startswith('ubuntu'):
            print('Ubuntu guest networking packages must be installed before capture:')
            print('  sudo apt-get update && sudo apt-get install -y isc-dhcp-client iproute2 net-tools')
            print('Run this inside the Ubuntu desktop terminal. The host/QEMU wrapper is separate.')
            ubuntu_swap_instructions(args.selection)
            if input('Have you configured and verified 12 GiB swap inside Ubuntu? [y/N] ').lower() != 'y':
                raise ValueError('Configure and verify Ubuntu swap before capturing its live state')
        print('Finish installation and eject installation media first. Generalize Windows before cloning if required.')
        if input('Capture VM state, then shut down and commit the template? [y/N] ').lower() == 'y':
            show(vm.prepare(args.selection, replace=args.replace))
    elif args.action == 'start': show(vm.start(args.selection, args.os))
    elif args.action == 'toggle': show(vm.stop(args.selection) if vm.info(args.selection)['running'] else vm.resume(args.selection))
    else: show(getattr(vm, args.action)(args.selection))


if __name__ == '__main__':
    try: main()
    except (ValueError, RuntimeError, OSError) as error: raise SystemExit(str(error))
