$DisplayName = "NAKIVO Backup & Replication"
$ProductUuid = "2C90508235DDBB670135DDBB739E0001"
$Contact = "support@nakivo.com"
$HelpLink = "https://www.nakivo.com"
$Readme = "https://www.nakivo.com"
$UrlInfoAbout = "https://www.nakivo.com"
$UrlUpdateInfo = "https://www.nakivo.com"
$DisplayVersion = "11.2.0.101299"
$Publisher = "NAKIVO, Inc"
$InstallLocation = "C:\Program Files\NAKIVO Backup & Replication"
$TransporterInstallLocation = "C:\Program Files\NAKIVO Backup & Replication\transporter"
$InstallRegistryFileName = "install.reg"
$UninstallScriptFileName = "uninstall.ps1"
$ProductUuidJavaPrefs = "2/C90508235/D/D/B/B670135/D/D/B/B739/E0001" # All alpha symbols are escaped
$InstallerHiveJavaPrefs = "/Installer/Hive" # All alpha symbols are escaped
$TransporterServicePort = "9446"
$TransporterServiceFirewallPortRange = @("9446","9448-10000") # Array of strings, e.g. "9446","9448-10000"
$TransporterServiceName = "bhsvc"
$TransporterServiceDisplayName = "NAKIVO Backup & Replication Transporter"
$TransporterServiceBinary = "bhsvc.exe"
$TransporterServiceDescription = "Performs data processing and transfer for NAKIVO Backup & Replication."
$TransporterIcon = "icon.ico"
$Update = $false
$IgnoreVcRedistInstallFailure = $false
$VcRedistSuccessCodes = @("0", "1603", "1638", "3010", "5100")
$SkipVcRedistInstall = $false
# Terminate on first error, do not continue
$ErrorActionPreference="Stop"
# Get powershell version
$PSVersion=$PSVersionTable.PSVersion.Major
$HasRedirectBugs=($PSVersion -lt 3)

# Removes standalone Windows installer registry key
function RemoveWindowsInstallerInfo() {
    echo "Removing installer info from registry."

    $hive = [Microsoft.Win32.Registry]::LocalMachine
    $prefsKey = $hive.openSubKey("SOFTWARE\JavaSoft\Prefs", $true)

    if ($prefsKey -ne $null) {
        $prefsKey.deleteSubKeyTree($InstallerHiveJavaPrefs, $false)
    }
}

# Checks service existence
function IsServiceExists() {
    echo "Checking if the service exists: $TransporterServiceName"

    $serviceExists = $true
    try {
        Get-Service -name $TransporterServiceName
    } catch {
        $serviceExists = $false
    }

    echo "Service exists: $serviceExists"

    $serviceExists
}

# Dumps exception into the log
function DumpException($exception) {
    try {
        echo $exception | format-list -force
    } catch {
        try {
            echo $exception
        } catch {
            echo "Exception happened."
        }
    }
}

try {
    # Support old Windows/PS version. This can happen even in Win2012R2.
    if (Get-Command Remove-NetFirewallRule -ErrorAction SilentlyContinue) {
        echo "Firewall: deleting rules via Remove-NetFirewallRule: $DisplayName"

        if ($HasRedirectBugs) {
            Remove-NetFirewallRule -DisplayName "$DisplayName" >$null
        } else {
            Remove-NetFirewallRule -DisplayName "$DisplayName"
        }
    } else {
        echo "Firewall: deleting rules via netsh: $DisplayName"

        if ($HasRedirectBugs) {
            Invoke-Expression "netsh advfirewall firewall delete rule name='$DisplayName' dir=in profile=any protocol=TCP localport=$TransporterServicePort" >$null
        } else {
            Invoke-Expression "netsh advfirewall firewall delete rule name='$DisplayName' dir=in profile=any protocol=TCP localport=$TransporterServicePort"
        }
    }
} catch {
    echo "Firewall rule removal failed."
    DumpException($_.Exception)
}

try {
    echo "Setting up the Transporter service."

    if (IsServiceExists) {
        Stop-Service $TransporterServiceName -ErrorAction Continue

        echo "Deleting service: $TransporterServiceName"

        if ($HasRedirectBugs) {
            sc.exe delete $TransporterServiceName >$null
        } else {
            sc.exe delete $TransporterServiceName
        }
    }
} catch {
    echo "Transporter service removal failed."
    DumpException($_.Exception)
}

try {
    RemoveWindowsInstallerInfo
} catch {
    echo "Standalone installer info removal failed."
    DumpException($_.Exception)
}

try {
    $uninstall = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
    $fullpath = "$uninstall$ProductUuid"

    echo "Cleaning registry: $fullpath"

    try {
        if (Test-Path $fullpath) {
            Remove-Item -Path $fullpath -ErrorAction Continue
        }
    } catch {
        # Ignore. "ErrorAction" is ignored on some systems.
    }

    if ($Update) {
        # KEEP_LIST="bh-logs bh-base bh-mount bh-vddk bhsvc.id certificate.pem activedc.conf uninstall.bat uninstall.ps1"
        $keepList = @('bh-logs', 'bh-base', 'bh-mount', 'bh-cfg', 'bh-vddk', 'bhsvc.id', 'certificate.pem', 'activedc.conf', 'uninstall.bat', 'uninstall.ps1')

        echo "Update mode: removing all in $TransporterInstallLocation except $keepList"

        $files = Get-Item "$TransporterInstallLocation\\*"
        for ($i = 0; $i -lt $files.length; $i++) {
            if (!$keepList.Contains($files[$i].Name)) {
                Remove-Item $files[$i] -Recurse -ErrorAction Continue
            }
        }

        echo "Update mode: remove complete."
    } else {
        echo "Uninstall mode: removing files in $TransporterInstallLocation"

        # Create temp files to hold the locations for self destruct commands to read later.
        $TransporterInstallLocation | Out-File "$env:TEMP\til.tmp"
        $InstallLocation | Out-File "$env:TEMP\il.tmp"

        $selfDestructCommands = {
            Start-Sleep -s 1
            $TransporterInstallLocation=Get-Content "$env:TEMP\til.tmp"
            $InstallLocation=Get-Content "$env:TEMP\il.tmp"

            # Remove temp files.
            Remove-Item "$env:TEMP\til.tmp" -Force
            Remove-Item "$env:TEMP\il.tmp" -Force

            # Remove files and folders.
            Remove-Item "$TransporterInstallLocation\\*" -Recurse -ErrorAction Continue
            Remove-Item "$TransporterInstallLocation\\" -Force
            if ((Get-Item "$InstallLocation\\").GetFileSystemInfos().count -eq 0) {
                Remove-Item "$InstallLocation\\"
            } elseif (!(Test-Path "$InstallLocation\\director")) {
                # Remove standalone installer's folders
                $removeList = @('installer', 'jre', 'native')
                $files = Get-Item "$InstallLocation\\*"
                for ($i = 0; $i -lt $files.length; $i++) {
                    if ($removeList.Contains($files[$i].Name)) {
                        Remove-Item $files[$i] -Recurse -ErrorAction Continue
                    }
                }
                if ((Get-Item "$InstallLocation\\").GetFileSystemInfos().count -eq 0) {
                    Remove-Item "$InstallLocation\\"
                }
            }
        }

        Start-Process "PowerShell.exe" -ArgumentList "-Command $selfDestructCommands" -windowstyle Hidden
    }
} catch {
    echo "Windows Programs and Features info removal failed."
    DumpException($_.Exception)
}
