Public/Show-PurviewConfigAnalyserGUI.ps1


function Show-PurviewConfigAnalyserGUI {
    [CmdletBinding()]
    param(
        [string]$MasterControlPath = (Join-Path $PSScriptRoot "..\config\MasterControlBooks\ControlBook_Reference.csv"),
        [string]$MasterPropertyPath = (Join-Path $PSScriptRoot "..\config\MasterControlBooks\ControlBook_Property_Reference.csv"),
        [string]$OutputPath = (Join-Path $PSScriptRoot "..\config")
    )
    try {
        Add-Type -AssemblyName System.Windows.Forms
        Add-Type -AssemblyName System.Drawing
    } catch {
        Write-Host "❌ Could not load Windows Forms assemblies: $($_.Exception.Message)" -ForegroundColor Red
        return
    }
    try {
        $controls = Import-Csv $MasterControlPath
        $properties = Import-Csv $MasterPropertyPath
    } catch {
        [System.Windows.Forms.MessageBox]::Show("Error loading control book CSVs: $($_.Exception.Message)", "Error", 'OK', 'Error')
        return
    }
    $form = New-Object Windows.Forms.Form
    $form.Text = "Custom Configuration Creator"
    $form.Size = New-Object Drawing.Size(1000, 700)
    $form.StartPosition = 'CenterScreen'
    $form.FormBorderStyle = 'FixedDialog'
    $form.MaximizeBox = $false
    $form.MinimizeBox = $false

    # Maturity Level selection
    $maturityLabel = New-Object Windows.Forms.Label
    $maturityLabel.Text = "How many Maturity Levels are you Planning ?"
    $maturityLabel.Location = New-Object Drawing.Point(10,10)
    $maturityLabel.Size = New-Object Drawing.Size(350, 25)
    $form.Controls.Add($maturityLabel)

    $maturityUpDown = New-Object Windows.Forms.NumericUpDown
    $maturityUpDown.Location = New-Object Drawing.Point(370,10)
    $maturityUpDown.Size = New-Object Drawing.Size(60,25)
    $maturityUpDown.Minimum = 1
    $maturityUpDown.Maximum = 10
    $maturityUpDown.Value = 1
    $form.Controls.Add($maturityUpDown)

    $label = New-Object Windows.Forms.Label
    $label.Text = "Select controls and configure properties."
    $label.AutoSize = $true
    $label.Location = New-Object Drawing.Point(10,40)
    $form.Controls.Add($label)
    $tree = New-Object Windows.Forms.TreeView
    $tree.Location = New-Object Drawing.Point(10,70)
    $tree.Size = New-Object Drawing.Size(350,550)
    $tree.CheckBoxes = $true
    $form.Controls.Add($tree)
    $capabilities = $controls | Group-Object Capability
    foreach ($cap in $capabilities) {
        $parent = $tree.Nodes.Add($cap.Name)
        foreach ($ctrl in $cap.Group) {
            $node = $parent.Nodes.Add("$($ctrl.ControlID) - $($ctrl.Control)")
            $node.Tag = $ctrl.ControlID
        }
    }
    # Panel for dynamic property controls
    $propertyPanel = New-Object Windows.Forms.Panel
    $propertyPanel.Location = New-Object Drawing.Point(370,70)
    $propertyPanel.Size = New-Object Drawing.Size(600,550)
    $propertyPanel.AutoScroll = $true
    $form.Controls.Add($propertyPanel)
    $propertyInputs = @{}
    $maturityInputs = @{}

    function Update-PropertyPanel {
        $propertyPanel.Controls.Clear()
        $propertyInputs.Clear()
        $maturityInputs.Clear()
        $y = 10
        $checkedControls = @()
        $numLevels = [int]$maturityUpDown.Value
        foreach ($cap in $tree.Nodes) {
            foreach ($ctrl in $cap.Nodes) {
                if ($ctrl.Checked) { $checkedControls += $ctrl.Tag }
            }
        }
        foreach ($cid in $checkedControls) {
            $props = $properties | Where-Object { $_.ControlID -eq $cid }
            $ctrlRow = $controls | Where-Object { $_.ControlID -eq $cid }
            # Header first, then maturity input, then properties
            $labelHeader = New-Object Windows.Forms.Label
            $labelHeader.Text = "ControlID: $cid - $($ctrlRow.Control)"
            $labelHeader.Font = New-Object Drawing.Font('Segoe UI',10,[Drawing.FontStyle]::Bold)
            $labelHeader.Location = New-Object Drawing.Point(10, $y)
            $labelHeader.Size = New-Object Drawing.Size(500, 25)
            $propertyPanel.Controls.Add($labelHeader)
            $y = [int]($y + 30)

            $maturityLabel = New-Object Windows.Forms.Label
            $maturityLabel.Text = "Maturity Level for ${cid}:"
            $maturityLabel.Location = New-Object Drawing.Point(20, $y)
            $maturityLabel.Size = New-Object Drawing.Size(150, 25)
            $propertyPanel.Controls.Add($maturityLabel)
            $maturityCombo = New-Object Windows.Forms.ComboBox
            $maturityCombo.Location = New-Object Drawing.Point(180, $y)
            $maturityCombo.Size = New-Object Drawing.Size(60, 25)
            for ($i = 1; $i -le $numLevels; $i++) { $maturityCombo.Items.Add($i) }
            $maturityCombo.SelectedIndex = 0
            $propertyPanel.Controls.Add($maturityCombo)
            $maturityInputs[$cid] = $maturityCombo
            $y = [int]($y + 30)

            if ($props) {
                foreach ($p in $props) {
                    $isRequired = ($p.MustConfigure -eq $true -or $p.MustConfigure -eq 'true' -or [string]::IsNullOrWhiteSpace($p.DefaultValue))
                    $labelText = if ($isRequired) { "* $($p.Properties)" } else { $p.Properties }
                    $label = New-Object Windows.Forms.Label
                    $label.Text = $labelText
                    $label.Location = New-Object Drawing.Point(20, $y)
                    $label.Size = New-Object Drawing.Size(200, 25)
                    $propertyPanel.Controls.Add($label)
                    $tb = New-Object Windows.Forms.TextBox
                    $tb.Location = New-Object Drawing.Point(230, $y)
                    $tb.Size = New-Object Drawing.Size(250, 25)
                    $tb.Text = $p.DefaultValue
                    $propertyPanel.Controls.Add($tb)
                    $propertyInputs["$($cid)|$($p.Properties)"] = @{ TextBox = $tb; Required = $isRequired }
                    $y = [int]($y + 35)
                }
            }
        }
        if ($y -eq 10) {
            $labelNone = New-Object Windows.Forms.Label
            $labelNone.Text = 'Check controls to configure their properties.'
            $labelNone.Location = New-Object Drawing.Point(10, $y)
            $labelNone.Size = New-Object Drawing.Size(400, 25)
            $propertyPanel.Controls.Add($labelNone)
        } else {
            $noteLabel = New-Object Windows.Forms.Label
            $noteLabel.Text = '* Required property'
            $noteLabel.ForeColor = [System.Drawing.Color]::Red
            $noteLabel.Location = New-Object Drawing.Point(10, $y)
            $noteLabel.Size = New-Object Drawing.Size(400, 20)
            $propertyPanel.Controls.Add($noteLabel)
        }
    }

    # Update property panel when a control is checked/unchecked
    $tree.Add_AfterCheck({ Update-PropertyPanel })
    # Also update when the form loads
    Update-PropertyPanel
    $saveBtn = New-Object Windows.Forms.Button
    $saveBtn.Text = "Save Configuration"
    $saveBtn.Location = New-Object Drawing.Point(370,560)
    $saveBtn.Size = New-Object Drawing.Size(200,40)
    $saveBtn.Add_Click({
        $checked = @()
        foreach ($cap in $tree.Nodes) {
            foreach ($ctrl in $cap.Nodes) {
                if ($ctrl.Checked) { $checked += $ctrl.Tag }
            }
        }
        if (-not $checked) {
            [Windows.Forms.MessageBox]::Show("Select at least one control.","Validation",'OK','Warning')
            return
        }
        $ctrlOut = @()
        $propOut = @()
        $allValid = $true
        $missingProps = @()
        foreach ($cid in $checked) {
            $ctrl = $controls | Where-Object { $_.ControlID -eq $cid }
            $maturityLevel = 1
            if ($maturityInputs.ContainsKey($cid)) {
                $maturityLevel = $maturityInputs[$cid].SelectedItem
            }
            $ctrlOut += [PSCustomObject]@{ Capability=$ctrl.Capability; ControlID=$ctrl.ControlID; Control=$ctrl.Control; MaturityLevel=$maturityLevel }
            $props = $properties | Where-Object { $_.ControlID -eq $cid }
            foreach ($p in $props) {
                $key = "$($cid)|$($p.Properties)"
                if ($propertyInputs.ContainsKey($key)) {
                    $val = $propertyInputs[$key].TextBox.Text
                    $isRequired = $propertyInputs[$key].Required
                } else {
                    $val = $p.DefaultValue
                    $isRequired = ($p.MustConfigure -eq $true -or $p.MustConfigure -eq 'true' -or [string]::IsNullOrWhiteSpace($p.DefaultValue))
                }
                if ($isRequired -and [string]::IsNullOrWhiteSpace($val)) {
                    $allValid = $false
                    $missingProps += "$($p.Properties) (ControlID: $cid)"
                }
                $propOut += [PSCustomObject]@{ ControlID=$cid; Properties=$p.Properties; DefaultValue=$val; MustConfigure=$p.MustConfigure; MaturityLevel=$maturityLevel }
            }
        }
        if (-not $allValid) {
            [Windows.Forms.MessageBox]::Show("Please fill all required properties before saving:`n`n" + ($missingProps -join "`n"),"Validation",'OK','Warning')
            return
        }
        $configName = [Microsoft.VisualBasic.Interaction]::InputBox("Enter configuration name:","Config Name","MyCustomConfig")
        if (-not $configName) { return }
        $ctrlOut | Export-Csv (Join-Path $OutputPath "ControlBook_${configName}_Config.csv") -NoTypeInformation
        $propOut | Export-Csv (Join-Path $OutputPath "ControlBook_Property_${configName}_Config.csv") -NoTypeInformation
        [Windows.Forms.MessageBox]::Show("Configuration saved!","Success",'OK','Information')
        $form.Close()
    })
    $form.Controls.Add($saveBtn)
    $cancelBtn = New-Object Windows.Forms.Button
    $cancelBtn.Text = "Cancel"
    $cancelBtn.Location = New-Object Drawing.Point(580,560)
    $cancelBtn.Size = New-Object Drawing.Size(120,40)
    $cancelBtn.Add_Click({ $form.Close() })
    $form.Controls.Add($cancelBtn)
    $form.ShowDialog()
}