#!/bin/bash
#############################################
# VirtualBox VM Scripts - vm-start
# by ulisse aka A. Livio Beccaria
#
# vm-start starts a VM :)
#############################################

APP_NAME="vm-start - VirtualBox VM Scripts"
VERSION="18.6.1"
AUTHOR="DiSIT"

# get source folder
SRC_DIR="$(dirname $(readlink -f $0))"

# include global settings
source "${SRC_DIR}/settings/settings"

# include common code
source "${SRC_DIR}/settings/common"

###############################################################################
# Title
##############
title () {
    echo -e "$APP_NAME by $AUTHOR"
    echo "v.$VERSION"
    echo
}
###############################################################################



###############################################################################
# Debug info
##################
debug () {
    if [[ ${DEBUG} == 1 ]]; then
        cat << EOF
Debug info:
  vm_id = $VM_ID
  fullscreen = $FULLSCREEN
  no-init = $NO_INIT
  no-run = $NO_RUN
  discard-state = $DISCARD_STATE
  hd-autoreset = $HD_AUTORESET

EOF
    fi
}
###############################################################################



###############################################################################
# Usage
#######
usage () {
    if [[ "$@" != "" ]]; then
        echo >&2 "$@"
        echo
    fi
    cat << EOF
Usage: ${BOLD}$0${NORMAL} <vm_id | vm_name> [OPTION]...

Options:
  ${BOLD}-g, --gui${NORMAL}
      launch VirtualBox in GUI mode (in a window with menus)
  ${BOLD}-f, --fullscreen${NORMAL}
      launch VirtualBox in fullscreen mode
  ${BOLD}-i, --no-init${NORMAL}
      don't reset VM (NIC MAC address, HDs and snapshot, if any)
  ${BOLD}-r, --no-run${NORMAL}
      the VM will not get started, just resetted (if --no-init is not set)
  ${BOLD}-s, --discard-state${NORMAL}
      discard VM's saved state, if any
  ${BOLD}-a, --hd-autoreset${NORMAL}
      set HD images autoreset flag
  ${BOLD}-d, --debug${NORMAL}
      print some debug info
  ${BOLD}-h, --help${NORMAL}
      print this help info

EOF

    print_vm_list
    echo
    exit 1
}
###############################################################################



###############################################################################
# vbox_remove_medium (disk_img, port_num)
###################
vbox_remove_medium () {
    local disk_img=$1
    local port_num=$2
    echo "Removing disk ${port_num}..."
    vboxmanage storageattach "${VM_NAME}" --storagectl "${STORAGE_CONTROLLER_NAME}" --port ${port_num} --device 0 --medium none
    sleep 1
    vboxmanage showvminfo "${VM_NAME}" | grep -m1 -Po ".*\.vdi.*\(UUID: \K(.*)" | while read -r line ; do
        # remove last ')'
        TMP_DIFF=${line::-1}
        if [ "${TMP_DIFF}" != "" ]; then
            vboxmanage closemedium disk "${TMP_DIFF}" --delete
        fi
    done
}



###############################################################################
# vbox_remove_media
###################
vbox_remove_media () {
    if [[ "${DISK_IMAGE_1}" != "" ]]; then
        vbox_remove_medium ${DISK_IMAGE_1} 1
    fi
    if [[ "${DISK_IMAGE_2}" != "" ]]; then
        vbox_remove_medium ${DISK_IMAGE_2} 2
    fi
    if [[ "${DISK_IMAGE_3}" != "" ]]; then
        vbox_remove_medium ${DISK_IMAGE_3} 3
    fi
    if [[ "${DISK_IMAGE_4}" != "" ]]; then
        vbox_remove_medium ${DISK_IMAGE_4} 4
    fi
}
###############################################################################



###############################################################################
# vbox_attach_medium (disk_img, port_num, disk_type)
###################
vbox_attach_medium () {
  local disk_img=$1
  local port_num=$2
  local disk_type=$3
  echo "Attaching disk ${port_num}..."
  VBoxManage modifyhd "${disk_img}" --type ${disk_type}
  vboxmanage storageattach "${VM_NAME}" --storagectl "${STORAGE_CONTROLLER_NAME}" --port ${port_num} --device 0 --type hdd --medium "${disk_img}"
}



###############################################################################
# vbox_attach_media
###################
vbox_attach_media () {
    if [[ "${DISK_IMAGE_1}" != "" ]]; then
        vbox_attach_medium "${DISK_IMAGE_1}" 1 ${STORAGE_TYPE}
    fi
    if [[ "${DISK_IMAGE_2}" != "" ]]; then
        vbox_attach_medium "${DISK_IMAGE_2}" 2 ${STORAGE_TYPE}
    fi
    if [[ "${DISK_IMAGE_3}" != "" ]]; then
        vbox_attach_medium "${DISK_IMAGE_3}" 3 ${STORAGE_TYPE}
    fi
    if [[ "${DISK_IMAGE_4}" != "" ]]; then
        vbox_attach_medium "${DISK_IMAGE_4}" 4 ${STORAGE_TYPE}
    fi
}
###############################################################################



###############################################################################
# vbox_set_hd_autoreset (hd_autoreset)
###################
vbox_set_hd_autoreset () {
    local hd_autoreset=$1
    # iterate on all attached disks (they should be all differencing disks)
    vboxmanage showvminfo "${VM_NAME}" | grep -m1 -Po ".*\.vdi.*\(UUID: \K(.*)" | while read -r line ; do
        # remove last ')'
        TMP_DIFF=${line::-1}
        if [ "${TMP_DIFF}" != "" ]; then
            echo "Setting differential disk ${TMP_DIFF}: autoreset=${hd_autoreset}"
            VBoxManage modifyhd ${TMP_DIFF} --autoreset ${hd_autoreset}
        fi
    done
}



###############################################################################
# vm_start_init
###############
vm_start_init () {
    # create temporary folder
    if [ ! -d $USER_TMP_DIR ]; then
        mkdir $USER_TMP_DIR
    fi

    # remove files older than 12 hours
    #find ${USER_TMP_DIR} -name "*" -type f -mmin +720 -delete

    # copy diff file (if needed)
    if [ "${DIFF_DISK_FILE}" != "" ]; then
        echo -n "Setting up differential disk... "
        cp "${TEMPLATE_DIR}/${DIFF_DISK_FILE}" "${USER_TMP_DIR}"
        chmod 755 "${USER_TMP_DIR}/${DIFF_DISK_FILE}"
        echo "OK"
    fi

    echo -n "Setting up media folder... "
    # create local media folder and symlink if not existing
    if [ ! -d "${SF_MEDIA_TARGET}" ]; then
        mkdir -p "${SF_MEDIA_TARGET}"
    fi
    if [ ! -e "${SF_MEDIA_TARGET}/${USER}" ]; then
        if [ ! -h "${SF_MEDIA_TARGET}/${USER}" ]; then
            ln -s "${SYSTEM_MEDIA_FOLDER}" "${SF_MEDIA_TARGET}/${USER}"
        fi
    fi
    echo "OK"

    # create network interface
    echo -n "Removing network interface: "
    VBoxManage hostonlyif remove vboxnet0
    echo -n "Creating network interface: "
    VBoxManage hostonlyif create
    # >/dev/null 2>&1

    # restore snapshot if needed
    if [ "${SNAPSHOT_NAME}" != "" ]; then
        VBoxManage snapshot "${VM_NAME}" restore "${SNAPSHOT_NAME}"
    fi

    if [ "${HD_AUTORESET}" == "off" ]; then
        vbox_set_hd_autoreset ${HD_AUTORESET}
    else
        vbox_remove_media
        vbox_attach_media
    fi
}
###############################################################################



###############################################################################
# discard_state
###############
vm_discard_state() {
    echo -n "Discard state... "
    VBoxManage discardstate "${VM_NAME}"
    echo "OK."
}
###############################################################################



###############################################################################
# vm_start_run
##############
vm_start_run() {
    # --fullscreen?
    if [[ ${FULLSCREEN} == 1 ]]; then
        # VBoxManage has no option for fullscreen mode, use VBoxSDL (no menu available in fullscreen)
        # VBoxSDL --startvm "${VM_NAME}" --fullscreen
        # options below could be useful in setting the fullscreen resolution, when known
        # --fullscreenresize --fixedmode 1152 864 32
        #
        # the following command can also be used to start the VM in fullscreen (GUI mode)
        /usr/bin/VirtualBox --startvm "${VM_NAME}" --fullscreen
    else
        VBoxManage startvm "${VM_NAME}"
    fi
}
###############################################################################


# print title
title


###############################################################################
# Parse arguments
#################

[[ "$#" -ge 1 ]] || usage "${ERROR}ERROR: one argument required ($# provided).${NORMAL}"

VM_ID=""
DEBUG=0
FULLSCREEN_CL=-1
FULLSCREEN=0
NO_RUN=0
NO_INIT=0
DISCARD_STATE=0
HD_AUTORESET=on

while [ "$1" != "" ]; do
    PARAM=`echo $1 | awk -F= '{print $1}'`
    VALUE=`echo $1 | awk -F= '{print $2}'`
    case ${PARAM} in
        -h | --help)
            usage ""
            exit 0
            ;;
        -g | --gui)
            FULLSCREEN_CL=0
            shift
            ;;
        -f | --fullscreen)
            FULLSCREEN_CL=1
            shift
            ;;
        -i |--no-init)
            NO_INIT=1
            shift
            ;;
        -r |--no-run)
            NO_RUN=1
            shift
            ;;
        -s | --discard-state)
            DISCARD_STATE=1
            shift
            ;;
        -d | --debug)
            DEBUG=1
            shift
            ;;
	      -a | --hd-autoreset)
	          HD_AUTORESET=$VALUE
	          shift
	          ;;
        *)
            if [[ "${VM_ID}" == "" ]]; then
                VM_ID=${PARAM}
                shift
            else
                usage "${ERROR}ERROR: unknown argument ${BOLD}${PARAM}.${NORMAL}"
                exit 1
            fi
            ;;
    esac
done
###############################################################################

# print debug info if needed
debug

# import VM settings by id or name
vm_settings=`get_vm_settings "${VM_ID}"`
if [ "$vm_settings" == "" ]; then
    usage "${ERROR}ERROR: wrong vm_id.${NORMAL}"
fi

echo "Applying settings $vm_settings"
echo

source "$vm_settings"

# override VM fullscreen setting if set on command line
if [[ ${FULLSCREEN_CL} != -1 ]]; then
    FULLSCREEN=${FULLSCREEN_CL}
fi

# check if VM exists
VBoxManage showvminfo "${VM_NAME}" &> /dev/null
[ "$?" -eq 0 ] || die "${ERROR}ERROR: VM not configured. Run ${BOLD}'vm-setup ${VM_ID}'${NORMAL}${ERROR} and try again.${NORMAL}"

# check if snapstot folder is the one defined by us
current_snapshot_folder=`VBoxManage showvminfo "${VM_NAME}" | grep -m1 "Snapshot folder" | awk '{print $3}'`

if [ "$current_snapshot_folder" != "${USER_TMP_DIR}" ]; then
    # non si può cambiare al volo se ci sono degli snapshot...
    #VBoxManage modifyvm "${VM_NAME}" --snapshotfolder "${USER_TMP_DIR}"
    echo "Configurazione obsoleta. Per favore riesegui:"
    echo "${SRC_DIR}/vm-setup ${VM_ID}"
    exit 1
fi

# --no-init?
if [[ ${NO_INIT} == 0 ]]; then
    vm_start_init
fi

# --discard-state?
if [[ ${DISCARD_STATE} == 1 ]]; then
    vm_discard_state
fi

# --no-run?
if [[ ${NO_RUN} == 0 ]]; then
    vm_start_run
fi

exit 0