import argparse
import os


from pathlib import Path
from uncloud.vmm import VMM
from uncloud.host.virtualmachine import update_radvd_conf, create_vxlan_br_tap

from . import virtualmachine, logger

###
# Argument parser loaded by scripts/uncloud.
arg_parser = argparse.ArgumentParser('oneshot', add_help=False)

# Actions.
arg_parser.add_argument('--list', action='store_true',
        help='list UUID and name of running VMs')
arg_parser.add_argument('--start', nargs=4,
        metavar=('NAME', 'IMAGE', 'UPSTREAM_INTERFACE', 'NETWORK'),
        help='start a VM using the OS IMAGE (full path), configuring networking on NETWORK IPv6 prefix')
arg_parser.add_argument('--stop', metavar='UUID',
        help='stop a VM')
arg_parser.add_argument('--get-status', metavar='UUID',
        help='return the status of the VM')
arg_parser.add_argument('--get-vnc', metavar='UUID',
        help='return the path of the VNC socket of the VM')
arg_parser.add_argument('--reconfigure-radvd', metavar='NETWORK',
        help='regenerate and reload RADVD configuration for NETWORK IPv6 prefix')

# Arguments.
arg_parser.add_argument('--workdir', default=Path.home(),
        help='Working directory, defaulting to $HOME')
arg_parser.add_argument('--mac',
        help='MAC address of the VM to create (--start)')
arg_parser.add_argument('--memory', type=int,
        help='Memory (MB) to allocate (--start)')
arg_parser.add_argument('--cores', type=int,
        help='Number of cores to allocate (--start)')
arg_parser.add_argument('--threads', type=int,
        help='Number of threads to allocate (--start)')
arg_parser.add_argument('--image-format', choices=['raw', 'qcow2'],
        help='Format of OS image (--start)')
arg_parser.add_argument('--accel', choices=['kvm', 'tcg'], default='kvm',
        help='QEMU acceleration to use (--start)')
arg_parser.add_argument('--upstream-interface', default='eth0',
        help='Name of upstream interface (--start)')

###
# Helpers.

# XXX: check if it is possible to use the type returned by ETCD queries.
class UncloudEntryWrapper:
    def __init__(self, value):
        self.value = value

    def value(self):
        return self.value

def status_line(vm):
     return "VM: {} {} {}".format(vm.get_uuid(), vm.get_name(), vm.get_status())

###
# Entrypoint.

def main(arguments):
    # Initialize VMM.
    workdir = arguments['workdir']
    vmm = VMM(vmm_backend=workdir)

    # Harcoded debug values.
    net_id = 0

    # Build VM configuration.
    vm_config = {}
    vm_options = [
            'mac', 'memory', 'cores', 'threads', 'image', 'image_format',
            '--upstream_interface', 'upstream_interface', 'network', 'accel'
            ]
    for option in vm_options:
        if arguments.get(option):
            vm_config[option] = arguments[option]

    vm_config['net_id'] = net_id

    # Execute requested VM action.
    if arguments['reconfigure_radvd']:
        # TODO: check that RADVD is available.
        prefix = arguments['reconfigure_radvd']
        network = UncloudEntryWrapper({
                'id': net_id,
                'ipv6': prefix
                })

        # Make use of uncloud.host.virtualmachine for network configuration.
        update_radvd_conf([network])
    elif arguments['start']:
        # Extract from --start positional arguments. Quite fragile.
        vm_config['name'] = arguments['start'][0]
        vm_config['image'] = arguments['start'][1]
        vm_config['network'] = arguments['start'][2]
        vm_config['upstream_interface'] = arguments['start'][3]

        vm_config['tap_interface'] = "uc{}".format(len(vmm.discover()))
        vm = virtualmachine.VM(vmm, vm_config)
        vm.start()
    elif arguments['stop']:
        vm = virtualmachine.VM(vmm, {'uuid': arguments['stop']})
        vm.stop()
    elif arguments['get_status']:
        vm = virtualmachine.VM(vmm, {'uuid': arguments['get_status']})
        print(status_line(vm))
    elif arguments['get_vnc']:
        vm = virtualmachine.VM(vmm, {'uuid': arguments['get_vnc']})
        print(vm.get_vnc_addr())
    elif arguments['list']:
        vms = vmm.discover()
        print("Found {} VMs.".format(len(vms)))
        for uuid in vms:
            vm = virtualmachine.VM(vmm, {'uuid': uuid})
            print(status_line(vm))
    else:
        print('Please specify an action: --start, --stop, --list,\
--get-status, --get-vnc, --reconfigure-radvd')
