ColorScripts-Enhanced.psm1


#Requires -Version 5.1

# ColorScripts-Enhanced Module
# High-performance colorscripts with intelligent caching

# Module state
$script:ModuleRoot = $null
$script:ScriptsPath = $null
$script:MetadataPath = $null
$script:MetadataCache = $null
$script:MetadataLastWriteTime = $null
$script:Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($false)
$script:CacheDir = $null
$script:CacheInitialized = $false
$script:ScriptInventory = $null
$script:ScriptInventoryStamp = $null
$script:ScriptInventoryInitialized = $false
$script:ScriptInventoryRecords = $null
$script:ConfigurationRoot = $null
$script:ConfigurationPath = $null
$script:ConfigurationData = $null
$script:ConfigurationInitialized = $false
$script:LocalizationInitialized = $false
$script:LocalizationDetails = $null
$script:Messages = $null
$script:ShouldProcessOverride = $null
$script:DefaultConfiguration = @{
    Cache   = @{
        Path = $null
    }
    Startup = @{
        AutoShowOnImport = $false
        ProfileAutoShow  = $true
        DefaultScript    = $null
    }
}

$script:IsWindows = $IsWindows
$script:IsMacOS = $IsMacOS
$script:PowerShellMajorVersion = $PSVersionTable.PSVersion.Major

$traceSetting = $env:COLOR_SCRIPTS_ENHANCED_TRACE
$script:ModuleTraceEnabled = $false
$script:ModuleTraceUseVerbose = $false
$script:ModuleTraceUseDebug = $false
$script:ModuleTraceUseFile = $false
$script:ModuleTraceFile = $null
$script:ModuleTraceWriteFailureNotified = $false

if (-not [string]::IsNullOrWhiteSpace($traceSetting)) {
    $script:ModuleTraceEnabled = $true
    $tokens = ($traceSetting -split '[,;]') | ForEach-Object { $_.Trim() } | Where-Object { $_ }
    if (-not $tokens) {
        $tokens = @($traceSetting.Trim())
    }

    foreach ($token in $tokens) {
        switch -Regex ($token) {
            '^(?i)(1|true|yes|on)$' { $script:ModuleTraceUseVerbose = $true; continue }
            '^(?i)verbose$' { $script:ModuleTraceUseVerbose = $true; continue }
            '^(?i)debug$' { $script:ModuleTraceUseDebug = $true; continue }
            '^(?i)file$' { $script:ModuleTraceUseFile = $true; continue }
            '^(?i)path:(?<path>.+)$' {
                $script:ModuleTraceUseFile = $true
                if (-not [string]::IsNullOrWhiteSpace($Matches['path'])) {
                    $script:ModuleTraceFile = $Matches['path']
                }
                continue
            }
            default {
                $resolvedPath = $null
                try {
                    $resolvedPath = [System.IO.Path]::GetFullPath($token)
                }
                catch {
                    $resolvedPath = $null
                }

                if ($resolvedPath -and ($token.Contains('\') -or $token.Contains('/') -or $token -match '^[A-Za-z]:')) {
                    $script:ModuleTraceUseFile = $true
                    $script:ModuleTraceFile = $resolvedPath
                }
                else {
                    $script:ModuleTraceUseVerbose = $true
                }
            }
        }
    }
}

if ($script:ModuleTraceEnabled) {
    if (-not ($script:ModuleTraceUseVerbose -or $script:ModuleTraceUseDebug -or $script:ModuleTraceUseFile)) {
        $script:ModuleTraceUseVerbose = $true
    }

    if ($script:ModuleTraceUseFile -and -not $script:ModuleTraceFile) {
        $script:ModuleTraceFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'cs-module-root-debug.log'
    }

    if ($script:ModuleTraceUseFile -and $script:ModuleTraceFile) {
        try {
            $traceDirectory = Split-Path -Path $script:ModuleTraceFile -Parent
            if ($traceDirectory -and -not (Test-Path -LiteralPath $traceDirectory)) {
                New-Item -Path $traceDirectory -ItemType Directory -Force | Out-Null
            }
        }
        catch {
            $script:ModuleTraceUseFile = $false
            Write-Verbose ("Unable to prepare trace directory '{0}': {1}" -f $script:ModuleTraceFile, $_.Exception.Message)
        }
    }
}

function Write-ModuleTrace {
    param(
        [Parameter(Mandatory)]
        [string]$Message
    )

    if (-not $script:ModuleTraceEnabled) {
        return
    }

    if ($script:ModuleTraceUseDebug) {
        Write-Debug $Message
    }

    if ($script:ModuleTraceUseVerbose) {
        Write-Verbose $Message
    }

    if ($script:ModuleTraceUseFile -and $script:ModuleTraceFile) {
        try {
            $Message | Out-File -FilePath $script:ModuleTraceFile -Encoding utf8 -Append
        }
        catch {
            if (-not $script:ModuleTraceWriteFailureNotified) {
                $script:ModuleTraceWriteFailureNotified = $true
                Write-Verbose ("Trace logging to '{0}' failed: {1}" -f $script:ModuleTraceFile, $_.Exception.Message)
            }
        }
    }
}

Write-ModuleTrace ("--- Import begin: {0} ---" -f (Get-Date -Format o))

$moduleInfo = $ExecutionContext.SessionState.Module
$moduleRootCandidates = @()

if ($moduleInfo) {
    if ($moduleInfo.ModuleBase) {
        $moduleRootCandidates += $moduleInfo.ModuleBase
    }

    if ($moduleInfo.Path) {
        $moduleRootCandidates += (Split-Path -Path $moduleInfo.Path -Parent)
    }
}

if ($PSScriptRoot) {
    $moduleRootCandidates += $PSScriptRoot
}

$availableModule = Get-Module -ListAvailable -Name 'ColorScripts-Enhanced' | Select-Object -First 1
if ($availableModule -and $availableModule.ModuleBase) {
    $moduleRootCandidates += $availableModule.ModuleBase
}

$environmentRoot = $env:COLOR_SCRIPTS_ENHANCED_MODULE_ROOT
if ($environmentRoot) {
    $moduleRootCandidates += $environmentRoot
}

Write-ModuleTrace ("Initial module root candidates: {0}" -f ($moduleRootCandidates -join ';'))

$resolvedCandidates = @()
foreach ($candidate in $moduleRootCandidates) {
    if ([string]::IsNullOrWhiteSpace($candidate)) { continue }
    try {
        $resolvedCandidate = (Resolve-Path -LiteralPath $candidate -ErrorAction Stop).ProviderPath
        if ($resolvedCandidate -and ($resolvedCandidates -notcontains $resolvedCandidate)) {
            $resolvedCandidates += $resolvedCandidate
        }
    }
    catch {
        continue
    }
}

$moduleRootCandidates = $resolvedCandidates
Write-ModuleTrace ("Resolved module root candidates: {0}" -f ($moduleRootCandidates -join ';'))

$cultureFallback = @()
try {
    $currentCulture = [System.Globalization.CultureInfo]::CurrentUICulture
}
catch {
    $currentCulture = $null
}

while ($currentCulture -and $currentCulture.Name -and -not ($cultureFallback -contains $currentCulture.Name)) {
    $cultureFallback += $currentCulture.Name
    if ($currentCulture.Parent -and $currentCulture.Parent.Name -and $currentCulture.Parent.Name -ne $currentCulture.Name) {
        $currentCulture = $currentCulture.Parent
    }
    else {
        break
    }
}

$cultureFallback += 'en-US'
$cultureFallback += 'en'
$cultureFallback = $cultureFallback | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique

$script:EmbeddedDefaultMessages = ConvertFrom-StringData @'
# ColorScripts-Enhanced Localized Messages
# English (en-US) - Default Language
 
# Error Messages
UnableToPrepareCacheDirectory = Unable to prepare cache directory '{0}': {1}
FailedToParseConfigurationFile = Failed to parse configuration file at '{0}': {1}. Using defaults.
UnableToResolveCachePath = Unable to resolve cache path '{0}'.
ConfiguredCachePathInvalid = Configured cache path '{0}' could not be resolved. Falling back to default locations.
UnableToResolveOutputPath = Unable to resolve output path '{0}'.
UnableToDetermineConfigurationDirectory = Unable to determine configuration directory for ColorScripts-Enhanced.
ConfigurationRootCouldNotBeResolved = Configuration root could not be resolved.
UnableToResolveProfilePath = Unable to resolve profile path '{0}'.
FailedToExecuteColorscript = Failed to execute colorscript '{0}': {1}
FailedToBuildCacheForScript = Failed to build cache for $($selection.Name).
CacheBuildFailedForScript = Cache build failed for {0}: {1}
ScriptAlreadyExists = Script '{0}' already exists. Use -Force to overwrite.
ProfilePathNotDefinedForScope = Profile path for scope '{0}' is not defined.
ScriptPathNotFound = Script path not found.
ScriptExitedWithCode = Script exited with code {0}.
CacheFileNotFound = Cache file not found.
NoChangesApplied = No changes applied.
UnableToRetrieveFileInfo = Unable to retrieve file info for '{0}': {1}
UnableToReadCacheInfo = Unable to read cache info for '{0}': {1}
 
# Warning Messages
NoColorscriptsFoundMatchingCriteria = No colorscripts found matching the specified criteria.
NoScriptsMatchedSpecifiedFilters = No scripts matched the specified filters.
NoColorscriptsAvailableWithFilters = No colorscripts available with the specified filters.
NoColorscriptsFoundInScriptsPath = No colorscripts found in $script:ScriptsPath
NoScriptsSelectedForCacheBuild = No scripts selected for cache build.
ScriptNotFound = Script not found: {0}
ColorscriptNotFoundWithFilters = Colorscript '{0}' not found with the specified filters.
CachePathNotFound = Cache path not found: {0}
NoCacheFilesFound = No cache files found at {0}.
ProfileUpdatesNotSupportedInRemote = Profile updates are not supported in remote sessions.
ScriptSkippedByFilter = Script '{0}' does not satisfy the specified filters and will be skipped.
 
# Status Messages
DisplayingColorscripts = `nDisplaying $totalCount colorscripts...
CacheBuildSummary = `nCache Build Summary:
FailedScripts = `nFailed scripts:
TotalScriptsProcessed = `nTotal scripts processed: $totalCount
DisplayingContinuously = Displaying continuously (Ctrl+C to stop)`n
FinishedDisplayingAll = Finished displaying all $totalCount colorscripts!
Quitting = `nQuitting...
CurrentIndexOfTotal = [$currentIndex/$totalCount]
FailedScriptDetails = - $($failure.Name): $($failure.StdErr)
MultipleColorscriptsMatched = Multiple colorscripts matched the provided name pattern(s): {0}. Displaying '{1}'.
StatusCached = Cached
StatusSkippedUpToDate = Skipped (up-to-date)
StatusSkippedByUser = Skipped by user
StatusFailed = Failed
StatusUpToDateSkipped = Up-to-date (skipped)
 
# Interactive Messages
PressSpacebarToContinue = Press [Spacebar] to continue to next, [Q] to quit`n
PressSpacebarForNext = Press [Spacebar] for next, [Q] to quit...
 
# Success Messages
ProfileSnippetAdded = [OK] Added ColorScripts-Enhanced startup snippet to {0}
ProfileAlreadyContainsSnippet = Profile already contains ColorScripts-Enhanced snippet.
ProfileAlreadyImportsModule = Profile already imports ColorScripts-Enhanced.
ModuleLoadedSuccessfully = ColorScripts-Enhanced module loaded successfully.
RemoteSessionDetected = Remote session detected.
ProfileAlreadyConfigured = Profile already configured.
ProfileSnippetAddedMessage = ColorScripts-Enhanced profile snippet added.
 
# Help/Instruction Messages
SpecifyNameToSelectScripts = Specify -Name to select scripts when -All is explicitly disabled.
SpecifyAllOrNameToClearCache = Specify -All or -Name to clear cache entries.
UsePassThruForDetailedResults = Use -PassThru to see detailed results`n
 
# Miscellaneous
'@


if (-not $script:LocalizationSyncRoot) { $script:LocalizationSyncRoot = New-Object System.Object }
if (-not $script:ConfigurationSyncRoot) { $script:ConfigurationSyncRoot = New-Object System.Object }
if (-not $script:CacheSyncRoot) { $script:CacheSyncRoot = New-Object System.Object }
if (-not $script:MetadataSyncRoot) { $script:MetadataSyncRoot = New-Object System.Object }
if (-not $script:InventorySyncRoot) { $script:InventorySyncRoot = New-Object System.Object }
if (-not $script:DelegateSyncRoot) { $script:DelegateSyncRoot = New-Object System.Object }

$privateDirectory = Join-Path -Path $PSScriptRoot -ChildPath 'Private'
if (Test-Path -LiteralPath $privateDirectory) {
    Get-ChildItem -Path $privateDirectory -Filter '*.ps1' -File | Sort-Object Name | ForEach-Object {
        Write-ModuleTrace ("Loading private script: {0}" -f $_.Name)
        . $_.FullName
    }
}
else {
    Write-ModuleTrace ("Private script directory '{0}' was not found." -f $privateDirectory)
}

$localizationResult = Initialize-ColorScriptsLocalization -CandidateRoots ($moduleRootCandidates | Select-Object -Unique) -CultureFallbackOverride $cultureFallback
if ($localizationResult -and $localizationResult.ModuleRoot) {
    $script:ModuleRoot = $localizationResult.ModuleRoot
}
elseif (-not $script:ModuleRoot) {
    if ($PSScriptRoot) {
        $script:ModuleRoot = $PSScriptRoot
    }
    elseif ($moduleInfo -and $moduleInfo.ModuleBase) {
        $script:ModuleRoot = $moduleInfo.ModuleBase
    }
}

if ($script:ModuleRoot) {
    try {
        $resolvedRoot = (Resolve-Path -LiteralPath $script:ModuleRoot -ErrorAction Stop).ProviderPath
        if ($resolvedRoot) {
            $script:ModuleRoot = $resolvedRoot
        }
    }
    catch {
        Write-ModuleTrace ("Resolve-Path for module root failed: {0}" -f $_.Exception.Message)
    }

    $script:ScriptsPath = Join-Path -Path $script:ModuleRoot -ChildPath 'Scripts'
    $script:MetadataPath = Join-Path -Path $script:ModuleRoot -ChildPath 'ScriptMetadata.psd1'
    Write-ModuleTrace ("Module root finalized at {0}" -f $script:ModuleRoot)
}
else {
    Write-ModuleTrace 'Module root could not be determined; relative operations may fail.'
}

$publicDirectory = Join-Path -Path $PSScriptRoot -ChildPath 'Public'
if (Test-Path -LiteralPath $publicDirectory) {
    Get-ChildItem -Path $publicDirectory -Filter '*.ps1' -File | Sort-Object Name | ForEach-Object {
        Write-ModuleTrace ("Loading public script: {0}" -f $_.Name)
        . $_.FullName
    }
}
else {
    Write-ModuleTrace ("Public script directory '{0}' was not found; exported functions may be unavailable." -f $publicDirectory)
}

Initialize-SystemDelegateState

Export-ModuleMember -Function @(
    'Show-ColorScript',
    'Get-ColorScriptList',
    'New-ColorScriptCache',
    'Clear-ColorScriptCache',
    'Add-ColorScriptProfile',
    'Get-ColorScriptConfiguration',
    'Set-ColorScriptConfiguration',
    'Reset-ColorScriptConfiguration',
    'Export-ColorScriptMetadata',
    'New-ColorScript'
) -Alias @('scs', 'Update-ColorScriptCache', 'Build-ColorScriptCache')

if ($script:Messages -and $script:Messages.ContainsKey('ModuleLoadedSuccessfully')) {
    Write-Verbose $script:Messages.ModuleLoadedSuccessfully
}
else {
    Write-Verbose 'ColorScripts-Enhanced module loaded successfully.'
}

try {
    Invoke-ColorScriptsStartup
}
catch {
    Write-ModuleTrace ("Startup invocation failure: {0}" -f $_.Exception.Message)
    Write-Verbose ("Auto-show on import skipped: {0}" -f $_.Exception.Message)
}

Write-ModuleTrace ("--- Import complete: {0} ---" -f (Get-Date -Format o))