Scripts/Installation.ps1


class CmxInstallation
{
    [string] GetFolder()
    {
        <#
        .SYNOPSIS
        Gets the path to the official powershell installation folder for the current user.
        #>


        return [Environment]::GetFolderPath('MyDocuments') + '\WindowsPowerShell\Modules\CmxModule'
    }

    [PsCustomObject] GetSymlinkFolder()
    {
        <#
        .SYNOPSIS
        Gets the symlink folder. The symlink folder has the name "LATEST".
        #>


        [PsCustomObject]$result = @{
            ExistsFolder = $false
            ExistsTarget = $false
            Target = $null
            Path = $null
        }
        $installationDir = $this.GetFolder()
        Write-Host "InstallationDir: $installationDir"
        $latestPath = $installationDir + '\LATEST'
        $result.Path = $latestPath
        $latestFolder = Get-Item $latestPath
        Write-Host "LatestPath: $latestFolder"
        if(Test-Path -Path $latestFolder -PathType Container)
        {
            Write-Verbose "The item is a folder."
            $result.ExistsFolder = $true
            if($latestFolder.LinkType -eq "SymbolicLink")
            {
                Write-Verbose "The item is a symbolic link."
                $result.ExistsTarget = $true;
                [string]$result.Target = $latestFolder.Target
            }
        }
        return $result
    }

    [PsCustomObject] GetVersionFolder()
    {
        <#
        .SYNOPSIS
        Gets the version folder with the highest version.
        #>


        [PsCustomObject]$result = @{
            ExistsPath = $false
            Version = $null
            Path = $null
        }
        $installationDir = $this.GetFolder()
        $refVersion = [System.Version]::new()
        $latestVersion = (Get-ChildItem $installationDir).Name | Where-Object { $true -eq [System.Version]::TryParse($_,[ref]$refVersion) } | Foreach-Object { [System.Version]::Parse($_) } | Sort-Object | Select-Object -Last 1
    
        $latestVersionFolder = $latestVersion.ToString()
        if($null -ne $latestVersionFolder)
        {
            Write-Host "Version: $latestVersionFolder"
            $result.Version = $latestVersionFolder
            $pathToLatestModule = $installationDir + '\' + $latestVersionFolder
            Write-Host "Path: $pathToLatestModule"
            $result.Path = $pathToLatestModule
            if(Test-Path -Path $pathToLatestModule -PathType Container)
            {
                $result.ExistsPath = $true
            }
        }
        return $result
    }

    [bool] IsSymlinkFolderUpdateToDate()
    {
        <#
        .SYNOPSIS
        Checks whether the symlink folder points to the version folder with the highest version.
        #>


        $symlink = $this.GetSymlinkFolder()
        if($symlink.ExistsFolder -and $symlink.ExistsTarget)
        {
            $versionFolder = $this.GetVersionFolder()
            if($versionFolder.ExistsPath)
            {
                $resolvedVersionPath = [System.IO.Path]::GetFullPath($versionFolder.Path)
                Write-Host "Version Path: $resolvedVersionPath"
                $resolvedSymlinkTarget = [System.IO.Path]::GetFullPath($symlink.Target)
                Write-Host "Symlink Target: $resolvedSymlinkTarget"
                return $resolvedVersionPath -eq $resolvedSymlinkTarget
            }
        }
        return $false
    }

    [bool] DeleteSymlinkFolder()
    {
        <#
        .SYNOPSIS
        Deletes the symlink folder.
        #>


        $symlink = $this.GetSymlinkFolder()
        if($symlink.ExistsFolder)
        {
            $latestItem = Get-Item $symlink.Path
            $latestItem.Delete()
            return $true
        }
        return $false  
    }

    CreateSymlinkFolder()
    {
        <#
        .SYNOPSIS
        Creates a new symlink folder which points to the version folder with the highest version.
        #>


        $versionFolder = $this.GetVersionFolder()
        if($versionFolder.ExistsPath)
        {
            $target = [System.IO.Path]::GetFullPath($versionFolder.Path)
            Write-Host "Target: $target"

            $installationDir = $this.GetFolder()
            Write-Host "InstallationDir: $installationDir"
            $source = $installationDir + '\LATEST'

            New-Item -ItemType SymbolicLink -Path $source -Target $target | Out-Null
        }   
    }

    static UpdateSymlinkFolder()
    {
        <#
        .SYNOPSIS
        Checks whether a symlink folder exists and whether the symlink folder points to the version
        folder with the highest version. If not, then deletes the current and creates a new symlink
        folder.
        #>


        $instance = [CmxInstallation]::new()

        if(-not ($instance.IsSymlinkFolderUpdateToDate()))
        {
            Write-Host "The symlink folder is out of date."
            Write-Host "Try to update the symlink folder."
            $instance.DeleteSymlinkFolder
            $instance.CreateSymlinkFolder
            $result = $instance.IsSymlinkFolderUpdateToDate
            Write-Host "Succeeded to update the symlink folder: $result"
            return
        }
        Write-Host "The symlink folder is already up to date."
    }
}

function CmxInstallationUpdateSymlinkFolder
{
    <#
    .SYNOPSIS
    Checks whether a symlink folder exists and whether the symlink folder points to the version
    folder with the highest version. If not, then deletes the current and creates a new symlink
    folder.
    #>


    [CmdletBinding()]
    param()

    [CmxInstallation]::UpdateSymlinkFolder()
}