'  
'   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 System.IO
Imports System.Windows.Forms

Imports Rebex.Net
Imports Rebex.TerminalEmulation

''' <summary>
''' The main form of the application. It cantains the terminal control.
''' </summary>
Public Class MainForm
    Inherits Form
    ''' <summary>
    ''' Path to the config file at Local application data storage on the File system.
    ''' </summary>
    Private Shared ReadOnly _configFile As String = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), String.Format("Rebex{0}TerminalEmulation{0}WinFormRExec.xml", Path.DirectorySeparatorChar))

    ''' <summary>
    ''' Required designer variable.
    ''' </summary>
    Private components As System.ComponentModel.IContainer = Nothing
    Private WithEvents txtCommand As System.Windows.Forms.TextBox
    Private WithEvents btnSend As System.Windows.Forms.Button
    Private label1 As System.Windows.Forms.Label
    Private txtResponse As System.Windows.Forms.TextBox
    Private label2 As System.Windows.Forms.Label

    ''' <summary>
    ''' The ssh object. It is used to comunicate with ssh server.
    ''' </summary>
    Private _ssh As Ssh

    ''' <summary>
    ''' Initialize this class.
    ''' </summary>
    Public Sub New()
        InitializeComponent()

        CheckForIllegalCrossThreadCalls = True
    End Sub

    ''' <summary>
    ''' Clean up any resources being used.
    ''' </summary>
    ''' <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso Not (components Is Nothing) Then
            components.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

#Region "Windows Form Designer generated code"

    ''' <summary>
    ''' Required method for Designer support - do not modify
    ''' the contents of this method with the code editor.
    ''' </summary>
    Private Sub InitializeComponent()
        Me.txtCommand = New System.Windows.Forms.TextBox
        Me.btnSend = New System.Windows.Forms.Button
        Me.label1 = New System.Windows.Forms.Label
        Me.txtResponse = New System.Windows.Forms.TextBox
        Me.label2 = New System.Windows.Forms.Label
        Me.SuspendLayout()
        '
        'txtCommand
        '
        Me.txtCommand.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.txtCommand.Location = New System.Drawing.Point(88, 31)
        Me.txtCommand.Name = "txtCommand"
        Me.txtCommand.Size = New System.Drawing.Size(488, 20)
        Me.txtCommand.TabIndex = 0
        Me.txtCommand.Text = ""
        '
        'btnSend
        '
        Me.btnSend.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.btnSend.Location = New System.Drawing.Point(587, 31)
        Me.btnSend.Name = "btnSend"
        Me.btnSend.Size = New System.Drawing.Size(63, 23)
        Me.btnSend.TabIndex = 1
        Me.btnSend.Text = "Send"
        '
        'label1
        '
        Me.label1.AutoSize = True
        Me.label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(238, Byte))
        Me.label1.Location = New System.Drawing.Point(10, 34)
        Me.label1.Name = "label1"
        Me.label1.Size = New System.Drawing.Size(67, 17)
        Me.label1.TabIndex = 2
        Me.label1.Text = "Command:"
        '
        'txtResponse
        '
        Me.txtResponse.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.txtResponse.Font = New System.Drawing.Font("Courier New", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(238, Byte))
        Me.txtResponse.Location = New System.Drawing.Point(12, 60)
        Me.txtResponse.Multiline = True
        Me.txtResponse.Name = "txtResponse"
        Me.txtResponse.ScrollBars = System.Windows.Forms.ScrollBars.Both
        Me.txtResponse.Size = New System.Drawing.Size(638, 494)
        Me.txtResponse.TabIndex = 3
        Me.txtResponse.Text = ""
        '
        'label2
        '
        Me.label2.AutoSize = True
        Me.label2.Font = New System.Drawing.Font("Microsoft Sans Serif", 9.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(238, Byte))
        Me.label2.Location = New System.Drawing.Point(10, 9)
        Me.label2.Name = "label2"
        Me.label2.Size = New System.Drawing.Size(348, 17)
        Me.label2.TabIndex = 4
        Me.label2.Text = "Note: Don't run commands that require user interaction."
        '
        'MainForm
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(659, 566)
        Me.Controls.Add(Me.label2)
        Me.Controls.Add(Me.txtResponse)
        Me.Controls.Add(Me.label1)
        Me.Controls.Add(Me.btnSend)
        Me.Controls.Add(Me.txtCommand)
        Me.Name = "MainForm"
        Me.Text = "Rebex Remote Exec"
        Me.ResumeLayout(False)

    End Sub

#End Region

    ''' <summary>
    ''' Handles the form load event.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            ' show connection dialog
            Dim connection As New Connection(_configFile)

            ' if not confirmed, exit the application
            If connection.ShowDialog() <> DialogResult.OK Then
                Close()
                Return
            End If

            ' create new Ssh object
            _ssh = New Ssh

            ' connect
            _ssh.Connect(connection.HostName)

            ' login
            _ssh.Login(connection.UserName, connection.Password)
        Catch ex As Exception
            txtResponse.AppendText(String.Format("Exception occured: {0}", ex))
            txtCommand.Enabled = False
            btnSend.Enabled = False
        End Try
    End Sub

    ''' <summary>
    ''' Handles the textbox 'Command' keyup event.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub txtCommand_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtCommand.KeyUp
        ' when enter was pressed, send the commend
        If e.KeyCode = Keys.Enter Then
            SendCommand()
        End If
    End Sub

    ''' <summary>
    ''' Handles the button 'Send' click event.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        ' when clicked on send, send the command
        SendCommand()
    End Sub

    ''' <summary>
    ''' Sends the command to the remote host and writes the output.
    ''' </summary>
    Private Sub SendCommand()
        Dim command As String = txtCommand.Text

        If command.Length = 0 Then
            Return
        End If

        Try
            ' --------------------------------------------------------
            ' This sample starts and runs a single command.
            ' If you would like to run multiple commands in a single
            ' shell session, use StartScripting() and refer to
            ' http:'www.rebex.net/terminal-emulation.net/features/scripting.aspx
            ' --------------------------------------------------------

            ' start a single command
            Dim scripting As Scripting = _ssh.StartScripting(command)

            ' --------------------------------------------------------
            ' 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').
            ' --------------------------------------------------------

            ' set the timeout of the shell to 30 seconds
            scripting.Timeout = 30000

            ' read the response of the command
            Dim response As String = scripting.ReadUntil(ScriptEvent.Closed)

            ' append the response
            If response Is Nothing OrElse response.Length = 0 Then
                txtResponse.AppendText("* No response.")
            Else
                txtResponse.AppendText(response.Replace("" & Chr(10) & "", "" & Chr(13) & "" & Chr(10) & ""))
            End If
        Catch ex As Exception
            txtResponse.AppendText(String.Format("Exception occured: {0}", ex))
        End Try

        txtResponse.AppendText("" & Chr(13) & "" & Chr(10) & "")

        ' scroll to the end of response
        txtResponse.SelectionStart = txtResponse.Text.Length
        txtResponse.ScrollToCaret()

        ' select the text of txtCommand to make it easier to enter a new command
        txtCommand.SelectAll()
    End Sub
End Class
