& {
    . "$PSScriptRoot/../../lib/Restoration.ps1";
    . "$PSScriptRoot/../../lib/SoftwareManagement.ps1";
    . "$PSScriptRoot/../../../lib/BrowserAutomation.ps1";
    . "$PSScriptRoot/../../../lib/Software.ps1";
    . "$PSScriptRoot/../../../lib/SoftwareManagement.ps1";
    . "$PSScriptRoot/../../../lib/System.ps1";

    [System.Tuple[string, string, string][]] $versions = @(
        [System.Tuple]::Create("visualstudio2019enterprise", "VisualStudio.16.Release", "Microsoft.VisualStudio.Product.Enterprise"),
        [System.Tuple]::Create("visualstudio2019community", "VisualStudio.16.Release", "Microsoft.VisualStudio.Product.Community"),
        [System.Tuple]::Create("visualstudio2022enterprise", "VisualStudio.17.Release", "Microsoft.VisualStudio.Product.Enterprise"),
        [System.Tuple]::Create("visualstudio2022community", "VisualStudio.17.Release", "Microsoft.VisualStudio.Product.Community")
    );

    <#
        .SYNOPSIS
        Gets the path to the Visual Studio Installer.
    #>
    function Get-InstallerPath {
        return "$((Get-KnownFolder ProgramFilesX86).Path)/Microsoft Visual Studio/Installer/vs_installer.exe";
    }

    <#
        .SYNOPSIS
        Gets the path to the configuration file in the backup archive.

        .PARAMETER Name
        The name of the software.

        .PARAMETER PackageName
        The name of the package to get the configuration for.
    #>
    function Get-ConfigPath {
        param(
            [string] $Name,
            [string] $PackageName
        )

        return Join-Path "$Name" "$PackageName.vsconfig";
    }

    Start-SoftwareInstaller @args `
        -Backup {
            param([string] $Name)

            foreach ($version in $versions) {
                if (Test-ChocoPackage $version[0]) {
                    Write-Host "Backing up ``$($version[0])…";
                    $configFile = New-TemporaryFile;

                    Start-Process -FilePath (Get-InstallerPath) -Wait `
                        -ArgumentList @(
                            "export",
                            "--channelId", $version[1],
                            "--productId", $version[2],
                            "--config", $configFile,
                            "--quiet"
                        );

                    Add-BackupArtifacts -Source $configFile -Path (Get-ConfigPath $Name $version[0]);
                    Remove-Item $configFile;
                }
            }
        } `
        -Installer {
            param([string] $Name)

            foreach ($version in $versions) {
                $packageName = $version[0];
                $file = New-TemporaryFile;
                Remove-Item $file;
                Expand-BackupArtifacts -Path (Get-ConfigPath $Name $packageName) -Target $file;

                if (Test-Path $file) {
                    Write-Host "Restoring ``$packageName``…";
                    Install-ChocoPackage $packageName -ArgumentList "--params", "--config `"$file`"";
                }
            }

            Remove-DesktopIcon "CocosCreator*";
            Remove-DesktopIcon "Unity Hub*";
        };
} @args;