#!/bin/sh

#  The logging routine
Log() {
	logger -p install.info -t 'Parallels Installer' "$@"
}

# Retouch desktop bundles in order to flush cache
Log "Retouch desktop bundles"
touch '/Applications/Parallels Desktop.app' '/Applications/Parallels Desktop.app/Contents/PlugIns/PD_Starter.app'

####################################################################################################
# Constants
####################################################################################################
dock_plist_edit="/Library/Parallels/Uninstaller/Parallels Hypervisor/DockPlistEdit.app/Contents/MacOS/DockPlistEdit"
APP_MENU_DIR="Library/Caches/Parallels/Applications Menus"
need_reboot_dock='no'

# 'Add To Lauchpad' feature support
launchpad_support='no'
####################################################################################################

# Update PD icon on Dock if needs
# Return 0 if Dock should be reboot; 1 if no changes are performed in Dock
fix_dock_icon() {
	ls /var/db/Parallels/Stats 2>/dev/null | grep -qs 'ParallelsDesktop.6.0'
	if [ $? -eq 0 ]; then
		Log "Found PD6 installed"
		return 1
	fi

	ret=1
	pd25="Parallels.app"
	pd3="Parallels Desktop.app"
	pd_cur="/Applications/Parallels Desktop.app"
	
	for i in `ls -1 /Users/ | grep -ivw Shared | grep -ve '^\\.'`; do
		id $i > /dev/null 2>&1
		if [ $? -ne 0 ]; then
			Log "No user $i on the system"
			continue
		fi
		sudo -u $i defaults read com.apple.dock persistent-apps | grep "$pd_cur"
		if [ $? -eq 0 ]; then
			Log "Found PD4 or PD5 icon in the Dock for user $i"
			return 0
		fi
		for old_pd in "$pd25" "$pd3"; do
			icon=$(sudo -u $i defaults read com.apple.dock persistent-apps 2>/dev/null | grep "$old_pd")
			if [ -z "$icon" ]; then
				continue
			fi
			Log "Found PD2.5 or PD3 icon in the Dock for user $i"
			icon_to_update=$(echo "$icon" | sed 's/.*=\ \"//' | sed 's/";//')
			sudo -u $i "$dock_plist_edit" -action update-path -section persistent-apps -path "$icon_to_update" -newpath "$pd_cur"
			if [ $? -eq 0 ]; then
				ret=0
			fi
		done
	done
	return $ret
}

# Check that PD with version greater than input parameters has been installed on the system
# $1 major version
# $2 build number
# if empty $1 - return false; if empty $2 - return result of checking only $1
check_pd_ver_greater_than() {
	ver=$1
	test -z "$ver" && return 1
	for stat_file in $(ls /var/db/Parallels/Stats); do
		num=$(echo $stat_file | grep 'ParallelsDesktop' | cut -d . -f 2)
		test $num -gt $ver
		if [ $? -eq 0 ]; then
			build_number=$2
			test -z $build_number && return 0
			bnum=$(echo $stat_file | grep 'ParallelsDesktop' | cut -d . -f 4)
			test $bnum -gt $build_number && return 0
		fi
	done
	return 1
}

fix_bundle_id() {
	PF="$1/Contents/Info.plist"
	Log "fix_bundle_id for Info.plist by path $PF"
	ESC_PATH=$(echo "$PF" | sed -e 's/\"/\\\"/g')

	export PYTHONIOENCODING=UTF-8
	BUNDLE_NAME="$(python -c "import plistlib as p; print p.readPlist(\"$ESC_PATH\")[\"CFBundleName\"]")"
	CFBUNDLE_ID="$(python -c "import plistlib as p; print p.readPlist(\"$ESC_PATH\")[\"CFBundleIdentifier\"]")"

	echo "$BUNDLE_NAME" | iconv -f utf-8 -t ascii > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		Log "Non-ASCII symbols in CFBundleName: $BUNDLE_NAME"
		MD5_BUNDLE_NAME="$(md5 -qs "$BUNDLE_NAME")"
		FIX_BUNDLE_ID="${CFBUNDLE_ID/$BUNDLE_NAME/$MD5_BUNDLE_NAME}"
		python -c "import plistlib as p; f=p.readPlist(\"$ESC_PATH\"); f[\"CFBundleIdentifier\"]=\"$FIX_BUNDLE_ID\"; p.writePlist(f, \"$ESC_PATH\")"
	fi
}

fix_sharedapp_bundle() {
	BUNDLE_ID="com.parallels.winapp."
	LSREG="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
	NEW_STAB="/Applications/Parallels Desktop.app/Contents/Resources/WinAppHelper"
	IFS=$'\n'
	for i in `ls -1 /Users/ | grep -ivw Shared | grep -ve '^\\.'`; do
		for app in $(sudo -u $i "$LSREG" -dump | grep -B3 "$BUNDLE_ID" | sed -n "s,^.*path:.*\(/Users/$i\),\1,gp;s,^.*path:.*\(/Applications\),\1,gp")
			do
			if [ -d "$app" ]; then
				Log "Substitute WinAppHelper for $app"
				cp -pPRf "$NEW_STAB" "$app/Contents/MacOS/WinAppHelper"
				fix_bundle_id "$app"
			fi
		done
	done
	unset $IFS
}

# Workaround of Apple bug with ID: 9672474 and title:
# '10.6.8 Degradation: Finder crashes / deadlock with icons larger than 128x128'
reset_app_menu_icns() {
	Log "Fixing application menu icons for user $1"
	IFS=$'\n'
	for app_dir in $(find "/Users/$1/$APP_MENU_DIR" -maxdepth 1 -type d -name '* Applications Menu.localized'); do
		Log "Found applications menu icons directory $app_dir"
		for file in $(find "$app_dir" -type f); do
			"$PRL_MAKE_ICNS" --lsicon "$file" | grep -q 'Image count: 0'
			if [ $? -eq 0 ]; then
				"$PRL_MAKE_ICNS" --reseticon "$file"
				touch -t 197001010000 "$file"
				need_reboot_dock='yes'
			fi
		done
	done
	unset $IFS
}

# Workaround for Launchpad in Lion(Mac OS 10.7)
# Parallels Shared Applications should not appear in LaunchPad
fix_shared_app() {
	Log "Fixing shared applications for user $1"
	USR_DIR="/Users/$1"
	OLD_APP_DIR="$USR_DIR/Applications"

	DIRS=$(find "$OLD_APP_DIR" -maxdepth 1 -type d -name '{*} Applications.localized')
	[ -z "$DIRS" ] && return

	NEW_APP_DIR="$USR_DIR/Applications (Parallels)"

	sudo -u $1 mkdir -p "$NEW_APP_DIR"
	IFS=$'\n'
	for appdir in $DIRS; do
		Log "Processing applications directory: $appdir"

		dname="$(basename $appdir)"
		new_appdir="$NEW_APP_DIR/$dname"

		if [ "x$launchpad_support" == "xyes" ]; then
			mkdir -p "$new_appdir"
			for winapp in $(find "$appdir" -type d -maxdepth 1 -name '*.app'); do
				# We can not use 'move' here because apps are stayed in Launchpad
				# in this case. Launchpad works so.
				cp -pPRf "$winapp" "$new_appdir"
				rm -rf "$winapp"
			done
		else
			# We can not use 'move' here because apps are stayed in Launchpad
			# in this case. Launchpad works so.
			cp -pPRf "$appdir" "$NEW_APP_DIR"
			rm -rf "$appdir"
		fi

		dock_items="$(sudo -u $1 defaults read com.apple.dock persistent-apps 2>/dev/null)"
		echo "$dock_items" | grep -q "$appdir"
		if [ $? -eq 0 ]; then
			Log "Fix Dock icons for applications of VM $appdir"
			for app in $(find "$new_appdir" -type d -maxdepth 1); do
				old_path="$appdir/$(basename $app)"
				echo "$dock_items" | grep -q "$old_path" &&
					sudo -u $1 "$dock_plist_edit" -action update-path -section persistent-apps -path "$old_path" -newpath "$app" &&
					need_reboot_dock='yes'
			done
		fi

		shapp_dir="$USR_DIR/$APP_MENU_DIR/${dname/Applications/Applications Menu}"
		if [ -d "$shapp_dir" ]; then
			Log "Found shared applications links directory $shapp_dir"
			for file in $(find "$shapp_dir" -type f); do
				Log "Relocating proxies in $file"
				"$PRL_SHAPP_UTIL" --proxy-relocate "$file" "$appdir" "$NEW_APP_DIR/$dname"
			done
		fi

	done
	unset IFS

	# Tell Dock that we made changes in ~/Applications directory
	# to get rid of windows shared applications in LaunchPad
	touch "$OLD_APP_DIR"

	APP_ICN="/Applications/Parallels Desktop.app/Contents/Resources/AppsMenuFolderIcon.icns"
	"$PRL_MAKE_ICNS" --seticns "$NEW_APP_DIR" "$APP_ICN"
}

processing_icns() {
	RESET_ICNS=yes
	RESRC="${0%/*}/../../../../Resources"

	PRL_MAKE_ICNS="$RESRC/prl_make_icns"
	if [ ! -x "$PRL_MAKE_ICNS" ]; then
		Log "prl_make_icns utility is not executable by path '$PRL_MAKE_ICNS'"
		RESET_ICNS=no
	fi

	PRL_SHAPP_UTIL="$RESRC/prl_shapplink_util"
	[ -x "$PRL_SHAPP_UTIL" ] || Log "prl_make_icns utility is not executable by path '$PRL_SHAPP_UTIL'"

	for i in `ls -1 /Users/ | grep -ivw Shared | grep -ve '^\\.'`; do
		relocate_app_menu_dir $i
		[ "x$RESET_ICNS" == "xyes" ] && reset_app_menu_icns $i

		# Kludge for update from PD7-GA: PD 7.0.14920 build doesn't transfer
		# stuff from "~/Applications" to "~/Applications (Parallels)".
		# There is possibility to create launchpad aliases in this build
		# so needs to skip them while transferring stuff from "~/Applications"
		check_pd_ver_greater_than 6 && launchpad_support='yes'

		check_pd_ver_greater_than 7 14920 || fix_shared_app $i
	done
}

relocate_app_menu_dir() {
	NEW_APP_MENU_DEST="Library/Parallels/"
	mkdir -p "$NEW_APP_MENU_DEST"
	Log "Relocate App Menu dir from '~/$APP_MENU_DIR' to '~/$NEW_APP_MENU_DEST'"
	# Move all stuff from old APP_MENU_DIR
	mv -f "/Users/$1/$APP_MENU_DIR" "/Users/$1/$NEW_APP_MENU_DEST"
	# Fix permissions on moved directory
	chown "$i" "/Users/$1/$NEW_APP_MENU_DEST"
	# Assign new value to global variable APP_MENU_DIR
	APP_MENU_DIR="$NEW_APP_MENU_DEST/$(basename $APP_MENU_DIR)"
}

####################################################################################################
# Perform actions
####################################################################################################
fix_sharedapp_bundle
fix_dock_icon && need_reboot_dock='yes'
processing_icns
# Reboot dock if needed
if [ "x$need_reboot_dock" == "xyes"  ]; then
	Log "Rebooting Dock"
	killall -HUP Dock
fi	

# To change icons on Desktop and in Documents we create new alias, remove old aliases and copy the new one
orig_alias_file_path="/Applications/Parallels Desktop.app/Contents/Resources"
orig_alias_file="${orig_alias_file_path}/Parallels Desktop"
if [ -d "/Applications/Parallels Desktop.app" ]; then 
/usr/bin/osascript >/dev/null << EOT
tell application "Finder"
set macSrcPath to "/Applications/Parallels Desktop.app" as POSIX file
set macDestPath to "$orig_alias_file_path" as POSIX file
make new alias to file macSrcPath at folder macDestPath
end tell	 
EOT
fi

for i in `ls -1 /Users/ | grep -ivw Shared | grep -ve '^\\.'`; do
	for loc in Desktop Documents; do
		# remove old parallels app on desktop or documents
		if [ -d "/Users/$i/$loc/Parallels Desktop.app" ]; then
			rm -rf "/Users/$i/$loc/Parallels Desktop.app"
			cp "$orig_alias_file" "/Users/$i/$loc/"
		fi
		# remove old alias on desktop or documents
		IFS='
		'
		for alias_file in $(find /Users/$i/$loc/ -maxdepth 1 -type f -name 'Parallels Desktop*'); do
			strings "$alias_file/rsrc" 2>/dev/null | grep -qs alis
			if [ $? -eq 0 ]; then
				rm -f "$alias_file"
				cp "$orig_alias_file" "$alias_file"
			fi
		done
		unset $IFS
	done
done
rm -f "$orig_alias_file"

# Warm up client app
ParallelsClient="/Applications/Parallels Desktop.app/Contents/PlugIns/PD_Starter.app/Contents/MacOS/prl_client_app"
if [ -e "${ParallelsClient}" ]; then
	Log "Worming up client application"
	sudo -u $USER "${ParallelsClient}" --mode cache_install
fi

# Copy receipts to Parallels Receipts directory
SWD=`cd "${0%/*}"; pwd`
. "${SWD}"/receipt.sh

# Just to finish installation with good mood
true
