'  
'   Rebex Sample Code License
' 
'   Copyright 2025, REBEX CR s.r.o.
'   All rights reserved.
'   https://www.rebex.net/
' 
'   Permission to use, copy, modify, and/or distribute this software for any
'   purpose with or without fee is hereby granted.
' 
'   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
'   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
'   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
'   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
'   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
'   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
'   OTHER DEALINGS IN THE SOFTWARE.
' 

Imports System

Imports Rebex.Net
Imports Rebex.TerminalEmulation

''' <summary>
''' The SimpleShell class provides a very simple shell:
'''  - read the command from the user input 
'''  - send the command to the remote host 
'''  - read the response from the remote host
'''  - write the response to the console
''' </summary>
Public Class SimpleShell
    ''' <summary>
    ''' Class that stores input program arguments.
    ''' </summary>
    Private Class ProgramArguments
        ''' <summary>
        ''' Gets or sets the host name.
        ''' </summary>
        Public Property HostName() As String
            Get
                Return _hostName
            End Get
            Set(value As String)
                _hostName = value
            End Set
        End Property
        Private _hostName As String

        ''' <summary>
        ''' Gets or sets the login name.
        ''' </summary>
        Public Property LoginName() As String
            Get
                Return _loginName
            End Get
            Set(value As String)
                _loginName = value
            End Set
        End Property
        Private _loginName As String

        ''' <summary>
        ''' Gets or sets the password.
        ''' </summary>
        Public Property Password() As String
            Get
                Return _Password
            End Get
            Set(value As String)
                _Password = value
            End Set
        End Property
        Private _Password As String
    End Class

    ''' <summary>
    ''' The main entry point for the application.
    ''' </summary>
    ''' <param name="args">Program arguments.</param>
    ''' <returns>Exit code.</returns>
    <STAThread()> _
    Public Shared Function Main(ByVal args As String()) As Integer
            ' set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key


        ' show program header
        ShowHeader()

        ' if no arguments was specified, show syntax and examples also
        If args.Length = 0 Then
            ShowHelp()
        End If

        ' get program arguments
        Dim arguments As ProgramArguments = GetProgramArguments(args)

        ' create an Ssh object
        Dim ssh As New Ssh()

        Try
            ' connect to the host
            ssh.Connect(arguments.HostName)

            ' login
            ssh.Login(arguments.LoginName, arguments.Password)

            ' start scripting
            Dim scripting As Scripting = ssh.StartScripting()

            ' --------------------------------------------------------
            ' A proper value of Scripting.Timeout property depends on the nature of
            ' the command you invoke.
            ' If the response of the command is being sent continuously,
            ' the timeout can be small (for example commands like 'ls -R /').
            ' If the response of the command is sent rarely or only at the end of the command,
            ' bigger timeout should be used (for example commands like 'ls -R / > list.txt').
            ' --------------------------------------------------------

            ' decrease the response timeout to 20 seconds (default is 60)
            scripting.Timeout = 20000

            ' detect prompt automatically
            scripting.DetectPrompt()

            ' main loop
            Dim result As ScriptMatch
            Do
                ' output a prompt to a console
                Console.Write("Enter shell command: ")

                ' read the command from a console
                Dim command As String = Console.ReadLine()

                ' send the command to the server
                scripting.SendCommand(command)

                ' --------------------------------------------------------
                ' There are several ways to read command response.
                ' Please check out http://www.rebex.net/terminal-emulation.net/features/scripting.aspx for more information.
                ' --------------------------------------------------------

                ' read the response line by line
                Do
                    ' read until a line is received (or prompt, or the connection is closed)
                    Dim line As String = scripting.ReadUntil(ScriptEvent.Line, ScriptEvent.Prompt, ScriptEvent.Closed)

                    ' get the result of the ReadUntil method
                    result = scripting.LastResult

                    ' display the line
                    Console.WriteLine(line)

                Loop While result.IsLine

            Loop While Not result.IsClosed

        Catch e As Exception
            Console.WriteLine("Exception occured: {0}", e)
            Return 1
        Finally
            ' disconnect from the server
            If Not ssh Is Nothing Then
                ssh.Disconnect()
            End If
        End Try

        Return 0
    End Function

    Private Shared Sub ShowHeader()
        Console.WriteLine("----------------------------------------------------------")
        Console.WriteLine("Rebex Simple Shell - executes commands on the remote host.")
        Console.WriteLine("----------------------------------------------------------")
        Console.WriteLine("Note: Don't start commands that require user interaction.")
        Console.WriteLine()
    End Sub

    Private Shared Sub ShowHelp()
        Console.WriteLine("Syntax: SimpleShell [host [login [password]]]")
        Console.WriteLine()
        Console.WriteLine("Example: SimpleShell sample.host.com test test123")
        Console.WriteLine("Example: SimpleShell sample.host.com test")
        Console.WriteLine("Example: SimpleShell sample.host.com")
        Console.WriteLine("Example: SimpleShell")
        Console.WriteLine()
    End Sub

    ''' <summary>
    ''' Initialize the ProgramArguments class by the given arguments.
    ''' If any argument is missing the user is prompted.
    ''' </summary>
    ''' <param name="args">Command line arguments.</param>
    ''' <returns>Initialized ProgramArguments class.</returns>
    Private Shared Function GetProgramArguments(ByVal args As String()) As ProgramArguments
        Dim arguments As New ProgramArguments()

        If args.Length > 0 Then
            arguments.HostName = args(0)
        Else
            Console.Write("host: ")
            arguments.HostName = Console.ReadLine()
        End If

        If args.Length > 1 Then
            arguments.LoginName = args(1)
        Else
            Console.Write("login: ")
            arguments.LoginName = Console.ReadLine()
        End If

        If args.Length > 2 Then
            arguments.Password = args(2)
        Else
            Console.Write("password: ")
            arguments.Password = Console.ReadLine()
        End If

        Return arguments
    End Function
End Class
