
New-Item "$PSScriptRoot\IsPatching.txt" -ErrorAction SilentlyContinue

if ($PSVersionTable -eq $null)
{
    Write-Host -ForegroundColor Red -BackgroundColor Black 'Please install Windows PowerShell v5. Current version is v1'
    exit -1	
}
if ($PSVersionTable.PSVersion.Major -lt 4)
{
    Write-Host -ForegroundColor Red -BackgroundColor Black "Please install Windows PowerShell v5. Current version is $($PSVersionTable.PSVersion)"
    exit -1	
}

$PatchesPath = "$PSScriptRoot\Patches"

New-Item -Path $PatchesPath -ItemType directory -Force > $null

if (Test-Path -Path "$PSScriptRoot\bin\SheetKraftWeb.dll")
{
    $InstalledVersion = [Version] [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$PSScriptRoot\bin\SheetKraftWeb.dll").FileVersion
}

if ($InstalledVersion -eq $null)
{
    $InstalledVersion = [Version] [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$PSScriptRoot\Runner\ActivityRunner.exe").FileVersion
}

if ($InstalledVersion -eq $null)
{
	Write-Host -ForegroundColor Red -BackgroundColor Black 'Could not obtain the installed version. Make sure that the location of this script file is correct'
    exit -1	
}

$webConfigFilePath = "Web.config"

if (-not (Test-Path -Path $webConfigFilePath)) {
    Write-Host "Web.config not found, please ensure it exists at $webConfigFilePath"
    exit -1
}

$webConfigContent = [xml](Get-Content -Path $webConfigFilePath)
$EnvKey = "Environment"
$nodeValue = $webConfigContent.configuration.appSettings.add | Where-Object { $_.key -eq $EnvKey }

if ($nodeValue -eq $null) 
{
    Write-Host -NoNewline "Key $EnvKey not found in the Web.config file, please add it under the appSettings section."
	exit -1
}

$Env = $nodeValue.value

if ($Env -eq "")
{
	Write-Host "Environment value is not set, please set it to a non-empty value in Web.config."
	exit -1
}
$EnvCheck = Read-Host "Please type the name of the environment to continue."

if ($Env -ne $EnvCheck)
{
	Write-Host "The current environment is $Env but you intended to apply the patch to $EnvCheck. Please check that you are logged in to the correct environment. If you are, check why the environment entered in the web.config file does not match."
	exit -1
}
 
Write-Host -NoNewline 'Installed version is '
Write-Host -ForegroundColor Yellow -BackgroundColor Black "$($InstalledVersion.Major).$($InstalledVersion.Minor).$($InstalledVersion.Build)$(if ($InstalledVersion.Revision -eq 0) {''} else {'.' + $InstalledVersion.Revision})"

$AvailablePatchVersions = Get-Item "$PatchesPath\SheetKraft.*.zip" |`
ForEach-Object `
{
    $v = [regex]::Match($_.Name, '(?i)SheetKraft\.(?:Patch|Full)\.(\d+\.\d+\.\d+(\.\d+)?)\.zip').Groups[1].Value
    if ($v.Length -eq 0) {$v = '0.0.0.0'}
    elseif (($v -split '\.').Count -eq 3) {$v += '.0'}
    New-Object -TypeName Version -ArgumentList $v
} |`
Where-Object {$_.Major -ne 0} | Sort-Object -Descending | Get-Unique

if (($AvailablePatchVersions | Select-Object -First 1) -ne $null)
{
    Write-Host "The patches shown below have already been downloaded in the Patches folder."
    Write-Host -ForegroundColor Yellow -BackgroundColor Black -Separator "`n" @($AvailablePatchVersions | ForEach-Object {
        "$($_.Major).$($_.Minor).$($_.Build)$(if ($_.Revision -eq 0) { '' } else { '.' + $_.Revision })"
    })
}
else
{
    "There are no patch files in the Patches folder."
}

$DesiredVersionStr = ''
while ($DesiredVersionStr -notmatch '^\d+\.\d+\.\d+(\.\d+)?$')
{
    $DesiredVersionStr = Read-Host "Please enter desired version in the form 'a.b.c' or 'a.b.c.d'. If it is not listed above, it will be downloaded from sheetkraft.com"
}

#Find latest version of patch
$DesiredVersion = New-Object -TypeName Version -ArgumentList $(if ($DesiredVersionStr -like '*.*.*.*') { $DesiredVersionStr } else { "$DesiredVersionStr.0" })

if ($DesiredVersion -lt $InstalledVersion)
{
    $ConfirmDowngrade = Read-Host "Please type the full word 'downgrade' to continue with the downgrade."
    if ($ConfirmDowngrade -ne 'downgrade')
    {
        Write-Host -ForegroundColor Red -BackgroundColor Black 'The downgrade was cancelled'
        exit -1
    }
}

$DesVerStr = "$($DesiredVersion.Major).$($DesiredVersion.Minor).$($DesiredVersion.Build)$(if ($DesiredVersion.Revision -eq 0) { '' } else { '.' + $DesiredVersion.Revision })"
$PatchFile = "SheetKraft.Patch.$DesVerStr.zip"
$PatchZip = "$PatchesPath\$PatchFile"
if ($AvailablePatchVersions -notcontains $DesiredVersion)
{
    $PatchUrl = "http://releases.sheetkraft.com/$PatchFile"
    Write-Host -NoNewline 'Attempting to download '
    Write-Host -ForegroundColor Yellow -BackgroundColor Black $PatchUrl
    try
    {
        Invoke-WebRequest -Uri $PatchUrl -OutFile $PatchZip -UserAgent "NativeHost"
        Write-Host -ForegroundColor Green -BackgroundColor Black "Patch downloaded successfully to $PatchZip."
    }
    catch
    {
        Write-Host -ForegroundColor Red -BackgroundColor Black "Failed to download the patch from $PatchUrl.
Please download it manually and place it in the Patches folder and run the script again. Error message is shown below
$($_.Exception.Message)"
        Exit -1
    }
}

$ZipPath = $PatchZip
$FolderName = 'SheetKraft.Patch'
if (!(Test-Path -Path $PatchZip))
{
    $FolderName = 'SheetKraft.Full'
    $ZipPath = "$PatchesPath\$FolderName.$DesVerStr.zip"
}

#Delete Temp Directory
Get-Item "$PatchesPath\$FolderName*" -Filter $FolderName | Remove-Item -Recurse -Force
Add-Type -assembly "System.IO.Compression.FileSystem"

try
{
    Unblock-File -Path $ZipPath
    Write-Host -NoNewline 'Attempting to extract '
    Write-Host -ForegroundColor Yellow -BackgroundColor Black $ZipPath
    [System.IO.Compression.ZipFile]::ExtractToDirectory($ZipPath, $PatchesPath)
    Write-Host -ForegroundColor Green -BackgroundColor Black "Patch extracted successfully."
}
catch
{
    Write-Host  -ForegroundColor Red -BackgroundColor Black "Failed to extract the patch from $ZipPath.
The file may be corrupt. Delete the file and try again. Error message is shown below
$($_.Exception.Message)"
        Exit - 1
}
& "$PatchesPath\$FolderName\Patch.ps1"

Remove-Item "$PSScriptRoot\IsPatching.txt" -ErrorAction SilentlyContinue
