Public/Nanite.ps1

function Nanite {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory = $FALSE
        )][string]$uri = $NULL,
        [Parameter(
            Mandatory = $FALSE
        )][string]$start = $NULL,
        [Parameter(
            Mandatory = $FALSE
        )][string]$end = $NULL,
        [Parameter(
            Mandatory = $FALSE
        )][string]$case = $NULL,
        [Parameter(
            Mandatory = $FALSE
        )][switch]$testing
    )

    <########################################
    # Start: Testing mode was flagged.
    #########################################>

    If ($testing) {
        $testOperations = Get-ChildItem -Path $Global:configuration.Testing -Recurse -Filter '*.json' | Sort-Object Name
        ForEach ($testOperation in $testOperations) {
            $operation = Get-Content $testOperation.FullName -Raw | ConvertFrom-Json
            $null = $Global:operations.Add($operation)
        }
        Write-Console -Message "Testing Mode: Adding $($testOperations.Count) test operation(s) to the catalog..." -Color 'Yellow'
    }
    <########################################
    # End: Testing mode was flagged.
    #########################################>


    <########################################
    # Start: Called with parameters.
    #########################################>

    If ($uri -or $start -or $end -or $case) {
        # Clear any existing sessions.
        $Global:session = [PSCustomObject]@{}

        # Begin validation of $uri.
        If (!$uri -or !(Test-URI -uri $uri)) {
            Do {
                Write-Console -Message 'Invalid or unsupported resource URI.' -Color 'Red'
                Write-Console -Message 'Resource URI?' -Color 'Cyan'
                $uri = Read-Host '?'
            }
            Until (Test-URI -uri $uri)
        }
        $Global:session | Add-Member -NotePropertyName 'uri' -NotePropertyValue $uri

        # Begin validation of $start.
        If (!$start -or !($start -as [DateTime])) {
            Do {
                Write-Console -Message 'Invalid start date and time.' -Color 'Red'
                Write-Console -Message 'Timespan start?' -Color 'Cyan'
                $start = Read-Host '?'
            }
            Until ($start -as [DateTime])  
        }
        $Global:session | Add-Member -NotePropertyName 'start' -NotePropertyValue $start

        # Begin validation of $end.
        If (!$end -or !($end -as [DateTime]) -or ($end -lt $start)) {
            Do {
                Write-Console -Message 'Invalid end date and time or end date and time cannot occur before start date and time.' -Color 'Red'
                Write-Console -Message 'Timespan end?' -Color 'Cyan'
                $end = Read-Host '?'
            }
            Until (($end -as [DateTime]) -and ($end -gt $start))
        }
        $Global:session | Add-Member -NotePropertyName 'end' -NotePropertyValue $end

        # Check if $case was supplied and validate it if so.
        If ($case) {
            If ($case -notmatch '^\d{15}$') {
                Do {
                    Write-Console -Message 'Invalid case number.' -Color 'Red'
                    Write-Console -Message 'Optional: Case number?' -Color 'Cyan'
                    $case = Read-Host '?'
                }
                Until ($case -match '^\d{15}$')
            }
        }
        $Global:session | Add-Member -NotePropertyName 'case' -NotePropertyValue $case

        # Register the session.
        Register-Session

        # Entering a continuous loop to ensure the main menu is shown until exited.
        While ($TRUE) {
            $operation = $Global:operations | Where-Object { ($_.tags -contains $Global:session.resourceType) -or ($_.tags -contains 'api') } | Select-Object name, @{ Name = 'tags'; Expression ={ $_.tags -Join "`r`n" }}, @{ Name = 'topics'; Expression ={ $_.topics -Join "`r`n" }}, @{ Name = 'description'; Expression ={ $_.description -Join "`r`n" }}, @{ Name = 'links'; Expression ={ $_.links -Join "`r`n" }} | Sort-Object name | Out-GridView -Title '[Nanite] Please select an operation.' -PassThru
            # An operation was selected.
            If ($operation) {
                # Get the operation.
                $operation = $operations | Where-Object { $_.name -eq $operation.name }
                Invoke-Operation -Operation $operation
            }
            # No operation was selected.
            Else {
                Write-Console -Message 'No operation selected.'
                Return
            }
        }
    }
    <########################################
    # End: Called with parameters.
    #########################################>


    <########################################
    # Start: Called without parameters.
    #########################################>

    Else {
        # Entering a continuous loop to ensure the main menu is shown until exited in case all nested continuous loops are exited.
        While ($TRUE) {
            # Clear any existing sessions.
            $Global:session = [PSCustomObject]@{}

            # Show the initial menu.
            Do {
                Write-Console -Message '[F] Free mode' -Color 'Cyan'
                Write-Console -Message '[N] New session' -Color 'Cyan'
                Write-Console -Message '[O] Open previous session' -Color 'Cyan'
                Write-Console -Message '[X] Exit' -Color 'Cyan'
                $mode = Read-Host '?'
            }
            Until ($mode -in @('F', 'N', 'O', 'X'))
            Switch ($mode) {
                <########################################
                # Start: Free Mode.
                #########################################>

                'F' {
                    # Entering a continuous loop to ensure the operations menu is shown until exited.
                    While ($TRUE) {
                        Write-Console -Message 'Please select an operation.'
                        # We do not show items tagged as Dashboards in Free Mode due to the complexity of their parameters and the required calculations not being user friendly manual inputs.
                        $operation = $Global:operations | Where-Object { $_.tags -notcontains 'Dashboards' } | Select-Object name,  @{ Name = 'parameters'; Expression ={ $_.parameters -Join "`r`n" }}, @{ Name = 'tags'; Expression ={ $_.tags -Join "`r`n" }}, @{ Name = 'topics'; Expression ={ $_.topics -Join "`r`n" }}, @{ Name = 'description'; Expression ={ $_.description -Join "`r`n" }}, @{ Name = 'links'; Expression ={ $_.links -Join "`r`n" }} | Sort-Object name | Out-GridView -Title '[Nanite] Please select an operation.' -PassThru
                        # An operation was selected.
                        If ($operation) {
                            # Get the operation.
                            $operation = $operations | Where-Object { $_.name -eq $operation.name }
                            Invoke-Operation -Operation $operation
                        }
                        # No operation was selected.
                        Else {
                            Write-Console -Message 'No operation selected.'
                            Return
                        }
                    }
                    # Break out of the Switch statement.
                    Break
                }
                <########################################
                # End: Free Mode.
                #########################################>


                <########################################
                # Start: New Session Mode.
                #########################################>

                'N' {
                    # Clear any existing sessions.
                    $Global:session = [PSCustomObject]@{}
                    
                    # Begin capturing and validation of $uri.
                    Write-Console -Message 'Resource URI?' -Color 'Cyan'
                    $uri = Read-Host '?'
                    # Begin validation of $uri.
                    If (!$uri -or !(Test-URI -uri $uri)) {
                        Do {
                            Write-Console -Message 'Invalid or unsupported resource URI.' -Color 'Red'
                            Write-Console -Message 'Resource URI?' -Color 'Cyan'
                            $uri = Read-Host '?'
                        }
                        Until (Test-URI -uri $uri)
                    }
                    $Global:session | Add-Member -NotePropertyName 'uri' -NotePropertyValue $uri

                    # Begin capturing and validation of $start.
                    Write-Console -Message 'Timespan start?' -Color 'Cyan'
                    $start = Read-Host '?'
                    # Begin validation of $start.
                    If (!$start -or !($start -as [DateTime])) {
                        Do {
                            Write-Console -Message 'Invalid start date and time.' -Color 'Red'
                            Write-Console -Message 'Timespan start?' -Color 'Cyan'
                            $start = Read-Host '?'
                        }
                        Until ($start -as [DateTime])  
                    }
                    $Global:session | Add-Member -NotePropertyName 'start' -NotePropertyValue $start

                    # Begin capturing and validation of $end.
                    Write-Console -Message 'Timespan end?' -Color 'Cyan'
                    $end = Read-Host '?'
                    # Begin validation of $end.
                    If (!$end -or !($end -as [DateTime]) -or ($end -lt $start)) {
                        Do {
                            Write-Console -Message 'Invalid end date and time or end date and time cannot occur before start date and time.' -Color 'Red'
                            Write-Console -Message 'Timespan end?' -Color 'Cyan'
                            $end = Read-Host '?'
                        }
                        Until (($end -as [DateTime]) -and ($end -gt $start))
                    }
                    $Global:session | Add-Member -NotePropertyName 'end' -NotePropertyValue $end

                    # Begin capturing and validation of the optional $case parameter.
                    Write-Console -Message 'Optional: Case number?' -Color 'Cyan'
                    $case = Read-Host '?'
                    # Check if $case was supplied and validate it if so.
                    # $case validation needs to be fixed to allow empty input.
                    If ($case) {
                        If ($case -notmatch '^\d{15}$') {
                            Do {
                                Write-Console -Message 'Invalid case number.' -Color 'Red'
                                Write-Console -Message 'Optional: Case number?' -Color 'Cyan'
                                $case = Read-Host '?'
                            }
                            Until ($case -match '^\d{15}$')
                        }
                    }
                    $Global:session | Add-Member -NotePropertyName 'case' -NotePropertyValue $case

                    # Register the session.
                    Register-Session

                    # Entering a continuous loop to ensure the operations menu is shown until exited.
                    While ($TRUE) {
                        Write-Console -Message 'Please select an operation.'
                        $operation = $Global:operations | Where-Object { ($_.tags -contains $Global:session.resourceType) -or ($_.tags -contains 'api') } | Select-Object name, @{ Name = 'tags'; Expression ={ $_.tags -Join "`r`n" }}, @{ Name = 'topics'; Expression ={ $_.topics -Join "`r`n" }}, @{ Name = 'description'; Expression ={ $_.description -Join "`r`n" }}, @{ Name = 'links'; Expression ={ $_.links -Join "`r`n" }} | Sort-Object name | Out-GridView -Title '[Nanite] Please select an operation.' -PassThru
                        # An operation was selected.
                        If ($operation) {
                            # Get the operation.
                            $operation = $operations | Where-Object { $_.name -eq $operation.name }
                            Invoke-Operation -Operation $operation
                        }
                        # No operation was selected.
                        Else {
                            Write-Console -Message 'No operation selected.'
                            Return
                        }
                    }
                    # Break out of the Switch statement.
                    Break
                }
                <########################################
                # End: Free Mode.
                #########################################>


                <########################################
                # Start: Open Previous Session Mode.
                #########################################>

                'O' {
                    # Find session files.
                    $sessions = Get-ChildItem -Path "$($Global:configuration.Output)\Sessions" -Recurse -Filter '*.json' | Sort-Object Name
                    If ($sessions.Count -eq 0) {
                        Write-Console 'No previous sessions were found.'
                        Return
                    }
                    Else {
                        # Display session selector.
                        $choice = $sessions | Select-Object @{ Name = 'LastUsed'; Expression ={ $_.LastWriteTime }}, @{ Name = 'Case'; Expression ={ $_.BaseName }} | Sort-Object LastUsed -Descending | Out-GridView -Title '[Nanite] Please select a session.' -OutputMode Single
                        If (!$choice) {
                            Write-Console -Message 'No session was selected.'
                            Return
                        }
                        Else {
                            # Clear any existing sessions.
                            $Global:session = [PSCustomObject]@{}
                            # Load the session file.
                            $sessionFile = $sessions | Where-Object BaseName -eq $choice.Case | Select-Object FullName
                            $Global:session = Get-Content -Path $sessionFile.FullName -Raw | ConvertFrom-Json
                            # Update the session file's $_.LastWriteTime to keep the session file relevant and reset its threshold timer.
                            (Get-Item $sessionFile.FullName).LastWriteTime = (Get-Date) 
                            Write-Console -Message "Opening previous session for case #$($Global:session.case)'s $($Global:session.resource) resource..."
                            Write-Console -Message "Session for $($Global:session.resourceType) from $($Global:session.timespanStart) to $($Global:session.timespanEnd) has loaded."
                        }
                    }
                    # Entering a continuous loop to ensure the operations menu is shown until exited.
                    While ($TRUE) {
                        Write-Console -Message 'Please select an operation.'
                        $operation = $Global:operations | Where-Object { ($_.tags -contains $Global:session.resourceType) -or ($_.tags -contains 'api') } | Select-Object name, @{ Name = 'tags'; Expression ={ $_.tags -Join "`r`n" }}, @{ Name = 'topics'; Expression ={ $_.topics -Join "`r`n" }}, @{ Name = 'description'; Expression ={ $_.description -Join "`r`n" }}, @{ Name = 'links'; Expression ={ $_.links -Join "`r`n" }} | Sort-Object name | Out-GridView -Title '[Nanite] Please select an operation.' -PassThru
                        # An operation was selected.
                        If ($operation) {
                            # Get the operation.
                            $operation = $operations | Where-Object { $_.name -eq $operation.name }
                            Invoke-Operation -Operation $operation
                        }
                        # No operation was selected.
                        Else {
                            Write-Console -Message 'No operation selected.'
                            Return
                        }
                    }
                    # Break out of the Switch statement.
                    Break
                }
                <########################################
                # End: Open Previous Session Mode.
                #########################################>


                <########################################
                # Start: Exit Nanite.
                #########################################>

                'X' {
                    Write-Console -Message 'Exiting Nanite.'
                    Return
                }
                <########################################
                # End: Exit Nanite.
                #########################################>

            }
            Write-Console -Message 'Returning to the main menu...'
        }
    }
    <########################################
    # End: Called without parameters.
    #########################################>

}