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

''' <summary>
''' Implementation of Rebex.ILogWriter which logs to specified RichTextBox.
''' </summary>
Public Class RichTextBoxLogWriter
    Inherits LogWriterBase
    ' colors
    Friend Shared ReadOnly COLORRESPONSE As Color = Color.Black
    ' response color
    Friend Shared ReadOnly COLORCOMMAND As Color = Color.DarkGreen
    ' command color
    Friend Shared ReadOnly COLORERROR As Color = Color.Red
    ' color of error messages
    Friend Shared ReadOnly COLORINFO As Color = Color.Blue
    ' info color
    Friend Shared ReadOnly COLORSSH As Color = Color.BlueViolet
    ' color of SSH communication
    Friend Shared ReadOnly COLORTLS As Color = Color.BlueViolet
    ' color of TLS communication
    Private _textbox As RichTextBox
    Private _maxCharsCount As Integer

    Public Sub New(textbox As RichTextBox, maxCharsCount As Integer, logAs As LogLevel)
        _textbox = textbox
        _maxCharsCount = maxCharsCount
        Level = logAs
    End Sub

    Public Overrides Sub Write(logAs As LogLevel, objectType As Type, objectId As Integer, area As String, message As String)
        If logAs < Level Then
            Return
        End If

        Dim color As Color = COLORINFO

        If logAs >= LogLevel.[Error] Then
            color = COLORERROR
        Else
            Select Case area.ToUpper()
                Case "COMMAND"
                    color = COLORCOMMAND
                    Exit Select
                Case "RESPONSE"
                    color = COLORRESPONSE
                    Exit Select
                Case "SSH"
                    color = COLORSSH
                    Exit Select
                Case "TLS"
                    color = COLORTLS
                    Exit Select
            End Select
        End If

        message = String.Format("{0:HH:mm:ss.fff} {1} {2}: {3}" & vbCr & vbLf, DateTime.Now, logAs.ToString(), area, message)

        Try
            If Not _textbox.IsDisposed Then
                _textbox.Invoke(New WriteLogHandler(AddressOf WriteLog), New Object() {message, color})
            End If
        Catch generatedExceptionName As ObjectDisposedException
        End Try
    End Sub

    Public Sub WriteToLog(message As String, color As Color)
        _textbox.Focus()
        _textbox.SelectionColor = color
        _textbox.AppendText(message & vbCr & vbLf)
    End Sub

    Public Sub WriteToLog(color As Color, format As String, ParamArray args As Object())

        WriteToLog(String.Format(format, args), color)
    End Sub

    Private Delegate Sub WriteLogHandler(message As String, color As Color)

    Private Sub WriteLog(message As String, color As Color)
        EnsureTextSpace(message.Length)

        _textbox.Focus()
        _textbox.SelectionColor = color
        _textbox.AppendText(message)
    End Sub

    Private Sub EnsureTextSpace(length As Integer)
        If _textbox.TextLength + length < _maxCharsCount Then
            Return
        End If

        Dim spaceLeft As Integer = _maxCharsCount - length

        If spaceLeft <= 0 Then
            _textbox.Clear()
            Return
        End If

        Dim plainText As String = _textbox.Text

        ' find the end of line
        Dim start As Integer = plainText.IndexOf(ControlChars.Lf, plainText.Length - spaceLeft)
        If start >= 0 AndAlso start + 1 < plainText.Length Then
            _textbox.SelectionStart = 0
            _textbox.SelectionLength = start + 1

            ' setting the SelectedText property is available only when ReadOnly = false
            Dim ro As Boolean = _textbox.[ReadOnly]
            _textbox.[ReadOnly] = False
            _textbox.SelectedText = ""
            _textbox.[ReadOnly] = ro

            _textbox.SelectionStart = _textbox.TextLength
            _textbox.SelectionLength = 0
        Else
            _textbox.Clear()
        End If
    End Sub
End Class
