[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true)]
    [System.String] $configuration
)

Add-Type -AssemblyName System.IO.Compression.FileSystem

$ErrorActionPreference = 'Stop'

function Unzip {
    param([string]$zipfile, [string]$outpath)

    Write-Verbose "Unzipping '$zipfile' to '$outpath'."

    [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}

function Confirm-NugetPackages {
    Write-Verbose "Starting Confirm-NugetPackages."
    $expectedNumOfFiles = @{
        "MSTest.Sdk"                                  = 15
        "MSTest.TestFramework"                        = 105
        "MSTest.TestAdapter"                          = 66
        "MSTest"                                      = 10
        "MSTest.Analyzers"                            = 56
        "MSTest.SourceGeneration"                     = 8
    }

    $packageDirectory = Resolve-Path "$PSScriptRoot/../artifacts/packages/$configuration"
    $tmpDirectory = Resolve-Path "$PSScriptRoot/../artifacts/tmp/$configuration"
    $nugetPackages = Get-ChildItem -Filter "*.nupkg" $packageDirectory -Recurse -Exclude "*.symbols.nupkg" | ForEach-Object { $_.FullName }

    Write-Verbose "Unzipping NuGet packages."
    $unzipNugetPackageDirs = @()
    foreach ($nugetPackage in $nugetPackages) {
        $unzipNugetPackageDir = $(Join-Path $tmpDirectory (Get-Item $nugetPackage).BaseName)
        $unzipNugetPackageDirs += $unzipNugetPackageDir

        if (Test-Path -Path $unzipNugetPackageDir) {
            Remove-Item -Force -Recurse $unzipNugetPackageDir
        }

        Unzip $nugetPackage $unzipNugetPackageDir
    }

    $versionPropsXml = [xml](Get-Content $PSScriptRoot\Versions.props)
    $version = $versionPropsXml.Project.PropertyGroup.VersionPrefix | Where-Object { $null -ne $_ } | Select-Object -First 1
    if ($null -eq $version) {
        throw "version is null"
    }

    Write-Verbose "Package version is '$version'."

    Write-Verbose "Verifying NuGet packages files."
    $errors = @()
    foreach ($unzipNugetPackageDir in $unzipNugetPackageDirs) {
        try {
            $packageName = (Get-Item $unzipNugetPackageDir).BaseName
            $nuspecFiles = @(Get-ChildItem -Path $unzipNugetPackageDir -Filter "*.nuspec" -File)
            if ($nuspecFiles.Count -ne 1) {
                $errors += "Expected exactly one nuspec in '$packageName', actual: $($nuspecFiles.Count)"
            }
            else {
                $nuspec = [xml](Get-Content -Raw $nuspecFiles[0].FullName)
                $metadata = $nuspec.package.metadata

                if ([string]::IsNullOrWhiteSpace([string]$metadata.tags)) {
                    $errors += "Package '$packageName' does not define tags"
                }

                $readme = [string]$metadata.readme
                if ([string]::IsNullOrWhiteSpace($readme)) {
                    $errors += "Package '$packageName' does not define a readme"
                }
                elseif (!(Test-Path -Path (Join-Path $unzipNugetPackageDir $readme) -PathType Leaf)) {
                    $errors += "Package '$packageName' readme '$readme' is not included in the package"
                }

                $icon = [string]$metadata.icon
                if ([string]::IsNullOrWhiteSpace($icon)) {
                    $errors += "Package '$packageName' does not define an icon"
                }
                elseif (!(Test-Path -Path (Join-Path $unzipNugetPackageDir $icon) -PathType Leaf)) {
                    $errors += "Package '$packageName' icon '$icon' is not included in the package"
                }
            }

            $versionIndex = $packageName.LastIndexOf($version)
            if ($versionIndex -lt 0) {
                continue
            }

            $packageKey = $packageName.Substring(0, $versionIndex - 1) # Remove last dot
            Write-Verbose "Verifying package '$packageKey'."

            $actualNumOfFiles = (Get-ChildItem -Recurse -File -Path $unzipNugetPackageDir).Count
            if ($expectedNumOfFiles[$packageKey] -ne $actualNumOfFiles) {
                $errors += "Number of files are not equal for '$packageKey', expected: $($expectedNumOfFiles[$packageKey]) actual: $actualNumOfFiles"
            }
        }
        finally {
            if (Test-Path $unzipNugetPackageDir) {
                Remove-Item -Force -Recurse $unzipNugetPackageDir | Out-Null
            }
        }
    }

    if ($errors) {
        Write-Error "Validation of NuGet packages failed with $($errors.Count) errors:`n$($errors -join "`n")"
    } else {
        Write-Host "Successfully validated content and metadata of NuGet packages"
    }
}

Confirm-NugetPackages
