$ErrorActionPreference = 'Stop';

$versionValuePath = 'HKLM:\SOFTWARE\Wow6432Node\Flexera Software\FlexNet Manager Platform\FNMPVersion';
$componentsKeyPath = 'HKLM:\SOFTWARE\Wow6432Node\Flexera Software\FlexNet Manager Platform\Features\CurrentVersion';
$installDirectoryValuePath = 'HKLM:\SOFTWARE\Wow6432Node\ManageSoft Corp\ManageSoft\InstallDir'
$beaconInstallDirectoryValuePath = 'HKLM:\SOFTWARE\Wow6432Node\ManageSoft Corp\ManageSoft\ETDPInstallDir';
$importXmlDirectoryValuePath = 'HKLM:\SOFTWARE\Wow6432Node\ManageSoft Corp\ManageSoft\Compliance\CurrentVersion\ImportXMLDirectory'
$processorStateDirectoryValuePath = 'HKLM:\SOFTWARE\Wow6432Node\ManageSoft Corp\ManageSoft\Compliance\CurrentVersion\BatchProcessor\ProcessorStateDirectory'
$loggingConfigurationDirectoryValuePath = 'HKLM:\SOFTWARE\Wow6432Node\ManageSoft Corp\ManageSoft\Compliance\CurrentVersion\LoggingBaseDirectory'

<# 
.Synopsis
Returns $true if the current process is running elevated.

.Outputs
System.Bool
#>
function Test-ProcessElevated() {
	$identity  = [System.Security.Principal.WindowsIdentity]::GetCurrent();
	$principal = New-Object System.Security.Principal.WindowsPrincipal($identity);
	return $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator);
}

<#
.Synopsis
Get the set of FNMS components installed on this server as an array.

.Outputs
System.String[]. An array of component names as strings.

.Description
The component list can include any of: 'BatchProcessor', 'BatchServer', 
'InventoryServer' and 'PresentationServer'.
#>
function Get-InstalledComponents() {
	
	$components = @();
	
	if (Test-Path $componentsKeyPath) {
		$components = @(Get-Item $componentsKeyPath | Select-Object -ExpandProperty Property);
	}
	else {
		Write-Error -Message 'No FNMS Platform features are installed on this server.'
	}
	
	return $components;
}

<#
.Synopsis
Check that the given FNMS component is installed

.Description
Asserts that the given FNMS component is installed, and throws an exception if it isn't.

.Parameter ComponentName
The name of the component to check. One of of: 'BatchProcessor', 'BatchServer', 
'InventoryServer' or 'PresentationServer'.
#>
function Assert-InstalledComponent {
	param (
		[ValidateSet('BatchProcessor', 'BatchServer', 'InventoryServer', 'PresentationServer')]
		[string]$ComponentName
	)
	
	if (-not (Test-InstalledComponent $ComponentName)) {
		Write-Error "The $ComponentName component is not installed on this server."
	} else {
		Write-Host "Found installed component $ComponentName";
	}
}

function Test-InstalledComponent {
	param (
		[ValidateSet('BatchProcessor', 'BatchServer', 'InventoryServer', 'PresentationServer')]
		[string]$ComponentName
	)
	$installedComponents = Get-InstalledComponents;
	
	return [bool]($installedComponents -icontains $ComponentName);
}

<#
.Synopsis
Get the current version number out of the registry. This should not be depended on
for the build number, just major and minor.
#>
function Get-InstalledVersion() {
	$keyPath = Split-Path -Parent $versionValuePath
	$valueName = Split-Path -Leaf $versionValuePath
	
	if (-not (Test-Path $keyPath)) {
		Write-Error -Message 'FNMS does not appear to be installed.'
	}
	
	if (@(Get-Item $keyPath | Select-Object -ExpandProperty Property | Where-Object { $_ -eq $valueName}).Count -ne 1) {
		Write-Error -Message 'FNMS version number not found in registry.'
	}
	
	return (Get-ItemProperty -Path $keyPath -Name $valueName  | Select-Object -ExpandProperty $valueName);
}

function Test-InstalledVersion {
	param (
		[string]$versionPrefix
	)
	$installedVersion = Get-InstalledVersion;
	
	return [bool]($installedVersion -ilike ($versionPrefix + '*'));
}

function Assert-InstalledVersion {
	param (
		[string]$versionPrefix
	)

	$installedVersion = Get-InstalledVersion;

	if (-not (Test-InstalledVersion $versionPrefix)) {
		Write-Error "This patch expected FNMS version '$($versionPrefix).*', but found '$installedVersion'. The patch will not apply."
	}
}

<#
.Synopsis
Get the file system path where FNMS components are installed.
#>
function Get-InstallationDirectory() {
	$keyPath = Split-Path -Parent $installDirectoryValuePath
	$valueName = Split-Path -Leaf $installDirectoryValuePath
	
	if (-not (Test-Path $keyPath)) {
		Write-Error -Message 'FNMS does not appear to be installed.'
	}
	
	if (@(Get-Item $keyPath | select -ExpandProperty Property | where { $_ -eq $valueName}).Count -ne 1) {
		Write-Error -Message 'FNMS installation directory not found in registry.'
	}
	
	return (Get-ItemProperty -Path $keyPath -Name $valueName  | select -ExpandProperty $valueName);
}


<#
.Synopsis
Get the file system path where FNMS Beacon components are installed.
#>
function Get-BeaconInstallationDirectory() {
	$keyPath = Split-Path -Parent $beaconInstallDirectoryValuePath
	$valueName = Split-Path -Leaf $beaconInstallDirectoryValuePath
	
	if (-not (Test-Path $keyPath)) {
		Write-Error -Message 'FNMS Beacon does not appear to be installed.'
	}
	
	if (@(Get-Item $keyPath | select -ExpandProperty Property | where { $_ -eq $valueName}).Count -ne 1) {
		Write-Error -Message 'FNMS Beacon installation directory not found in registry.'
	}
	
	return (Get-ItemProperty -Path $keyPath -Name $valueName  | select -ExpandProperty $valueName);
}
<#
.Synopsis
Get the file system path where the FNMS Importer XML procedures are installed.
#>
function Get-ImportXMLDirectory() {
	$keyPath = Split-Path -Parent $importXmlDirectoryValuePath
	$valueName = Split-Path -Leaf $importXmlDirectoryValuePath
	
	if (-not (Test-Path $keyPath)) {
		Write-Error -Message 'FNMS inventory importer does not appear to be installed.'
	}
	
	if (@(Get-Item $keyPath | select -ExpandProperty Property | where { $_ -eq $valueName}).Count -ne 1) {
		Write-Error -Message 'FNMS inventory import procedures directory not found in registry.'
	}
	
	return (Get-ItemProperty -Path $keyPath -Name $valueName  | select -ExpandProperty $valueName);
}

<#
.Synopsis
Get the file system path where the FNMS logs and logging configuration are placed.
#>
function Get-LoggingConfigurationDirectory() {
	$keyPath = Split-Path -Parent $loggingConfigurationDirectoryValuePath
	$valueName = Split-Path -Leaf $loggingConfigurationDirectoryValuePath
	
	if ((Test-Path $keyPath) -and
			(@(Get-Item $keyPath | select -ExpandProperty Property | where { $_ -eq $valueName}).Count -eq 1)) {
		
		return (Get-ItemProperty -Path $keyPath -Name $valueName  | select -ExpandProperty $valueName);
		
	} else {
		return (Join-Path ([Environment]::GetFolderPath([Environment+SpecialFolder]::CommonApplicationData)) 'Flexera Software\Compliance\Logging')
	}
}

<#
.Synopsis
Get the file system path where the FNMS Batch Processor state is maintained.
#>
function Get-ProcessorStateDirectory() {
	$keyPath = Split-Path -Parent $processorStateDirectoryValuePath
	$valueName = Split-Path -Leaf $processorStateDirectoryValuePath
	$stateFolder = "State"
	
	if ((Test-Path $keyPath) -and (@(Get-Item $keyPath | select -ExpandProperty Property | where { $_ -eq $valueName}).Count -eq 1)) {
		$processorStateDirectory = (Get-ItemProperty -Path $keyPath -Name $valueName  | select -ExpandProperty $valueName)
		
		# If it is a full path, just return it, otherwise it is a sub folder
		if ([System.IO.Path]::IsPathRooted($processorStateDirectory)) {
			return $stateProcessorDirectory;
		}
		else {
			$stateFolder = $processorStateDirectory
		}
	}
	
	# Return the default location
	return Join-Path -Path (Join-Path -Path (Join-Path -Path (Join-Path -Path $env:ProgramData -ChildPath "Flexera Software") -ChildPath "Compliance") -ChildPath "BatchProcessor") -ChildPath $stateFolder
}

function Set-MaxScreenWidth {

	try {
		$screen = (Get-Host).UI.RawUI;

		$maxWidth = ($screen.MaxPhysicalWindowSize.Width) - 10;

		$buffer = $screen.BufferSize;
		$window = $screen.WindowSize;

		$buffer.Width = $maxWidth;
		$window.Width = $maxWidth;

		$screen.BufferSize = $buffer;
		$screen.WindowSize = $window;
	} catch {
		Write-Verbose "Could not resize the current active screen context."
	}
}
