#!/bin/bash
#
# STP
#
# ReleaseDate: 20250116
# Created by Cartor on 2019-06-13.
# Copyright 2019 Splashtop Inc. All rights reserved.
#

# set -e

# for debug shell script
# set -x

#----------------common function start-----------------------#



function exceCMD() {
    local cmd="${1}"
    echo "${cmd}" | sh
    #echo "${cmd}"
    #echo "${cmd}" >> ~/uninstaller.log
}

function tarCopyFile() {
    local _DIR=$(pwd)

    local SOURCE="$(dirname "$1")"
    local DESTINATION="$2"
    local FILE="$(basename "$1")"

    echo "Copying file to ${DESTINATION}"
    cd "${SOURCE}"
    sudo tar cf - "${FILE}" | (cd "${DESTINATION}"; sudo tar xfp -)
    cd "${_DIR}"
}

function vercomp () {
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

function plist_WriteOption() {
    local FILENAME="${1}"
    local KEY="${2}"
    local VALUE="${3}"
    local TYPE="${4}"

    /usr/libexec/PlistBuddy -c "Add :${KEY} ${TYPE} \"${VALUE}\"" "${FILENAME}" 2>/dev/null || /usr/libexec/PlistBuddy -c "Set :${KEY} \"${VALUE}\"" "${FILENAME}"
}

function setDeployCode() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"
    local DCode="${3}"

    local keys=("DeployCode" "DeployTeamNameCache" "DeployTeamOwnerCache" "LastDeployCode" "TeamCode" "TeamCodeInUse")
    local values=("${DCode}" "" "" "" "" "")
    local types=("string" "string" "string" "string" "string" "string")

    local n=${#keys[@]}
    for (( i=0; i<n; i++ ))
    do
        local key=${keys[i]}
        local value=${values[i]}
        local type=${types[i]}

        plist_WriteOption "${FILENAME}" "${STREAMER}:${key}" "${value}" "${type}"
    done
}

function setShowDeployLoginWarning() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    local ShowDeployLoginWarning="true"
    if [ "${3// }" == "0" ]; then
        ShowDeployLoginWarning="false"
    fi
    plist_WriteOption "${FILENAME}" "${STREAMER}:ShowDeployLoginWarning" "${ShowDeployLoginWarning}" "bool"
}

function setComputerName() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"
    local COMPUTER_NAME="${3}"

    plist_WriteOption "${FILENAME}" "${STREAMER}:HostName" "${COMPUTER_NAME}" "string"
}

function setPermissionProtectionOption() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"
    local REQUEST_PERMISSION="${3}"
    local EnablePermissionProtection=""

    if [ -z "${REQUEST_PERMISSION// }" ]; then
        return
    fi

    local EnablePermissionProtection="${REQUEST_PERMISSION// }"
    if [ ! -z "${EnablePermissionProtection// }" ]; then
        plist_WriteOption "${FILENAME}" "${STREAMER}:EnablePermissionProtection" "${EnablePermissionProtection}" "int"
    fi    
}

function setSecurityOption() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"
    local SECURITY_OPTION="${3}"

    local EnableSecurityCodeProtection=""
    local EnableOSCredential=""

    if [ "$SECURITY_OPTION" == "0" ]; then
        EnableSecurityCodeProtection="false"
        EnableOSCredential="false"
    fi

    if [ "$SECURITY_OPTION" == "1" ]; then
        EnableSecurityCodeProtection="true"
        EnableOSCredential="false"
    fi

    if [ "$SECURITY_OPTION" == "2" ]; then
        EnableSecurityCodeProtection="false"
        EnableOSCredential="true"
    fi
    
    if [ ! -z "${EnableSecurityCodeProtection// }" ]; then
        plist_WriteOption "${FILENAME}" "${STREAMER}:EnableSecurityCodeProtection" "${EnableSecurityCodeProtection}" "bool"
    fi

    if [ ! -z "${EnableOSCredential// }" ]; then
        plist_WriteOption "${FILENAME}" "${STREAMER}:EnableOSCredential" "${EnableOSCredential}" "bool"
    fi    
}

function setInitSecurityCode() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:init_security_code" "${3}" "string"
}

function setLegacyConnectionLoopbackOnly() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:LegacyConnectionLoopbackOnly" "true" "bool"
}

function setHideTrayIcon() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:HideTrayIcon" "true" "bool"
}

function setDefaultClientDeviceName() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:DefaultClientDeviceName" "${3}" "string"
}

function setShowStreamerUI() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    local keys=("FirstTimeClose" "FirstTimeLogin" "PermissionAlert")
    local values=("false" "false" "false")
    local types=("bool" "bool" "bool")

    local n=${#keys[@]}
    for (( i=0; i<n; i++ ))
    do
        local key=${keys[i]}
        local value=${values[i]}
        local type=${types[i]}

        plist_WriteOption "${FILENAME}" "${STREAMER}:${key}" "${value}" "${type}"
    done
}

function setEnableLanConnection() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:EnableLanConnection" "false" "bool"
}

function setBackendAddress() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:BackendAddress" "${3}" "string"
}

function setBackendAccount() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:SplashtopAccount" "${3}" "string"
}

function setBackendPassword() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:SplashtopPassword" "${3}" "string"
}

function setInfraGenForce() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:InfraGenForce" "${3}" "int"
}

function setForceUUID32() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:ForceUUID32" "${3}" "bool"
}

function setIgnoreUntrustedCert() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    plist_WriteOption "${FILENAME}" "${STREAMER}:IgnoreUntrustedCert" "${3}" "bool"
}

function setCommonDict() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    /usr/libexec/PlistBuddy -c "Add :Common dict" "${FILENAME}" 2>/dev/null || true
    /usr/libexec/PlistBuddy -c "Add :Common:HidePreferenceDomainSelection bool YES" "${FILENAME}" 2>/dev/null || /usr/libexec/PlistBuddy -c "Set :Common:HidePreferenceDomainSelection YES" "${FILENAME}"
    /usr/libexec/PlistBuddy -c "Add :Common:EulaAccepted bool YES" "${FILENAME}" 2>/dev/null || /usr/libexec/PlistBuddy -c "Set :Common:EulaAccepted YES" "${FILENAME}"

    if [ "$STREAMER_TYPE" != "0" ]; then
        /usr/libexec/PlistBuddy -c "Add :Common:StreamerType integer 1" "${FILENAME}" 2>/dev/null || /usr/libexec/PlistBuddy -c "Set :Common:StreamerType 1" "${FILENAME}"
    fi

    if [ ! -z "${STREAMER}" ]; then
        /usr/libexec/PlistBuddy -c "Add :"${STREAMER}" dict" "${FILENAME}" 2>/dev/null || true
    fi
}

function setStreamerTypeDict() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    local keys=()
    local values=()
    local types=()

    if [ "$STREAMER_TYPE" == "0" ]; then
        keys+=("ShowDeployMode" "SplashtopAccount")
        values+=("true" "")
        types+=("bool" "string")
    fi

    if [ "$STREAMER_TYPE" == "1" ]; then
        keys+=("ShowDeployMode" "SplashtopAccount")
        values+=("true" "")
        types+=("bool" "string")
    fi

    if [ "$STREAMER_TYPE" == "2" ]; then
        keys+=("FirstTimeLogin" "BackendConnected" "ClientCertificateData" "CustomizeTeamCode" "FirstTimeLogin" "IsNewUUIDScheme" "RelayConnected")
        values+=("false" "true" "" "" "" "" "true")
        types+=("bool" "bool" "data" "string" "string" "string" "bool")
    fi

    local n=${#keys[@]}
    for (( i=0; i<n; i++ ))
    do
        local key=${keys[i]}
        local value=${values[i]}
        local type=${types[i]}

        plist_WriteOption "${FILENAME}" "${STREAMER}:${key}" "${value}" "${type}"
    done
}

function setPlistByStreamerType() {
    local FILENAME="${1}"
    local STREAMER_TYPE="${2}"
    local STREAMER="$(streamerTypeString "${STREAMER_TYPE}")"

    /usr/libexec/PlistBuddy -c "Add :UniversalSetting bool YES" "${FILENAME}" 2>/dev/null || /usr/libexec/PlistBuddy -c "Set :UniversalSetting YES" "${FILENAME}"

    setCommonDict "${FILENAME}" "${STREAMER_TYPE// }"
    setStreamerTypeDict "${FILENAME}" "${STREAMER_TYPE// }"
}

function streamerTypeString() {
    local STREAMER_TYPE="${1}"
    local STREAMER=""

    if [ "$STREAMER_TYPE" == "0" ]; then
        STREAMER="STP"
    fi

    if [ "$STREAMER_TYPE" == "1" ]; then
        STREAMER="STB"
    fi

    if [ "$STREAMER_TYPE" == "2" ]; then
        STREAMER="STE"
    fi

    echo "${STREAMER}"
}

function restartApp() {
    local APPNAME="${1}"
    ps axc -Ouser | grep -i "${APPNAME}" | awk '{print $1}' | xargs -o kill -9
    sleep 2
    open -b `osascript -e "id of app \"${APPNAME}\""`
}

function restartCoreAudioService() {
    sleep 1; sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod >/dev/null 2>&1 || sudo kill `ps -ax | grep 'coreaudio[a-z]' | grep 'sbin' | awk '{print $1}'`; sleep 1;
}

function removePlugInsSoundDriver() {
    local is_unload=false
    local DriverName1=("Splashtop Remote Sound")
    local DriverName2=("SplashtopRemoteSound.driver")

    n=${#DriverName1[@]}
    for (( i=0; i<n; i++ )); do
        local _name=${DriverName1[i]}
        local _driver="/Library/Audio/Plug-Ins/HAL/${DriverName2[i]}"
        local _plist="${_driver}/Contents/Info.plist"

        local BundleIdentifier=""
        local Version=""

        [ -d "${_driver}" ] || continue

        if sudo rm -rf "${_driver}" && system_profiler SPAudioDataType | grep "${_name}:" >/dev/null 2>&1; then
            is_unload=true
        fi
    done

    if [ ${is_unload} = true ]; then
        restartCoreAudioService
    fi
}

function removeKextSoundDriver() {
    local KextInstallPath=("/Library/Extensions" "/System/Library/Extensions")
    local KextName=("SplashtopSoundDriver.kext" "Soundflower.kext")

    for _kextPath in "${KextInstallPath[@]}" ; do
        for _kextName in "${KextName[@]}" ; do
            local is_unload=true
            local _kext="${_kextPath}/${_kextName}"
            local _plist="${_kext}/Contents/Info.plist"

            local BundleIdentifier=""
            local Version=""

            [ -d "${_kext}" ] || continue

            if [ -f "${_plist}" ]; then
                #CFBundleIdentifier
                #CFBundleShortVersionString
                echo "${_plist}"

                BundleIdentifier=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "${_plist}")
                Version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "${_plist}")
            fi

            if [[ "${_kextName}" == "Soundflower.kext" && "${Version}" != "1.6.7" ]]; then
                is_unload=false
            fi

            if [ "$is_unload" = true ]; then
                [ -d "${_kext}" ] && echo "unstall kext... [${_kext}]" ; remove_kext "${_kext}" "${BundleIdentifier}"
            fi
        done
    done
}

function remove_kext() {
    local _kext="$1"
    local bundle_id="$2"

    if [ -z "${bundle_id}" ]; then
        exceCMD "sudo kextunload ${_kext}"
    else
        exceCMD "sudo kextstat -b \"${bundle_id}\" > /dev/null 2>&1 && sudo kextunload -b \"${bundle_id}\""
    fi

    exceCMD "sudo rm -rf \"${_kext}\""
}

function removeSoundDriver() {
    removeKextSoundDriver
    removePlugInsSoundDriver
}

function installPluginSoundDriver() {
    local _path="$1"
    local PlugInsPath="/Library/Audio/Plug-Ins/HAL"
    local SoundPlugInsDriver="$2"
    local SoundPlugInsDriverName="$3"
    local isSkippedInstall="$4"

    local _plist="${_path}/${SoundPlugInsDriver}/Contents/Info.plist"
    local _version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${_plist}")

    if [ -d "${PlugInsPath}/${SoundPlugInsDriver}" ]; then
        local _plist="${PlugInsPath}/${SoundPlugInsDriver}/Contents/Info.plist"
        local Version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${_plist}")

        vercomp "${_version}" "${Version}"
        if [ $? -eq 1 ]; then
            if sudo rm -rf "${PlugInsPath}/${SoundPlugInsDriver}" && system_profiler SPAudioDataType | grep "${SoundPlugInsDriverName}:" >/dev/null 2>&1; then
                restartCoreAudioService
            fi
        else
            # skipped install driver
            echo "skipped install ${SoundPlugInsDriver} drvier. now driver is ${Version}"
            return
        fi
    elif [ ${isSkippedInstall} = true ]; then
        echo "skipped install ${SoundPlugInsDriver} drvier. ${SoundPlugInsDriver} is ${isSkippedInstall}"
        return
    fi

    if sudo cp -rf "${_path}/${SoundPlugInsDriver}" "${PlugInsPath}/"; then
        echo "copy \"${SoundPlugInsDriver}\" driver into ${PlugInsPath}"
        restartCoreAudioService
    fi
}

function installSoundDriver() {
    local DRIVER_PATH="${1}"
    local forceInstall="${2}"

    local MANUAL_UNINSTALL_SOUNDDRIVER=false
    if [ ${forceInstall} = false ]; then
        MANUAL_UNINSTALL_SOUNDDRIVER=true
    fi

    local MIC_DRIVER=false
    #if [ ${forceInstall} = true ]; then
    #    MIC_DRIVER=false
    #fi

    local SOUNDPLUGINSPATH="${DRIVER_PATH}/universal"
    #vercomp "${MAJOR_MAC_VERSION}" "10.15"
    #[ $? -eq 1 ] && SOUNDPLUGINSPATH="${DRIVER_PATH}/universal"

    local MAJOR_MAC_VERSION=$(sw_vers -productVersion | awk -F '.' '{print $1 "." $2}')
    vercomp "${MAJOR_MAC_VERSION}" "10.8"
    if [ $? -eq 1 ]; then
        local driverName=("Splashtop Remote Sound" "Splashtop Remote Microphone")
        local driverFullName=("SplashtopRemoteSound.driver" "SplashtopRemoteMic.driver")
        local driverIsSkippedInstall=(${MANUAL_UNINSTALL_SOUNDDRIVER} ${MIC_DRIVER})

        n=${#driverName[@]}
        for (( i=0; i<n; i++ )); do
            local _name=${driverName[i]}
            local _driver="${driverFullName[i]}"
            local _isSkippedInstall=${driverIsSkippedInstall[i]}

            installPluginSoundDriver "${SOUNDPLUGINSPATH}" "${_driver}" "${_name}" "${_isSkippedInstall}"
        done
    fi
}

function repackDMG() {
    local ORGRINDMGPATH="${1}"
    local REPACKDMGPATH="${2}"
    local INI_SETTING_FILE="${3}"

    local WORKSPACEFOLDER="$(mktemp -d /tmp/$$_XXXXXXX)"
    local TMP_RW_DMG_PATH=$(mktemp -d ${WORKSPACEFOLDER}/ReadableAndWritableCopy_$$.XXXXXXX)".dmg"
    local DESTINATION=$(mktemp -d ${WORKSPACEFOLDER}/$$_XXXXXXX)

    #echo "[${ORGRINDMGPATH}][${REPACKDMGPATH}]"
    #echo "[${TMP_RW_DMG_PATH}][${DESTINATION}]"

    rm -rf "${TMP_RW_DMG_PATH}"
    hdiutil convert -format UDRW -o "${TMP_RW_DMG_PATH}" "${ORGRINDMGPATH}"
    [ $? -ne 0 ] && return 1
    hdiutil attach "${TMP_RW_DMG_PATH}" -nobrowse -mountpoint "${DESTINATION}"
    [ $? -ne 0 ] && return 1
    cp "${INI_SETTING_FILE}" "${DESTINATION}/.PreInstall"
    [ $? -eq 0 ] && ret=0 || ret=1
    hdiutil detach "${DESTINATION}"
    [ $? -ne 0 ] && ret=1
    rm -rf "${REPACKDMGPATH}" 2>/dev/null || true
    hdiutil convert -format UDRO -o "${REPACKDMGPATH}" "${TMP_RW_DMG_PATH}"
    [ $? -ne 0 ] && ret=1

    rm -rf "${WORKSPACEFOLDER}" 2>/dev/null || true

    return $ret
}

function setManualUninstallSoundDrvier {
    local manual_uninstall_sounddriver="$1"

    removeSoundDriver
    if [ "${manual_uninstall_sounddriver}" == "0" ]; then
        installSoundDriver "/Applications/Splashtop Streamer.app/Contents/Resources" true
    fi

    if [ -z "$(ps axc -Ouser | grep "${appName}" | awk '{print $1}')" ]; then
        open "st-streamer://com.splashtop.streamer" && sleep 2
    fi 

    open "st-streamer://com.splashtop.streamer?manual_uninstall_sounddriver=${manual_uninstall_sounddriver}" > /dev/null 2>&1
}
#----------------common function end-------------------------#

function usage()
{
    echo -e "Usage: `basename $1` [-i input streamer dmg file] [-d deploy code] [-a account based setting] [-w show deploy warning] ..."
    echo -e "\t-i : input streamer dmg file."
    echo -e "\t-k : input streamer pkg file."
    echo -e "\t-d : deploy code."
    echo -e "\t-w : show deploy warning (0/1). (default 1)"
    echo -e "\t-n : computer name."
    echo -e "\t-s : show Streamer UI after installation (0/1). (default 1)"
    echo -e "\t-c : init security code."
    echo -e "\t-e : Require additional password to connect (0:off, 1:Require security code, 2:Require Mac login). (default 0)"
    echo -e "\t-r : Request permission to connect (0:off, 1:reject after request expires, 2:connect after request expires, 3:reject after request expires and allow connect in pre-login)."
    echo -e "\t-l : loopback connection only (0/1). (default 0)"
    echo -e "\t-h : hide tray icon (0/1). (default 0)"
    echo -e "\t-b : default client name on connection bubble."
    echo -e "\t-p : enable LAN TCP/UDP server. (default 1)"
    echo -e "\t-v : force install/remove remote sound driver. (1/0)"
    echo -e "\t-t : to skip install pkg or dmg, to re-config setting."
    echo -e "\t-f : force Infrastructure Generation setting."
    echo -e "\t-x : Use high precision UUID. (V3473)"
    echo -e "\t-y : Re-Pack DMG with setting. (Just support DMG -i)"
}

#----------------usage function--------------------------#

echo "ReleaseDate: 20250116"

# -i : input streamer dmg file.
DMG_IN=""
# -k : input streamer pkg file.
PKG_IN=""
# -d : deploy code.
DEPLOY_CODE=""
# -n : computer name."
COMPUTER_NAME=""
# -r : Request permission to connect (0:off, 1:reject after request expires, 2:connect after request expires, 3:reject after request expires and allow connect in pre-login).
REQUEST_PERMISSION=""
# -c : init security code.
INIT_SECURITY_CODE=""
# -e : Require additional password to connect (0:off, 1:Require security code, 2:Require Mac login). (default 0)"
SECURITY_OPTION=""
# -l : loopback connection only (0/1). (default 0)
LOOPBACK_ONLY="0"
# -v : force install/remove remote sound driver. (1/0)
INSTALL_SOUND_DRIVER="-1"
# -h : hide tray icon (0/1). (default 0
HIDE_TRAY_ICON="0"
# -b : default client name on connection bubble.
DEFAULT_CLIENT_NAME=""
SHOW_DEPLOY_WARNING=""
# -s : show Streamer UI after installation (0/1). (default 1)"
SHOW_STREAMER_UI=""
# -p : enable LAN TCP/UDP server. (default 1)
ENABLE_LAN_SERVER=""
# -t : to skip install pkg or dmg, to re-config setting.
SkippedInstall="0"
# -f : force Infrastructure Generation setting.
InfraGenForce=""
# -y : Re-Pack DMG with setting. (Just support DMG -i)
REPACKDMGPATH=""
ForceUUID32=""

#check options
OPTIND=1
# Reset is necessary if getopts was used previously in the script.  It is a good idea to make this local in a function.
while getopts i:k:d:w:n:s:c:e:r:l:v:h:b:p:f:x:y:t o
do	case "$o" in
    i)
        DMG_IN="$OPTARG"
        ;;
    k)
        PKG_IN="$OPTARG"
        ;;
    d)
        DEPLOY_CODE="$OPTARG"
        ;;
    w)
        SHOW_DEPLOY_WARNING="$OPTARG"
        ;;
    n)
        COMPUTER_NAME="$OPTARG"
        ;;
    s)
        SHOW_STREAMER_UI="$OPTARG"
        ;;
    c)
        INIT_SECURITY_CODE="$OPTARG"
        ;;
    e)
        SECURITY_OPTION="$OPTARG"
        ;;
    r)
        REQUEST_PERMISSION="$OPTARG"
        ;;
    l)
        LOOPBACK_ONLY="$OPTARG"
        ;;
    v)
        INSTALL_SOUND_DRIVER="${OPTARG}"
        ;;
    h)
        HIDE_TRAY_ICON="$OPTARG"
        ;;
    b)
        DEFAULT_CLIENT_NAME="$OPTARG"
        ;;
    p)
        ENABLE_LAN_SERVER="$OPTARG"
        ;;
    f)
        InfraGenForce="${OPTARG// }"
        ;;
    x)
        if ((10#${OPTARG} > 0)); then
            ForceUUID32="true"
        else
            ForceUUID32="false"
        fi
        ;;
    y)
        if [ ! -z "${OPTARG// }" ]; then
            REPACKDMGPATH="${OPTARG}"
        else
            REPACKDMGPATH="!!!!####empty dmg####!!!!"
        fi
        ;;
    t)
        SkippedInstall="1"
        ;;
	[?])
		echo "invalid option: $1" 1>&2;
		usage "$0"
		exit 1;;
	esac
done
shift $((OPTIND-1)) # Shift off the options and optional --.

if [ -z "${DMG_IN}" ] && [ -z "${PKG_IN}" ] && [ "${SkippedInstall}" == "0" ]; then
    echo "Please input streamer dmg or pkg file!"
    usage "$0"
    exit 1
elif [ -z "${DMG_IN}" ] && [ ! -z "${REPACKDMGPATH// }" ] && [ "${SkippedInstall}" == "0" ]; then
    echo "Please input streamer dmg file! To re-pack dmg with setting."
    usage "$0"
    exit 1
fi


if [ ! -z "${REPACKDMGPATH// }" ] && [ "${REPACKDMGPATH}" == "!!!!####empty dmg####!!!!" ] ; then
    filename=$(basename "${DMG_IN}")
    extension="${filename##*.}"
    filename="${filename%.*}"
    REPACKDMGPATH="$(pwd)/${filename}.repack.${extension}"
fi

PRE_INSTALL_PATH="/Users/Shared/SplashtopStreamer"
#write .PreInstall
echo "Inject settings"
mkdir "${PRE_INSTALL_PATH}" 2>/dev/null || true

TEMP_DIR="$(mktemp -d)"

Exit_safely () {
    [ -z "${VOLUME}" ] || hdiutil detach -quiet "${VOLUME}" 2>/dev/null || true
    
    #rm -rf "${PRE_INSTALL}" 2>/dev/null || true
    rm -rf "${TEMP_DIR}" 2>/dev/null || true
}

trap Exit_safely EXIT

PRE_INSTALL="${PRE_INSTALL_PATH}/.PreInstall"
FILENAME="${TEMP_DIR}/.PreInstall.$$"
echo "Writing file ${PRE_INSTALL}"
#set plist header and common dict
# 0: STP, 1: STB, 2: STE
DEFAULT_STREAMER_TYPE="0"
setPlistByStreamerType "${FILENAME}" "${DEFAULT_STREAMER_TYPE}"

[ ! -z "${DEPLOY_CODE// }" ] && setDeployCode "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${DEPLOY_CODE// }"
setShowDeployLoginWarning "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${SHOW_DEPLOY_WARNING// }"
[ ! -z "${COMPUTER_NAME// }" ] && setComputerName "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${COMPUTER_NAME// }"
[ ! -z "${REQUEST_PERMISSION// }" ] && setPermissionProtectionOption "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${REQUEST_PERMISSION// }"
[ ! -z "${SECURITY_OPTION// }" ] && setSecurityOption "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${SECURITY_OPTION// }"
[ ! -z "${INIT_SECURITY_CODE// }" ] && setInitSecurityCode "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${INIT_SECURITY_CODE// }"
[ "$LOOPBACK_ONLY" == "1" ] && setLegacyConnectionLoopbackOnly "${FILENAME}" "${DEFAULT_STREAMER_TYPE}"
[ "$HIDE_TRAY_ICON" == "1" ] && setHideTrayIcon "${FILENAME}" "${DEFAULT_STREAMER_TYPE}"
[ ! -z "${DEFAULT_CLIENT_NAME// }" ] && setDefaultClientDeviceName "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${DEFAULT_CLIENT_NAME// }"
[ "$SHOW_STREAMER_UI" == "0" ] && setShowStreamerUI "${FILENAME}" "${DEFAULT_STREAMER_TYPE}"
[ "$ENABLE_LAN_SERVER" == "0" ] && setEnableLanConnection "${FILENAME}" "${DEFAULT_STREAMER_TYPE}"
[ ! -z "${InfraGenForce// }" ] && setInfraGenForce "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${InfraGenForce}"
[ ! -z "${ForceUUID32// }" ] && setForceUUID32 "${FILENAME}" "${DEFAULT_STREAMER_TYPE}" "${ForceUUID32}"

if [ ! -z "${REPACKDMGPATH// }" ]; then
    repackDMG "${DMG_IN}" "${REPACKDMGPATH}" "${FILENAME}"
    if [ $? -ne 0 ]; then
        echo "error : re-pack dmg failed."
    fi
    rm -rf "${FILENAME}"
    exit 0
fi

ret=0
sudo cp -r "${FILENAME}" "${PRE_INSTALL}"
rm -rf "${FILENAME}"
#sudo chown -R root:wheel "${PRE_INSTALL}"
sudo chmod 644 "${PRE_INSTALL}"

if [ "${SkippedInstall}" == "0" ]; then
    ret=-1
    DEFAULT_PKG_SORUCE=""
    INSTALLER_PKG_PATH=""
    if [ ! -z "${DMG_IN}" ]; then
        if [ ! -f "${DMG_IN}" ]; then
            echo "${DMG_IN} is not exist."
            rm -rf "${PRE_INSTALL}" 2>/dev/null || true
            exit 1
        fi

        #mount dmg
        VOLUME=$(hdiutil attach -nobrowse "${DMG_IN}" -mountroot "${TEMP_DIR}" | awk 'END {print $3}')
        [ -z "${VOLUME}" ] && VOLUME="/Volumes/SplashtopStreamer"
        echo "Mounting dmg file, Volume \"${VOLUME}\"."

        NORMAL_INSTALLER="${VOLUME}/Splashtop Streamer.pkg"
        HIDDEN_INSTALLER="${VOLUME}/.Splashtop Streamer.pkg"

        if [ -f "${NORMAL_INSTALLER}" ] || [ -f "${HIDDEN_INSTALLER}" ]; then
            # copy pkg file into temp folder
            if [ ! -f "${NORMAL_INSTALLER}" ]; then
                cp "${HIDDEN_INSTALLER}" "${TEMP_DIR}/Splashtop Streamer.pkg"
                DEFAULT_PKG_SORUCE="${HIDDEN_INSTALLER}"
            else
                cp "${NORMAL_INSTALLER}" "${TEMP_DIR}/Splashtop Streamer.pkg"
                DEFAULT_PKG_SORUCE="${NORMAL_INSTALLER}"
            fi
            INSTALLER_PKG_PATH="${TEMP_DIR}/Splashtop Streamer.pkg"
        else
            ls -asl "${VOLUME}"
            echo "Install failed. Can not find installer pkg in [${VOLUME}]."
            rm -rf "${PRE_INSTALL}" 2>/dev/null || true
            exit 1
        fi
        
        echo "Unmount dmg. ${VOLUME}"
        hdiutil detach -quiet "${VOLUME}"
    else
        if [ ! -f "${PKG_IN}" ]; then
            echo "${PKG_IN} is not exist."
            rm -rf "${PRE_INSTALL}" 2>/dev/null || true
            exit 1
        fi

        # copy pkg file into temp folder
        cp "${PKG_IN}" "${TEMP_DIR}/Splashtop Streamer.pkg"

        DEFAULT_PKG_SORUCE="${PKG_IN}"
        INSTALLER_PKG_PATH="${TEMP_DIR}/Splashtop Streamer.pkg"
    fi

    if [ ! -z "${INSTALLER_PKG_PATH}" ] && [ -f "${INSTALLER_PKG_PATH}" ]; then
        # copy preinstall setting into temp folder
        cp "${PRE_INSTALL}" "${TEMP_DIR}/.PreInstall"

        echo "Install silently"
        sudo installer -pkg "${INSTALLER_PKG_PATH}" -target /
        ret=$?

        if [ $ret -ne 0 ]; then
            echo "Install failed. (${ret}) [${INSTALLER_PKG_PATH}][${DEFAULT_PKG_SORUCE}]"
            rm -rf "${PRE_INSTALL}" 2>/dev/null || true
        fi
    fi

    if [ $ret -eq 0 ]; then
        if [ "${INSTALL_SOUND_DRIVER}" != "-1" ];then
            if [ "${INSTALL_SOUND_DRIVER}" == "1" ];then
                setManualUninstallSoundDrvier "0"
            elif [ "${INSTALL_SOUND_DRIVER}" == "0" ];then
                setManualUninstallSoundDrvier "1"
            fi
        fi
    fi 
else
    if [ ! -d "/Applications/Splashtop Streamer.app" ]; then
        echo "Error : Splashtop Streamer is not installed."

        rm -rf "${PRE_INSTALL}" 2>/dev/null || true
        exit 1
    fi

    if [ "$USER" == "root" ]; then
        if [ "${INSTALL_SOUND_DRIVER}" == "1" ];then
            setManualUninstallSoundDrvier "0"
        elif [ "${INSTALL_SOUND_DRIVER}" == "0" ];then
            setManualUninstallSoundDrvier "1"
        fi
    fi

    echo "Skipped install pkg or dmg, to re-config setting."
    restartApp "Splashtop Streamer"
fi

#echo "Launch Streamer"
#open "/Applications/Splashtop Streamer.app"

rm -fr "${TEMP_DIR}" 2>/dev/null || true
echo "Done!"

exit ${ret}

