public/path/Add-EnvironmentPath.ps1

#requires -Version 3
Set-StrictMode -Version Latest

function Add-EnvironmentPath{
    <#
    .SYNOPSIS
        Adds the specified PATH Environment Variable.
    .DESCRIPTION
        The Add-EnvironmentPath cmdlet determines whether all elements of the PATH Environment Variable exist. It returns $True if all elements exist and $False if any are missing.
    .EXAMPLE
        PS C:\> Add-EnvironmentPath "C:\Program Files\Java\jdk-17.0.2"
        PS C:\> Add-EnvironmentPath -EnvironmentVariableName "GOPATH" -Path "C:\Users\example\gocode"
    #>

    [CmdletBinding(DefaultParametersetName="Path")]
    Param(
        # Specifies a Path Name of the PATH Environment Variable.
        [Parameter(Position=0,ParameterSetName="Path", ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Parameter(Position=0,ParameterSetName="AddFirst", ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Parameter(Position=0,ParameterSetName="SpecifyPlace", ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string[]]$Path
        ,
        # Add first
        [Parameter(ParameterSetName="AddFirst")]
        [switch]$Prepend
        ,
        # Add befor Name pattern
        [Parameter(ParameterSetName="SpecifyPlace")]
        [string[]]$Befor
        ,
        # Add after Name pattern
        [Parameter(ParameterSetName="SpecifyPlace")]
        [string[]]$After
        ,
        # Specifies a Name of the Environment Variable.
        [string]$EnvironmentVariableName = "PATH"
    )
    Begin{

        function seach_index($arr, $seach_value, $last){
            $hitIndex = -1
            if($last){
                for ($i = $arr.Count - 1; 0 -le $i; $i--) {
                    if($arr[$i].Path -ilike $seach_value){
                        $hitIndex = $i
                        break
                    }
                }
            }else{
                for ($i = 0; $i -lt $arr.Count; $i++) {
                    if($arr[$i].Path -ilike $seach_value){
                        $hitIndex = $i
                        break
                    }
                }
            }
            $hitIndex
        }

    }
    Process{

        $parameterSetName = $PsCmdlet.ParameterSetName
        $paths = New-Object System.Collections.ArrayList
        $paths.AddRange(@(Get-InternalEnvPathArray $EnvironmentVariableName))

        $Path | ForEach-Object {

            $pathC = New-InternalEnvValue $_

            if([string]::IsNullOrWhiteSpace($pathC.Path)){
                return
            }

            switch ($parameterSetName) {
                "Path" {
                    $paths.Insert($paths.Count, $pathC)
                }
                "AddFirst" {
                    $paths.Insert(0, $pathC)
                }
                "SpecifyPlace" {

                    $befInsertIndex = $paths.Count

                    if($Befor){
                        foreach ($bf in $Befor) {
                            if(-not [string]::IsNullOrEmpty($bf)){
                                $hitIndex = seach_index $paths $bf $true
                                if($hitIndex -ne -1){
                                    $befInsertIndex = [System.Math]::Min($befInsertIndex, $hitIndex)
                                }
                            }
                        }
                    }

                    $aftInsertIndex = 0

                    if($After){
                        foreach ($af in $After) {
                            if(-not [string]::IsNullOrEmpty($af)){
                                $hitIndex = seach_index $paths $af $true
                                if($hitIndex -ne -1){
                                    $aftInsertIndex = [System.Math]::Max($aftInsertIndex, $hitIndex + 1)
                                }
                            }
                        }
                    }

                    if($befInsertIndex -lt $aftInsertIndex){
                        Write-Warning -Message "Conflict add position Befor($befInsertIndex) < After($aftInsertIndex)"
                    }else{
                        $paths.Insert($aftInsertIndex, $pathC)
                    }

                }
            }
        }

        Set-InternalEnvPathArray -Path $paths -EnvironmentVariableName $EnvironmentVariableName

    }
}