#!/usr/bin/env python

import os
import sys
import argparse
import subprocess

INCLUDEOS_PREFIX = None
default_prefix = "/usr/local"

# Locate IncludeOS installation
if "INCLUDEOS_PREFIX" not in os.environ:
    INCLUDEOS_PREFIX = default_prefix
else:
    INCLUDEOS_PREFIX = os.environ['INCLUDEOS_PREFIX']

if not os.path.isdir(INCLUDEOS_PREFIX + "/includeos"):
    print "Couldn't find IncludeOS installation. If you installed to a non-default location (e.g. not " + default_loc + ") please set the environment variable INCLUDEOS_PREFIX to point to this location."
    sys.exit(0)

# Location of vmrunner
sys.path.append(INCLUDEOS_PREFIX + "/includeos")

from vmrunner.prettify import color


# Argparse
parser = argparse.ArgumentParser(
  description="IncludeOS vmrunner. Builds and runs an IncludeOS service")

parser.add_argument("-c", "--clean", dest="clean", action="store_true",
                    help="Clean previous build before building")

parser.add_argument("-b", "--build", dest="build", action="store_true", default=False,
                    help="Only build the service, don't start it in a VM")

parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=False,
                    help="Verbose output when building")

parser.add_argument("--create-bridge", dest="bridge", action="store_true",
                    help="Create bridge43, used in local testing when TAP devices are supported")

parser.add_argument("-g", "--grub", dest="grub", action="store_true",
                    help="Create image with GRUB bootloader that will boot provided binary")

parser.add_argument("-j", "--config", dest="config", type = str, metavar = "PATH",
                    help="Location of VM config file - JSON validated against a schema")

parser.add_argument('vm_location', action="store", type = str,
                    help="Location of the IncludeOS service binary, image or source")

parser.add_argument('vmargs', nargs='*', help="Arguments to pass on to the VM start / main")

args = parser.parse_args()


# Pretty printing from this command
nametag = "<boot>"
INFO = color.INFO(nametag)

# Override VM output prepension
color.VM_PREPEND = ""

# in verbose mode we will set VERBOSE=1 for this environment
VERB = False
if (args.verbose):
    os.environ["VERBOSE"] = "1"
    VERB = True
    print INFO, "VERBOSE mode set for environment"
# Avoid the verbose var to hang around next run
elif "VERBOSE" in os.environ:
    del os.environ["VERBOSE"]

# Note: importing vmrunner will make it start looking for VM's
# vmrunner also relies on the verbose env var to be set on initialization
from vmrunner import vmrunner


# We can boot either a binary without bootloader, or an image with bootloader allready attached
has_bootloader = False

if VERB: print INFO , "Args to pass to VM: ", args.vmargs
# path w/name of VM image to run
image_name = args.vm_location

# if the binary argument is a directory, go there immediately and
# then initialize stuff ...
if (os.path.isdir(args.vm_location)):
    image_name = os.path.abspath(args.vm_location)
    if VERB: print INFO, "Changing directory to  " + image_name
    os.chdir(os.path.abspath(args.vm_location))


if len(vmrunner.vms) < 1:
    # This should never happen - there should always be a default
    print color.FAIL("No vm object found in vmrunner - nothing to boot")
    exit(-1)

if VERB:
    print INFO, len(vmrunner.vms), "VM initialized. Commencing build- and boot..."

config = None
if args.config:
    config = os.path.abspath(args.config)
    if VERB: print INFO, "Using config file", config

vm = vmrunner.vm(config = config)

# For multible JSON configs, find the one matching the provided image name
for vm_ in vmrunner.vms:
    if vm_._config.has_key("image") and vm_._config["image"].startswith(image_name):
        vm = vm_

# Don't listen to events needed by testrunner
vm.on_success(lambda: None, do_exit = False)

if (args.clean):
    print INFO, "Cleaning build"
    vm.clean()

if (args.bridge):
    print INFO, "Creating bridge"
    subprocess.call(INCLUDEOS_PREFIX + "/includeos/scripts/create_bridge.sh", shell=True)

# If the binary name is a folder, such as ".", build the service
if (os.path.isdir(image_name)):
    vm.cmake()
    # also, set image name to
    image_name = open("binary.txt", 'r').read()
# If the binary name has an extension (e.g. a '.'), assume it has a bootloader attached
# NOTE: the idea is to support e.g. .vdi and virtualbox etc. in the future
elif ("." in args.vm_location):
    has_bootloader = True

if (args.grub):
  print INFO, "Creating GRUB image from ", args.vm_location
  subprocess.call(INCLUDEOS_PREFIX + "/includeos/scripts/grubify.sh " + image_name, shell=True)
  image_name = image_name + ".grub.img"
  has_bootloader = True

# Skip starting a VM if we are only building
if (args.build): exit(0);

if (not has_bootloader):
    vm.boot(timeout = None, multiboot = True, kernel_args = " ".join(args.vmargs), image_name = image_name)
else:
    vm.boot(timeout = None, multiboot = False, kernel_args = None, image_name = image_name)
