using Common.AppSettings; using Common.Logging; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using MultiTerm.Core.Model; using MultiTerm.Core.Types; using MultiTerm.Protocols.Model; using System.Text; namespace MultiTerm.Core.ViewModel; public partial class ConsoleViewModel : TerminalViewModel { public override TerminalViewType ViewType => TerminalViewType.Console; private readonly ILogger logger; private Encoding currentEncoding; /* settings */ private readonly Encoding defaultEncoding = Encoding.ASCII; // default encoding instance private const EncodingType defaultEncodingType = EncodingType.ASCII; // default encoding type private const int DataMaxLength = 5000; // maximum amount of characters stored int the data textbox #region Observable Properties /// /// Holds Console content. /// [ObservableProperty] private string data = string.Empty; /// /// Encoding type of the sent and received messages. /// [ObservableProperty] private EncodingType selectedEncodingType = defaultEncodingType; /// /// Holds message that is to be sent next. E.g. currently being typed in. /// [ObservableProperty] private string sendableMessage = string.Empty; #endregion public ConsoleViewModel(IAppSettingsProvider appSettings, IMessenger messenger, ILogger logger) : base(appSettings, messenger) { this.logger = logger; this.currentEncoding = this.GetEncoding(this.SelectedEncodingType); } public override void DisplayNewReceivedData(IEnumerable newData) { // extract bytes var bytes = newData.Select(b => b.Byte).ToArray(); string newDataDecoded = currentEncoding.GetString(bytes); // calculate new legth int newTotalLength = this.Data.Length + newDataDecoded.Length; // trim current data at the beginning if new length is too long if (newTotalLength > DataMaxLength) { // trim overshoot from start of string this.Data = this.Data[(newTotalLength - DataMaxLength)..]; } // append data this.Data += newDataDecoded; } /// /// Command to send a prepared message. /// [RelayCommand] public void Send() { // encode var encodedBytes = this.currentEncoding.GetBytes(this.SendableMessage); // send if (this.SendToCommunicationProtocol(encodedBytes)) { // add to history this.AddToSendHistory(new StringHistoryElement(this.SendableMessage)); // clear if sending was successful this.SendableMessage = string.Empty; } } protected override void HandleInsertElementFromHistory(object element) { if(element is not StringHistoryElement elementString) { throw new Exception($"'{HandleInsertElementFromHistory}()' in {nameof(ConsoleViewModel)} got wrong type of element. Got Type: {element.GetType()}"); } // overwrite sendable message with history element this.SendableMessage = elementString.Text; } /// /// Command to clear the data that was received. /// [RelayCommand] public void ClearData() { this.Data = string.Empty; } /// /// Handles changing of encoding type. /// /// new value partial void OnSelectedEncodingTypeChanged(EncodingType value) { this.currentEncoding = this.GetEncoding(value); } #region Unused Methods public override void DisplayNewSentData(IEnumerable newData) { // no display of sent data } protected override void ActOnDataDisplayNewlineSeparatorTypeChanged(NewlineSeparatorType newType) { // No change when data display newline separator type changed } #endregion #region Helpers /// /// Returns instance of . /// If the is not supported or any issue arrived, the is set to ASCII and ASCII is returned. /// /// type of encoding /// encoding instance private Encoding GetEncoding(EncodingType encodingType) { Encoding? encoding; try { // Encoding Type value corresponds to codepage number, therefore can be get by cast to int encoding = Encoding.GetEncoding(Convert.ToInt32(encodingType)); } catch (Exception) { // log exception and set encoding to null this.logger.LogWarn($"'{nameof(GetEncoding)}()' failed to resolve encoding type {encodingType} (codepage {Convert.ToInt32(encodingType)}). Reverted to default.", nameof(ConsoleViewModel)); encoding = null; } // failed to get encoding or got null encoding if (encoding == null) { // set selected encoding type to default and return default encoding this.SelectedEncodingType = defaultEncodingType; encoding = defaultEncoding; } return encoding!; } #endregion }