GsriModpackLib.psm1

function Get-LocalVersion {
    [CmdletBinding()]
    param(
        [string]$Path
    )
    $VersionFile = "$Path\version.txt"
    if (-not(Test-Path $VersionFile -PathType Leaf)) {
        Write-Verbose "$VersionFile not found"
        return 0
    }
    $Version = (Get-Content "$Path\version.txt" -ErrorAction SilentlyContinue).Trim()
    Write-Verbose "Local version : $Version"
    return $Version
}

function Get-RemoteVersion {
    [CmdletBinding()]
    param()

    $Content = (Invoke-WebRequest -URI 'https://mods.gsri.team/version.txt').Content
    if ($null -eq $Content) { throw 'Cannot contact GSRI mods repository' }
    $Version = $Content.Trim()
    Write-Verbose "Remote version : $Version"
    return $Version
}

function Test-ModpackVersion {
    [CmdletBinding()]
    param(
        [string]$Path
    )

    $Remote = Get-RemoteVersion    
    $Local = Get-LocalVersion -Path $Path
    if (0 -eq $Local) {
        Write-Verbose 'Local modpack not detected'
        return $false
    }

    $Compare = Compare-Object $Remote -DifferenceObject $Local
    if ( $null -eq $Compare) {
        Write-Verbose 'Local and remote versions match'
        return $true
    }
    else {
        Write-Verbose 'Local and remote versions mismatch'
        return $false
    }
}

function Write-Generic {
    [CmdletBinding()]
    param(
        [string]$Message,
        [bool]$Result
    )
    Write-Host "$Message :`t" -NoNewline
    if ($Result) {
        Write-Host -ForegroundColor Green '[OK]'
        return 0
    } 
    Write-Host -ForegroundColor Red '[FAIL]'
    return 1
}

function Write-AppInstallationStatus {
    [CmdletBinding()]
    param(
        [string]$Name,
        [string]$Node,
        [string]$Property = 'InstallLocation',
        [switch]$IsWOW64
    )
    $Result = (Test-AppInstallation -Name $Name -Node $Node -Property $Property -IsWOW64:$IsWOW64 -Verbose:($PSBoundParameters['Verbose'] -eq $true))
    return Write-Generic -Message "Checking app installation $Name" -Result $Result
}

function Write-ModpackStatus {
    [CmdletBinding()]
    param(
        [string] $Path
    )
    
    $Result = (Test-ModpackVersion -Path $Path)
    return Write-Generic -Message 'Checking GSRI modpack is up-to-date' -Result $Result
}

function Write-TaskForceStatus {
    [CmdletBinding()]
    param()

    $Result = Test-TaskForceStatus -Verbose:($PSBoundParameters['Verbose'] -eq $true)
    return Write-Generic -Message 'Checking TFAR plugin installation' -Result $Result    
}
function Test-Paths {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [string[]]$Files,
        [int]$Expected
    )
    Begin {
        $Actual = 0
    }
    Process {
        $Files | ForEach-Object {
            if (Test-Path $_ -PathType Leaf) {
                $Actual++
                Write-Verbose "$_ found"
            }
            else {
                Write-Verbose "$_ not found"
            }
        }
    }
    End {
        return $Expected -eq $Actual
    }
}

function Test-TaskForceLegacy {
    [CmdletBinding()]
    param()

    return "$env:APPDATA\TS3Client\plugins\task_force_radio_win64.dll",
    "$env:APPDATA\TS3Client\plugins\task_force_radio_win32.dll" | Test-Paths -Expected 0    
}

function Test-TaskForceBeta {
    [CmdletBinding()]
    param()

    return "$env:APPDATA\TS3Client\plugins\TFAR_win64.dll",
    "$env:APPDATA\TS3Client\plugins\TFAR_win32.dll" | Test-Paths -Expected 2
}

function Test-TeamspeakStatus {
    [CmdletBinding()]
    Param()

    $Exe = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 'ts3client_win64' } else { 'ts3client_win32' }
    $Count = (Get-Process -Name $Exe -ErrorAction Ignore | Measure-Object).Count
    Write-Verbose "$Exe.exe : $Count processes running"
    return 0 -eq $Count
}

function  Test-TaskForceStatus {
    [CmdletBinding()]
    param ()
    
    return (Test-TaskForceLegacy) -and (Test-TaskForceBeta)
}

function Remove-TaskForceLegacy {
    [CmdletBinding()]
    Param()

    "$env:APPDATA\TS3Client\plugins\task_force_radio_win64.dll",
    "$env:APPDATA\TS3Client\plugins\task_force_radio_win32.dll" | ForEach-Object {
        Remove-Item $_ -ErrorAction Ignore
        Write-Verbose "$_ removed"
    }
}

function Expand-TaskForceBeta {
    [CmdletBinding()]
    Param(
        [string] $PluginSource
    )

    $PluginPath = Split-Path -Parent $PluginSource
    $PluginZip = "$PluginPath\task_force_radio.zip"
    Copy-Item $PluginSource $PluginZip
    Expand-Archive -Path $PluginZip -DestinationPath "$env:APPDATA\TS3Client" -Force
    Remove-Item "$env:APPDATA\TS3Client\package.ini" -ErrorAction Ignore
    Remove-Item $PluginZip -ErrorAction Ignore
}


function Write-Preset {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [object[]]$Mods,
        [string]$Name
    )
    Begin {
        $PresetDate = Get-Date -Format "o"
        $File = "$env:LOCALAPPDATA\Arma 3 Launcher\Presets\$Name.preset2"
        if (Test-Path $File) { Remove-Item $File }
        Add-Content -Path $File '<?xml version="1.0" encoding="utf-8"?>'
        Add-Content -Path $File '<addons-presets>'
        Add-Content -Path $File "<last-update>$PresetDate</last-update>"
        Add-Content -Path $File '<published-ids>'
    }
    Process {
        $Mods | ForEach-Object {
            Write-Verbose $_.FullName
            Add-Content -Path $File "<id>local:$($_.FullName)</id>"            
        }
    }
    End {
        Add-Content -Path $File '</published-ids>'
        Add-Content -Path $File '<dlcs-appids />'
        Add-Content -Path $File '</addons-presets>'
    }
}
function Test-NodePath {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0)]
        [string]$Node
    )

    if (Test-Path $Node -ErrorAction SilentlyContinue) {
        Write-Verbose "$Node found"
        return $true
    }
    else {
        Write-Verbose "$Node not found"
        return $false
    }
}

function Test-NodePathAndPropertyValue {
    [CmdletBinding()]
    param(
        [string]$Node,
        [string]$PropertyName
    )

    if (-not (Test-NodePath $Node)) { 
        Write-Verbose "$Node not found"
        return $false; 
    }    
    $Property = Get-ItemProperty $Node -Name $PropertyName -ErrorAction Ignore
    if ($null -eq $Property) { 
        Write-Verbose "$Node.$PropertyName not found"
        return $false 
    }

    $Value = Get-ItemPropertyValue $Node -Name $PropertyName -ErrorAction Ignore
    if ($null -eq $Value) {
        Write-Verbose "$Node.$PropertyName has no value"
        return $false 
    }

    return Test-NodePath $Value
}

function Test-AppInstallation {
    [CmdletBinding()]
    param(
        [string]$Name,
        [string]$Node,
        [string]$Property,
        [switch]$IsWOW64
    )

    $RegistryPath = 'HKLM:\SOFTWARE'
    $IsWin64 = ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64')
    
    if ($IsWin64 -and $IsWOW64) {
        Write-Verbose 'Looking for a WOW64 application'
        $RegistryPath = "$RegistryPath\WOW6432Node"
    }
        
    $RegistryPath = "$RegistryPath\$Node"
    Write-Verbose "Searching for $RegistryPath.$Property"
    return Test-NodePathAndPropertyValue -Node $RegistryPath -Property $Property
}

<#
.SYNOPSIS
.DESCRIPTION
.PARAMETER x
.PARAMETER y
.INPUTS
.OUTPUTS
.EXAMPLE
.EXAMPLE
.EXAMPLE
.EXAMPLE
.LINK
.LINK
.NOTES
#>

function Write-InstallationStatus {
    [CmdletBinding()]
    param(
        [string]$Path = '.'
    )

    $Uninstall_Path = 'Microsoft\Windows\CurrentVersion\Uninstall'
    $status += Write-AppInstallationStatus -Name 'Steam' -Node 'Valve\Steam' -Property 'InstallPath' -IsWOW64
    $status += Write-AppInstallationStatus -Name 'Arma 3' -Node "$Uninstall_Path\Steam App 107410"
    $status += Write-AppInstallationStatus -Name 'Arma 3 Sync' -Node "$Uninstall_Path\{F097E7D7-D093-4394-9EED-43AFCCD12B7A}_is1" -IsWOW64
    $status += Write-AppInstallationStatus -Name 'TeamSpeak' -Node "$Uninstall_Path\TeamSpeak 3 Client"
    $status += Write-ModpackStatus -Path $Path
    $status += Write-TaskForceStatus

    if (0 -lt $status) {
        Write-Host -ForegroundColor Red "`n *** Your installation is incorrect *** `n"
        return $false
    }
    else {
        Write-Host -ForegroundColor Green "`n *** Your installation is valid *** `n"
        return $true
    }
}

<#
.SYNOPSIS
.DESCRIPTION
.PARAMETER x
.PARAMETER y
.INPUTS
.OUTPUTS
.EXAMPLE
.EXAMPLE
.EXAMPLE
.EXAMPLE
.LINK
.LINK
.NOTES
#>

function Install-Preset {
    [CmdletBinding()]
    param(
        [string]$Path,
        [string]$Name
    )

    if (-not(Test-Path $Path -PathType Container)) {
        throw "$Path not found"
    }
    Get-ChildItem -Path $Path -Recurse -Filter "@*" |
    Where-Object { -not ($_.FullName -like "*\Campaign\@*") } |
    Write-Preset -Name $Name -Verbose:($PSBoundParameters['Verbose'] -eq $true)
}


<#
.SYNOPSIS
.DESCRIPTION
.PARAMETER x
.PARAMETER y
.INPUTS
.OUTPUTS
.EXAMPLE
.EXAMPLE
.EXAMPLE
.EXAMPLE
.LINK
.LINK
.NOTES
#>

function Install-TaskForceAddon {
    [CmdletBinding()]
    Param(
        [string] $PluginSource
    )

    if (-not(Test-Path $PluginSource -PathType Leaf)) {
        throw "$PluginSource not found"
    }
    if (-not (Test-TeamspeakStatus)) {
        throw 'Please close Teamspeak before install'
    }
    if (-not(Test-TaskForceLegacy)) {
        Write-Verbose 'TFAR 0.x found'
        Remove-TaskForceLegacy 
    }
    Expand-TaskForceBeta -PluginSource $PluginSource
}