JRE-Modules.psm1

# JRE-Modules - Composite PowerShell Module
# This module loads all nested submodules from the JRE-Modules collection

Write-Verbose "Loading JRE-Modules composite module..."

# Modules are automatically loaded via NestedModules in the manifest
# No additional initialization needed at this time

$module = $ExecutionContext.SessionState.Module
$moduleName = if ($module -and $module.Name) { $module.Name } else { 'JRE-Modules' }

function Get-DisplayVersion {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Version,

        [string]$Prerelease
    )

    if ([string]::IsNullOrWhiteSpace($Prerelease)) {
        return $Version
    }

    return "$Version-$Prerelease"
}

function Compare-DisplayVersion {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Left,

        [Parameter(Mandatory = $true)]
        [string]$Right
    )

    $leftParts = $Left -split '-', 2
    $rightParts = $Right -split '-', 2

    $leftBase = $leftParts[0]
    $rightBase = $rightParts[0]

    $leftPre = if ($leftParts.Count -gt 1) { $leftParts[1] } else { $null }
    $rightPre = if ($rightParts.Count -gt 1) { $rightParts[1] } else { $null }

    $baseCompare = 0
    try {
        $leftSem = [System.Management.Automation.SemanticVersion]$leftBase
        $rightSem = [System.Management.Automation.SemanticVersion]$rightBase

        if ($leftSem -gt $rightSem) { $baseCompare = 1 }
        elseif ($leftSem -lt $rightSem) { $baseCompare = -1 }
    }
    catch {
        $leftVer = [version]$leftBase
        $rightVer = [version]$rightBase

        if ($leftVer -gt $rightVer) { $baseCompare = 1 }
        elseif ($leftVer -lt $rightVer) { $baseCompare = -1 }
    }

    if ($baseCompare -ne 0) {
        return $baseCompare
    }

    # Same base version: stable release is newer than prerelease.
    if ([string]::IsNullOrWhiteSpace($leftPre) -and [string]::IsNullOrWhiteSpace($rightPre)) { return 0 }
    if ([string]::IsNullOrWhiteSpace($leftPre)) { return 1 }
    if ([string]::IsNullOrWhiteSpace($rightPre)) { return -1 }

    return [string]::Compare($leftPre, $rightPre, $true)
}

$currentVersion = if ($module -and $module.Version) { [string]$module.Version } else { '0.0.0' }
$currentPrerelease = $null

if ($module -and $module.PrivateData -and $module.PrivateData.PSData) {
    $currentPrerelease = [string]$module.PrivateData.PSData.Prerelease
}

# If script module reports 0.0/0.0.0, fall back to manifest metadata.
if ($currentVersion -in @('0.0', '0.0.0')) {
    $moduleBase = if ($module -and $module.ModuleBase) { $module.ModuleBase } else { Split-Path -Parent $PSCommandPath }
    $manifestPath = Join-Path $moduleBase "$moduleName.psd1"

    if (Test-Path -LiteralPath $manifestPath) {
        try {
            $manifest = Test-ModuleManifest -Path $manifestPath -ErrorAction Stop
            if ($manifest -and $manifest.Version) {
                $currentVersion = [string]$manifest.Version
            }

            if ($manifest -and $manifest.PrivateData -and $manifest.PrivateData.PSData) {
                $currentPrerelease = [string]$manifest.PrivateData.PSData.Prerelease
            }
        }
        catch {
            # Keep existing values if manifest read fails.
        }
    }
}

$currentDisplayVersion = Get-DisplayVersion -Version $currentVersion -Prerelease $currentPrerelease
$includePrerelease = -not [string]::IsNullOrWhiteSpace($currentPrerelease)

$latestDisplayVersion = $null
try {
    if (Get-Command -Name Find-PSResource -ErrorAction SilentlyContinue) {
        $findPsResourceParams = @{
            Name        = $moduleName
            Repository  = 'PSGallery'
            ErrorAction = 'Stop'
        }

        if ($includePrerelease) {
            $findPsResourceParams['Prerelease'] = $true
        }

        $latest = Find-PSResource @findPsResourceParams | Select-Object -First 1
        if ($null -ne $latest) {
            $latestPrerelease = $null

            if ($latest.PSObject.Properties.Match('Prerelease').Count -gt 0) {
                $latestPrerelease = [string]$latest.Prerelease
            }

            $latestDisplayVersion = Get-DisplayVersion -Version ([string]$latest.Version) -Prerelease $latestPrerelease
        }
    }
    elseif (Get-Command -Name Find-Module -ErrorAction SilentlyContinue) {
        $findModuleParams = @{
            Name        = $moduleName
            Repository  = 'PSGallery'
            ErrorAction = 'Stop'
        }

        if ($includePrerelease) {
            $findModuleParams['AllowPrerelease'] = $true
        }

        $latest = Find-Module @findModuleParams
        if ($null -ne $latest) {
            $latestPrerelease = $null
            if ($latest.AdditionalMetadata -and $latest.AdditionalMetadata.ContainsKey('Prerelease')) {
                $latestPrerelease = [string]$latest.AdditionalMetadata['Prerelease']
            }

            $latestDisplayVersion = Get-DisplayVersion -Version ([string]$latest.Version) -Prerelease $latestPrerelease
        }
    }
}
catch {
    $latestDisplayVersion = $null
}

$updateAvailable = $false
if (-not [string]::IsNullOrWhiteSpace($latestDisplayVersion)) {
    $updateAvailable = (Compare-DisplayVersion -Left $latestDisplayVersion -Right $currentDisplayVersion) -gt 0
}

Write-Host ("=" * 88) -ForegroundColor Cyan
Write-Host "JRE-Modules imported. Run 'Get-Command -Module JRE-Modules' and 'Get-Help <CommandName> -Detailed' for detailed information on available commands." -ForegroundColor Green
Write-Host "Most modules should also have a help function (JRE-KaliHelp, JRE-AzureDetonateVmHelp, etc.)" -ForegroundColor Green
if ($updateAvailable) {
    Write-Host ("Update available: {0} -> {1}" -f $currentDisplayVersion, $latestDisplayVersion) -ForegroundColor Yellow
    $updateCmd = if ($latestDisplayVersion -like '*-*') { "Update-Module -Name $moduleName -AllowPrerelease" } else { "Update-Module -Name $moduleName" }
    Write-Host "Run '$updateCmd' to get the latest version." -ForegroundColor Yellow
    Write-Host "You will need to re-import the module with the '-Force' parameter after updating to load the new version." -ForegroundColor Yellow
}
Write-Host ("=" * 88) -ForegroundColor Cyan

Write-Verbose "JRE-Modules composite module loaded successfully."