enum WorkshopEnsure {
    Absent
    Present
}

class WorkshopReason {
    [DscProperty()]
    [string] $Code

    [DscProperty()]
    [string] $Phrase
}

class WorkshopWindowsPowerShellBridge {
    static [string] Invoke([string] $Script) {
        $encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Script))
        $startInfo = [Diagnostics.ProcessStartInfo]::new()
        $startInfo.FileName = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
        $startInfo.Arguments = "-NoLogo -NoProfile -NonInteractive -EncodedCommand $encoded"
        $startInfo.UseShellExecute = $false
        $startInfo.CreateNoWindow = $true
        $startInfo.RedirectStandardOutput = $true
        $startInfo.RedirectStandardError = $true

        $process = [Diagnostics.Process]::new()
        $process.StartInfo = $startInfo
        if (-not $process.Start()) {
            throw 'Windows PowerShell could not be started.'
        }

        # Drain both redirected streams concurrently. Reading one stream to EOF
        # before the other can deadlock when ServerManager emits enough progress or
        # warning output to fill the second pipe.
        $stdoutTask = $process.StandardOutput.ReadToEndAsync()
        $stderrTask = $process.StandardError.ReadToEndAsync()
        if (-not $process.WaitForExit(900000)) {
            try { $process.Kill($true) } catch { }
            throw 'Windows PowerShell did not complete within 15 minutes.'
        }
        $stdout = $stdoutTask.GetAwaiter().GetResult()
        $stderr = $stderrTask.GetAwaiter().GetResult()
        if ($process.ExitCode -ne 0) {
            throw "Windows PowerShell exited with code $($process.ExitCode): $stderr"
        }

        return $stdout.Trim()
    }
}

[DscResource()]
class WorkshopWindowsFeature {
    [DscProperty(Key)]
    [string] $Name

    [DscProperty(Mandatory)]
    [WorkshopEnsure] $Ensure

    [DscProperty()]
    [WorkshopReason[]] $Reasons

    hidden [bool] IsInstalled() {
        $nameLiteral = $this.Name.Replace("'", "''")
        $result = [WorkshopWindowsPowerShellBridge]::Invoke("[bool](Get-WindowsFeature -Name '$nameLiteral').Installed")
        return $result -eq 'True'
    }

    [WorkshopWindowsFeature] Get() {
        $installed = $this.IsInstalled()
        $current = [WorkshopWindowsFeature]::new()
        $current.Name = $this.Name
        $current.Ensure = if ($installed) { [WorkshopEnsure]::Present } else { [WorkshopEnsure]::Absent }
        if ($current.Ensure -ne $this.Ensure) {
            $reason = [WorkshopReason]::new()
            $reason.Code = 'WorkshopWindowsFeature:WorkshopWindowsFeature:StateMismatch'
            $reason.Phrase = "Windows feature '$($this.Name)' is $($current.Ensure); expected $($this.Ensure)."
            $current.Reasons = @($reason)
        }
        else {
            $current.Reasons = @()
        }
        return $current
    }

    [bool] Test() {
        return $this.Get().Ensure -eq $this.Ensure
    }

    [void] Set() {
        $nameLiteral = $this.Name.Replace("'", "''")
        if ($this.Ensure -eq [WorkshopEnsure]::Present) {
            [void][WorkshopWindowsPowerShellBridge]::Invoke("Install-WindowsFeature -Name '$nameLiteral' -IncludeManagementTools | Out-Null")
        }
        else {
            [void][WorkshopWindowsPowerShellBridge]::Invoke("Remove-WindowsFeature -Name '$nameLiteral' -Restart:`$false | Out-Null")
        }
    }
}

[DscResource()]
class WorkshopWindowsOptionalFeature {
    [DscProperty(Key)]
    [string] $Name

    [DscProperty(Mandatory)]
    [WorkshopEnsure] $Ensure

    [DscProperty()]
    [WorkshopReason[]] $Reasons

    hidden [bool] IsEnabled() {
        $nameLiteral = $this.Name.Replace("'", "''")
        $state = [WorkshopWindowsPowerShellBridge]::Invoke("(Get-WindowsOptionalFeature -Online -FeatureName '$nameLiteral').State")
        return $state -match '^Enabled'
    }

    [WorkshopWindowsOptionalFeature] Get() {
        $enabled = $this.IsEnabled()
        $current = [WorkshopWindowsOptionalFeature]::new()
        $current.Name = $this.Name
        $current.Ensure = if ($enabled) { [WorkshopEnsure]::Present } else { [WorkshopEnsure]::Absent }
        if ($current.Ensure -ne $this.Ensure) {
            $reason = [WorkshopReason]::new()
            $reason.Code = 'WorkshopWindowsOptionalFeature:WorkshopWindowsOptionalFeature:StateMismatch'
            $reason.Phrase = "Windows optional feature '$($this.Name)' is $($current.Ensure); expected $($this.Ensure)."
            $current.Reasons = @($reason)
        }
        else {
            $current.Reasons = @()
        }
        return $current
    }

    [bool] Test() {
        return $this.Get().Ensure -eq $this.Ensure
    }

    [void] Set() {
        $nameLiteral = $this.Name.Replace("'", "''")
        if ($this.Ensure -eq [WorkshopEnsure]::Present) {
            [void][WorkshopWindowsPowerShellBridge]::Invoke("Enable-WindowsOptionalFeature -Online -FeatureName '$nameLiteral' -NoRestart | Out-Null")
        }
        else {
            [void][WorkshopWindowsPowerShellBridge]::Invoke("Disable-WindowsOptionalFeature -Online -FeatureName '$nameLiteral' -NoRestart | Out-Null")
        }
    }
}
