#!/bin/bash

WRAPPER="qemu-wrapper.sh"

source /usr/share/qemu-integration/functions.sh

function echoParams {
	local I=1 L=$#
	while (( I <= L ))
	do
		(( I < L )) && printf '%s ' "${!I}" || printf '%s\n' "${!I}"
		I=$(( I+1 ))
	done
}

function dirname {
	if [[ $1 =~ ^(.+)/[^/]+ ]]
	then
		echoParams "${BASH_REMATCH[1]}"
	elif [[ $1 =~ ^/[^/]+$ ]]
	then
		echoParams "/"
	elif [[ $1 =~ ^[^/]+$ ]]
	then
		echoParams "."
	fi
}

function commonPathPrefix {
	if [ "$1" != "$2" ]
	then
		if (( ${#1} < ${#2} ))
		then
			commonPathPrefix "$1" "$(dirname "$2")"
		else
			commonPathPrefix "$2" "$(dirname "$1")"
		fi
	else
		echoParams "$1"
	fi
}

function qcygpath {
	cygpath -m -l "$1"
}

function qrealpath {
	local FILE="$(realpath "$1")"
	if (( ${#FILE} >= ${#CYGUROOT} )) &&
		[ "${FILE:0:${#CYGUROOT}}" == "${CYGUROOT}" ]
	then
		echoParams "${FILE:${#CYGUROOT}}"
	else
		echoParams "$FILE"
	fi
}

function translateExistingPath {
	local PARAM="$1"
	debugLog "Existing path to translate: '$PARAM'"
	if [[ $PARAM =~ ^/ ]]
	then
		traceLog "Absolute path"
		if [[ ! $PARAM =~ ^/(dev|proc)(/|$) ]]
		then
			debugLog "Regular path, use cygpath"
			qcygpath "$PARAM"
		else
			debugLog "Won't translate special absolute path"
			echoParams "$PARAM"
		fi
	else
		traceLog "Relative path"
		local PARAMPATH="$(qrealpath "$PARAM")"
		local WORKINGDIR="$(qrealpath .)"
		local COMMONDIR="$(commonPathPrefix "$WORKINGDIR" "$PARAMPATH")"
		debugLog "Paths by realpath: commondir:'$COMMONDIR' - workingdir:'$WORKINGDIR' - path:'$PARAMPATH'"
		# relInHomeOnly: if [[ ! $COMMONDIR =~ ^$HOME ]]
		if [ "$COMMONDIR" == "/" ] && [[ $PARAMPATH =~ ^/cygdrive ]]
		then
			#debugLog "Path is outside of ~/, use cygpath"
			debugLog "Path is outside of relative sight, use cygpath"
			qcygpath "$PARAM"
		else
			debugLog "Path is file/dir in working dir or in super of working dir, turn relative"
			local WORKINGDIR_TO_COMMONDIR
			while [ "$WORKINGDIR" != "$COMMONDIR" ]
			do
				WORKINGDIR="$(dirname $WORKINGDIR)"
				WORKINGDIR_TO_COMMONDIR="../$WORKINGDIR_TO_COMMONDIR"
			done
			traceLog "WORKINGDIR_TO_COMMONDIR: '$WORKINGDIR_TO_COMMONDIR'"
			local RELPATH_START=${#COMMONDIR}
			# RELPATH doesn't start with /, add 1 to jump over / after COMMONDIR prefix
			[ "$COMMONDIR" != "/" ] && RELPATH_START=$(( RELPATH_START+1 ))
			local RELPATH_FROM_COMMONDIR="${PARAMPATH:RELPATH_START}"
			traceLog "RELPATH_FROM_COMMONDIR: '$RELPATH_FROM_COMMONDIR'"
			local RELPATH="${WORKINGDIR_TO_COMMONDIR}${RELPATH_FROM_COMMONDIR}"
			traceLog "RELPATH: '$RELPATH'"
			echoParams "$RELPATH"
		fi
	fi
}

function translatePotentialPath {
	local PARAM="$1"
	traceLog "Potential path to translate: '$PARAM'"
	if [[ $PARAM =~ ^.: ]] || [[ $PARAM =~ \\ ]]
	then
		traceLog "Looks like Windows path, no translation"
		echoParams "$PARAM"
	elif [ -e "$PARAM" ]
	then
		debugLog "Is existing file/dir, go on..."
		translateExistingPath "$PARAM"
		debugLog
	elif [ ! -L "$PARAM" ] && [[ $PARAM =~ /.+ ]]
	then
		traceLog "Is no dangling link and contains a slash..."
		local DPARAM="$(dirname "$PARAM")"
		local BPARAM="$(basename "$PARAM")"
		if [ -d "$DPARAM" ]
		then
			debugLog "Path has existing super dir '$DPARAM', go on ..."
			local ODPARAM="$DPARAM"
			DPARAM="$(translateExistingPath "$DPARAM")"
			if [ "$ODPARAM" != "$DPARAM" ]
			then
				traceLog "Translated to '$DPARAM/$BPARAM'"
				echoParams "$DPARAM/$BPARAM"
			else
				traceLog "Not modified on translation"
				echoParams "$PARAM"
			fi
			debugLog
		else
			traceLog "No translation"
			echoParams "$PARAM"
		fi
	else
		traceLog "No translation. Param: '$PARAM'"
		echoParams "$PARAM"
	fi
}

function translateParam {
	local PARAM="$1"
	traceLog "Analyse param for translation: '$PARAM'"
	if [[ $PARAM =~ = ]]
	then
		traceLog "Param contains '=', assuming comma-separated key-value list"
		local REST="$PARAM" TRANS=""
		while [[ $REST =~ ^([^,]+),?(.*) ]]
		do
			local TOKEN="${BASH_REMATCH[1]}" REST="${BASH_REMATCH[2]}"
			if [[ $TOKEN =~ ^(logfile|file|filename|file.filename|path|splash|script|x509-[^=]+)=(.+)$ ]]
			then
				traceLog "Token: '$TOKEN'"
				local TOKEN_NAME="${BASH_REMATCH[1]}" TOKEN_OVALUE="${BASH_REMATCH[2]}"
				local TOKEN_TVALUE="$(translatePotentialPath "$TOKEN_OVALUE")"
				TOKEN="${TOKEN_NAME}=${TOKEN_TVALUE}"
			fi
			TRANS="${TRANS}${TOKEN},"
		done
		echoParams "${TRANS::-1}"
	else
		traceLog "Assuming plain param"
		traceLog "Param before: '$PARAM'"
		local TRANS="$(translatePotentialPath "$PARAM")"
		traceLog "Param after:  '$TRANS'"
		echoParams "$TRANS"
	fi
	traceLog
}

function printTranslated {
	infoLog
	infoLog "/usr/share/qemu-integration/$WRAPPER applied its path translation:"
	infoLog "--------------------------------------------------------------------------------"
	local PARAM LINE INDENT PREVH CURRH
	for PARAM in "${@}"
	do
		[ "${PARAM:0:1}" == '-' ] && CURRH="-" || CURRH=""

		# Newline before "-"-param and between 2 non-"-"-params
		if [ -n "$LINE" ] && ( [ -n "$CURRH" ] || [ -z "$PREVH" ] )
		then
			infoLog "$LINE \\"
			LINE=""
		fi

		# Add quots to param, if param is empty or contains blanks
		if [ "$PARAM" == "" ] || [[ $PARAM =~ ' ' ]]
		then
			PARAM="'$PARAM'"
		fi

		LINE="${LINE}${INDENT}${PARAM}"

		INDENT=" "
		PREVH="$CURRH"
	done
	infoLog "$LINE"
	infoLog "--------------------------------------------------------------------------------"
	infoLog
}


# Try to determine and translate unix to windows paths 
declare -a QPARAMS=()
CYGWROOT="$( qcygpath / )"
CYGUROOT="$( echoParams "$CYGWROOT" | sed "s%^\(.\):%/cygdrive/\L\1%" )"
TAPPLIED="false"
for QPARAM in "$@"
do
	if [ -z "$DISABLE_PATH_TRANSLATION" ]
	then
		traceLog "Param before: '$QPARAM'"
		TPARAM="$(translateParam "$QPARAM")"
		traceLog "Param after:  '$TPARAM'"
		if [ "$TPARAM" != "$QPARAM" ]
		then
			TAPPLIED="true"
		fi
		QPARAM="$TPARAM"
	fi
	QPARAMS+=("$QPARAM")
done
if [ -z "$DISABLE_PATH_TRANSLATION" ] && $TAPPLIED
then
	printTranslated "$(basename "$0")" "${QPARAMS[@]}"
fi

# Define native windows title bar if not defined otherwise
if [ -z "$GTK_CSD"]
then
	export GTK_CSD=0
fi

determineConfig

# Add mingw/bin and configured extension to PATH
export PATH="$QEMU_BIN_DIR:$WRAPPER_ENV_PATH_EXTENSION:$PATH"

# Determine binary to execute
QBINARY="$QEMU_BIN_DIR/$(basename $0)"
debugLog "$QBINARY"
if [ ! -f "$QBINARY" ]
then
	# Suffix .exe was not used on invocation
	QBINARY="$QBINARY.exe"
	debugLog "$QBINARY"
fi
qexec "$QBINARY" "${QPARAMS[@]}"
