Private/scriptFunctions.ps1

# Send automated key strokes
function Send-Key {
    Param(
        [String] $WindowTitle,
        [String[]]$Key
    )

    Begin {
        Add-Type -AssemblyName System.Windows.Forms, Microsoft.VisualBasic
    }
    
    Process {
        $procId = (Get-Process | Where-Object { $_.MainWindowTitle -Match $WindowTitle }).Id
        If ($procId) {
            [Microsoft.VisualBasic.Interaction]::AppActivate($procId)
            ForEach ($Press in $Key) {
                [System.Windows.Forms.SendKeys]::SendWait($Press)
            }
        }
    }
}

# Graphical countdown timer
function Start-Countdown {
    Param(
        [Int32]$Seconds,
        [string]$Message
    )
    ForEach ($Count in (1..$Seconds))
    {   Write-Progress -Id 1 -Activity $Message -Status "Waiting for $Seconds seconds, $($Seconds - $Count) left" -PercentComplete (($Count / $Seconds) * 100)
        Start-Sleep -Seconds 1
    }
    Write-Progress -Id 1 -Activity $Message -Status "Completed" -PercentComplete 100 -Completed
}

# Get available Java information
function getAvailableJava {
    $latestReleases = Invoke-RestMethod -Uri "https://api.github.com/repos/adoptium/temurin17-binaries/releases"
    $latestReleases = $latestReleases | Where-Object { $_.prerelease -eq $False } | Sort-Object -Property published_at | Select-Object -Last 1
    $availableJavaVersion = $latestReleases.name -replace "jdk-", "" -replace "\+", "."
    $latestRelease = $latestReleases.assets | Where-Object { $_.browser_download_url -like '*jre_x64*msi' }
    $javaURL = $latestRelease.browser_download_url
    
    $javaInfo = [PSCustomObject]@{
        availableJavaVersion = $availableJavaVersion
        javaURL = $javaURL
    }

    return $javaInfo
}

# Get available Unifi information
function getAvailableUnifi {
    $latestReleases = Invoke-RestMethod -Uri "https://download.svc.ui.com/v1/software-downloads"
    $latestReleases = $latestReleases.downloads | Where-Object { $_.platform -eq "windows" -and $_.name -like "UniFi Network Application*"} | Sort-Object -Property date_published | Select-Object -Last 1
    $availableUnifiVersion = $latestReleases.version
    $unifiURL = $latestReleases.file_url

    $unifiInfo = [PSCustomObject]@{
        availableUnifiVersion = $availableUnifiVersion
        unifiURL = $unifiURL
    }

    return $unifiInfo
}

# Download and Install Java
function installJava {
    param (
        [string]$javaURL
    )
    Start-BitsTransfer -Source $javaURL -Destination "$PSScriptRoot\java_installer.msi"
    Start-Process msiexec.exe "/i `"$PSScriptRoot\java_installer.msi`" ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome,FeatureOracleJavaSoft INSTALLDIR=`"C:\Program Files\Eclipse Adoptium\`" /quiet" -Wait
    Remove-Item -Path "$PSScriptRoot\java_installer.msi" -Force
    Write-Warning "Java had to be installed or upgaded. A reboot will be required to start the contoller."
}

# Uninstall Java
function uninstallJava{
    $installedJavaApp = Get-WmiObject -Class Win32_Product | Where-Object{$_.Name -like "Eclipse Temurin*"} | Select-Object -ExpandProperty IdentifyingNumber
    Start-Process msiexec.exe "/x $installedJavaApp /norestart /qn" -Wait
}

# Check if Java is installed and up to date, if not, install or upgrade
function getJava {
    $javaInfo = getAvailableJava
    $availableJavaVersion = $javaInfo.availableJavaVersion
    $javaURL = $javaInfo.javaURL

    if (Test-Path "HKLM:\SOFTWARE\Eclipse Adoptium\JRE\"){
        $installedJavaVersion = Get-ChildItem "HKLM:\SOFTWARE\Eclipse Adoptium\JRE\" | Split-Path -Leaf
        if ($installedJavaVersion -ne $availableJavaVersion) {
            Write-Host "Java out of date. Upgrading Java..."
            uninstallJava
            installJava -javaURL $javaURL
        } else {
            Write-Host "Java up to date."
        }
    } else {
        Write-Host "Java not installed. Installing Java..."
        InstallJava -javaURL $javaURL
    }    
}

# Download and Install Unifi Controller
function installUnifi {
    param (
        [string]$unifiURL,
        [boolean]$isUpgrade
    )

    # Install or upgrade Java
    getJava

    # Download Unifi Controller
    Start-BitsTransfer -Source $unifiURL -Destination $PSScriptRoot

    # If Unifi is installed, stop and uninstall service before upgrading
    if ($isUpgrade) {
        unifiService -action stop
        unifiService -action uninstall
    }

    # Install Unifi Controller
    Write-Host "Installing Unifi Contoller..."
    Start-Process -FilePath "$PSScriptRoot\UniFi-installer.exe" -ArgumentList "/S", "/D=$unifiDirectory" -Wait
    Remove-Item -Path "$PSScriptRoot\UniFi-installer.exe" -Force
    
    # Remove shortcut
    $desktopPath = [Environment]::GetFolderPath('Desktop')
    Remove-Item -Path "$desktopPath\UniFi.lnk" -Force

    # Open Unifi Controller (Java App)
    #Write-Host "Starting Unifi Controller with Java app to initialize database..."
    #. "$unifiDirectory\jre\bin\javaw.exe" -jar "$unifiDirectory\lib\ace.jar" ui

    # Wait for controller to load
    #Start-Countdown -Seconds 100 -Message "Awaiting completion of UniFi Controller loading"

    # Close Unifi Controller (Java App)
    #Send-Key -WindowTitle "UniFi Network Server" -Key '%{F4}'
    #Send-Key -WindowTitle "UniFi Network Server" -Key '{ENTER}'

    # Install and start Unifi Service
    unifiService -action install
    unifiService -action start

}

# Check if Unifi Controller is installed and up to date, if not, install or upgrade
function getUnifi {
    $unifiInfo = getAvailableUnifi
    $unifiURL = $unifiInfo.unifiURL
    $availableUnifiVersion = $unifiInfo.availableUnifiVersion

    if (Test-Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Ubiquiti UniFi"){
        $installedVersionNumber = Get-ItemPropertyValue "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Ubiquiti UniFi" -Name Version
        if ($installedVersionNumber -ne $availableUnifiVersion){
            Write-Host "Unifi installed but not up to date."
            Write-Host "Upgrading Unifi..."
            installUnifi -unifiURL $unifiURL -isUpgrade $true
        } else {
            Write-Host "Unifi installed and up to date."
        }
    } else {
        Write-Host "Unifi not installed."
        installUnifi -unifiURL $unifiURL -isUpgrade $false
    } 
}

# Unifi service control
function unifiService {
    param (
        [string]$action
    )
    switch ($action) {
        "install" {
            Write-Host "Installing Unifi Service..."
            . "$unifiDirectory\jre\bin\java.exe" -jar "$unifiDirectory\lib\ace.jar" installsvc | Out-Null
        }
        "uninstall" {
            Write-Host "Uninstalling Unifi Service..."
            . "$unifiDirectory\jre\bin\java.exe" -jar "$unifiDirectory\lib\ace.jar" uninstallsvc | Out-Null
        }
        "start" {
            Write-Host "Starting Unifi Service..."
            . "$unifiDirectory\jre\bin\java.exe" -jar "$unifiDirectory\lib\ace.jar" startsvc | Out-Null
        }
        "stop" {
            Write-Host "Stopping Unifi Service..."
            . "$unifiDirectory\jre\bin\java.exe" -jar "$unifiDirectory\lib\ace.jar" stopsvc | Out-Null
        }
        Default {}
    }
}