using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Ebel.Hardware.Communications;
using Ebel.Hardware.Communications.Rbs;
using HwComWrapperNETGui.UserControls;
using State = Ebel.Hardware.Communications.Rbs.State;

namespace HwComWrapperNETGui
{
    public partial class HwComForm : Form
    {
        #region Constructors and Destructors

        public HwComForm(IPAddress initialIpAddress)
            : this()
        {
            if (initialIpAddress != null)
            {
                this.mtbIpAdress.Text = initialIpAddress.ToString();
            }
        }

        public HwComForm()
        {
            this.InitializeComponent();
            ExtendWithContextMenu(this.tbLog);

            this.mtbIpAdress.KeyPress += this.OnMtbIpAdressKeyPress;
            this.buttonTCPOpen.Click += this.OnOpenTcpConnection;
            this.buttonClose.Click += this.OnCloseConnection;
            this.buttonGetDLLVersion.Click += this.OnGetDllVersion;
            this.btnGetOnlineDevices.Click += this.OnGetOnlineDevices;
            this.btnGetSlotInfos.Click += this.OnGetSlotInfos;

            var msgCat00 = new MsgCat00();
            msgCat00.ButtonGetVersionClicked += this.OnGetVersion;
            msgCat00.ButtonGetConnectedHardwareClicked += this.OnGetConnectedHw;
            msgCat00.ButtonLockHardwareClicked += this.OnLockHw;
            msgCat00.ButtonUnlockHardwareClicked += this.OnUnLockHw;
            this.tabPage00.Controls.Add(msgCat00);

            var msgCat01 = new MsgCat01();
            msgCat01.ButtonGetNicConfigClicked += this.OnGetNicConfig;
            msgCat01.ButtonSetNicConfigClicked += this.OnSetNicConfig;
            msgCat01.ButtonGetDeviceNameClicked += this.OnGetDeviceName;
            msgCat01.ButtonSetDeviceNameClicked += this.OnSetDeviceName;
            msgCat01.ButtonGetWakeupSleepConfigClicked += this.OnGetWakeupSleepConfig;
            msgCat01.ButtonSetWakeupSleepConfigClicked += this.OnSetWakeupSleepConfig;
            msgCat01.ButtonGetTerminationConfigClicked += this.OnGetTerminationConfig;
            msgCat01.ButtonSetTerminationConfigClicked += this.OnSetTerminationConfig;

            msgCat01.ButtonGetSwSleepConfigClicked += this.OnGetSwSleepConfig;
            msgCat01.ButtonSetSwSleepConfigClicked += this.OnSetSwSleepConfig;
            msgCat01.ButtonGetWifiConfigClicked += this.OnGetWifiConfigConfig;
            msgCat01.ButtonSetWifiConfigClicked += this.OnSetWifiConfigConfig;
            msgCat01.ButtonGetWifiInfoClicked += this.OnGetWifiInfo;

            this.tabPage01.Controls.Add(msgCat01);

            var msgCat02 = new MsgCat02();
            msgCat02.ButtonDownloadClicked += this.OnDownload;
            msgCat02.ButtonDownloadDestClicked += this.OnDownloadDest;
            msgCat02.ButtonDownloadFPGAClicked += this.OnDownloadFpga;
            this.tabPage02.Controls.Add(msgCat02);

            var msgCat03 = new MsgCat03();
            msgCat03.ButtonGetHwConfigClicked += this.OnGetHwConfig;
            msgCat03.ButtonGetLicensesConfigClicked += this.OnGetLicenseConfig;
            msgCat03.ButtonGetSwConfigClicked += this.OnGetSwConfig;
            msgCat03.ButtonGetFPGAConfigClicked += this.OnGetFpgaConfig;
            msgCat03.ButtonGetFPGAImagesInfoClicked += this.OnGetFpgaImagesInfo;
            msgCat03.ButtonGetMountStatesClicked += this.OnGetMountStates;
            msgCat03.ButtonGetSetTransceiverStateClicked += this.OnGetSetTransceiverState;
            msgCat03.ButtonGetRtcClicked += this.OnGetRtcClicked;
            msgCat03.ButtonSetRtcClicked += this.OnSetRtcClicked;
            msgCat03.ButtonSetActiveApplicationClicked += this.OnSetActiveApplicationClicked;
            msgCat03.ButtonGetActiveApplicationClicked += this.OnGetActiveApplicationClicked;
            msgCat03.ButtonGetApplicationsVersionClicked += this.OnGetApplicationsVersionClicked;
            this.tabPage03.Controls.Add(msgCat03);

            var msgCat04 = new MsgCat04();
            msgCat04.ButtonCpuRunClicked += this.OnCpuRun;
            msgCat04.ButtonCpuStopClicked += this.OnCpuStop;
            msgCat04.ButtonCpuResetClicked += this.OnCpuReset;
            this.tabPage04.Controls.Add(msgCat04);

            var msgCat05 = new MsgCat05();
            msgCat05.ButtonAppStartClicked += this.OnAppStart;
            msgCat05.ButtonAppStopClicked += this.OnAppStop;
            msgCat05.ButtonStatusClicked += this.OnGetStatus;
            this.tabPage05.Controls.Add(msgCat05);

            var msgCat81 = new MsgCat81();
            msgCat81.ButtonStreamStartClicked += this.OnStartStream;
            msgCat81.ButtonStreamStopClicked += this.OnStopStream;
            msgCat81.ButtonStreamReceiveClicked += this.OnStreamReceive;
            this.tabPage81.Controls.Add(msgCat81);

            var msgCat82 = new MsgCat82();
            msgCat82.ButtonChangeSignalClicked += this.OnChangeSignal;
            msgCat82.ButtonChangePDUClicked += this.OnChangePdu;
            msgCat82.ButtonChangeMessageClicked += this.OnChangeMsg;
            msgCat82.ButtonChangeControlClicked += this.OnChangeControl;
            this.tabPage82.Controls.Add(msgCat82);

            var msgCat83 = new MsgCat83();
            msgCat83.ButtonGetRBSStatusClicked += this.OnGetRbsStatus;
            msgCat83.ButtonECUControlClicked += this.OnEcuControlClicked;
            msgCat83.ButtonGetRBSTimestampClicked += this.OnTimeStamp;
            msgCat83.ButtonGetRBSVersionClicked += this.OnRBSVersion;
            msgCat83.ButtonGetVersionStringClicked += this.OnVersionString;
            msgCat83.ButtonGetRBSManipulationActiveClicked += this.OnIsRbsManipulationActive;
            msgCat83.ButtonStartRBSManipulationClicked += (sender, args) =>
            {
                this.rbsSequenceDialog.SetCyclic(false);
                this.OnStartRbsManipulation(sender, args);
            };

            msgCat83.ButtonStartRBSManipulationCyclicClicked += (sender, args) =>
            {
                this.rbsSequenceDialog.SetCyclic(true);
                this.OnStartRbsManipulation(sender, args);
            };

            msgCat83.ButtonStopRBSManipulationClicked += this.OnStopRbsManipulation;
            msgCat83.ButtonSaveRBSManipulationClicked += this.OnSaveManipulation;
            msgCat83.ButtonDeleteRBSManipulationClicked += this.OnDeleteManipulation;
            msgCat83.ButtonSetValueClicked += this.OnSetValue;
            msgCat83.ButtonGetValueClicked += this.OnGetValue;
            msgCat83.ButtonGetRBSChannelsInfoClicked += this.OnGetRbsChannelInfos;
            msgCat83.ButtonGetFrOffsetCtrlStatesClicked += this.OnGetFrOffsetCtrlStates;
            msgCat83.ButtonECUShutdownClicked += this.OnEcuShutdownClicked;
            msgCat83.ButtonServiceControlClicked += this.OnServiceControlClicked;
            msgCat83.ButtonServiceGetStateClicked += this.OnServiceGetStateClicked;
            msgCat83.ButtonChangeRbsApplicationType += this.OnChangeRbsApplicationTypeClicked;
            msgCat83.ButtonGetActiveManipulationsClicked += this.OnGetRbsActiveManipulationsClicked;
            msgCat83.ButtonGetManipulationStatusClicked += this.OnGetRBSManipulationStatus;
            msgCat83.ButtonStartRbsManipulation64Clicked += (sender, args) => this.OnStartRbsManipulation64(false);
            msgCat83.ButtonStartRbsManipulationCyclic64Clicked += (sender, args) => this.OnStartRbsManipulation64(true);
            msgCat83.ButtonAddRbsManipulation64Clicked += this.OnAddRbsManipulation64;
            msgCat83.ButtonRemoveRbsManipulation64Clicked += this.OnRemoveRbsManipulation64;
            msgCat83.ButtonStopRbsManipulation64Clicked += this.OnStopRbsManipulation64;
            msgCat83.ButtonGetActiveManipulations64Clicked += this.OnGetRbsActiveManipulations64Clicked;
            msgCat83.ButtonGetManipulationStatus64Clicked += this.OnGetRbsManipulationStatus64;
            this.tabPage83.Controls.Add(msgCat83);
            MsgCat83 = msgCat83;

            var msgCat84 = new MsgCat84();
            msgCat84.ButtonResetAllFiltersClicked += this.OnResetAllFilters;
            msgCat84.ButtonSetChannelConfigurationClicked += this.OnSetChannelConfiguration;
            msgCat84.ButtonSetFilterConfigurationClicked += this.OnSetFilterConfiguration;
            msgCat84.ButtonSendMessageClicked += this.OnSendMessage;
            msgCat84.ButtonStartAnalyzerClicked += this.OnStartAnalyzer;
            msgCat84.ButtonStopAnalyzerClicked += this.OnStopAnalyzer;
            msgCat84.ButtonAnalyzerVersionClicked += this.OnAnalyzerVersion;
            msgCat84.ButtonAnalyzerConfigureClicked += this.OnAnalyzerConfigure;
            msgCat84.ButtonAnalyzerStartChannelClicked += this.OnAnalyzerStartChannel;
            msgCat84.ButtonAnalyzerStopChannelClicked += this.OnAnalyzerStopChannel;
            msgCat84.ButtonAnalyzerPersistenceControlClicked += this.OnAnalyzerPersistenceControl;
            msgCat84.ButtonAnalyzerConfigurePTPTimeSyncClicked += this.OnAnalyzerPTPTimeSyncConfigure;
            msgCat84.btnLoggingConfig.Click += this.OnAnalyzerLoggingConfigure;
            this.tabPage84.Controls.Add(msgCat84);

            var msgCat85 = new MsgCat85();
            msgCat85.ButtonStartAllLoggerClicked += this.OnLoggingStartAll;
            msgCat85.ButtonStopAllLoggerClicked += this.OnLoggingStopAll;
            msgCat85.ButtonGetLoggingActivenClicked += this.OnGetLoggingActive;
            msgCat85.ButtonGetLoggingVersionClicked += this.OnGetLoggingVersion;
            this.tabPage85.Controls.Add(msgCat85);

            var msgCat86 = new MsgCat86();
            msgCat86.ButtonReplayConfigClicked += this.OnSetReplayConfiguration;
            msgCat86.ButtonReplayControlClicked += this.OnSetReplayControl;
            msgCat86.ButtonReplayStreamClicked += this.OnSetReplayStream;
            msgCat86.ButtonGetReplayStatisticsClicked += this.OnGetReplayStatistics;
            this.tabPage86.Controls.Add(msgCat86);
            // Assign Form to a global variable, used in order to update statistics list 
            MsgCat86 = msgCat86;

            this.UpdateButtons();
            this.Init();
        }

        #endregion

        #region Methods

        private static void ExtendWithContextMenu(RichTextBox rtb)
        {
            ContextMenuStrip ctx = new ContextMenuStrip();

            ToolStripMenuItem cut = new ToolStripMenuItem("Cut", null, (sender, e) => rtb.Cut());

            ToolStripMenuItem copy = new ToolStripMenuItem("Copy", null, (sender, e) => rtb.Copy());

            ToolStripMenuItem paste = new ToolStripMenuItem("Paste", null, (sender, e) => rtb.Paste());

            ctx.Items.Add(cut);
            ctx.Items.Add(copy);
            ctx.Items.Add(paste);

            rtb.ContextMenuStrip = ctx;

            ctx.Opening +=
                (sender, e) =>
                    {
                        bool noSelectedText = string.IsNullOrEmpty(rtb.SelectedText);
                        cut.Enabled = !noSelectedText;
                        copy.Enabled = !noSelectedText;

                        bool noClipboardText = string.IsNullOrEmpty(Clipboard.GetText());
                        paste.Enabled = !noClipboardText;
                    };
        }

        private void Init()
        {
            var dllVersion = Communication.DLLVersion;
            if (dllVersion != null)
            {
                this.PrintValue("HwCom.dll Version:", dllVersion);
            }
        }

        private void OnGetMountStates(object sender, EventArgs e)
        {
            var mountStates = this.com.GetFileSystemMountStates().ToList();
            this.PrintResult("GetFileSystemMountStates", this.com.LastResult);
            this.PrintValue("Count:", mountStates.Count);
            for (int i = 0; i < mountStates.Count; i++)
            {
                this.PrintValue(string.Format("MountStates[{0}]: ", i), mountStates[i]);
            }
        }

        private void OnGetSetTransceiverState(object sender, GetSetTransceiverStateEventArgs e)
        {
            TransceiverStateInfo transceiverStateInfo = e.transceiverStateInfo;
            TransceiverStateInfo returnedInfo = this.com.GetSetTransceiverState(transceiverStateInfo);
            this.PrintResult("GetSetTransceiverState", this.com.LastResult);

            if (this.com.LastResult.Ok)
            {
                this.PrintValue("TransceiverState:\n", returnedInfo);
            }
        }

        private void OnSetRtcClicked(object sender, EventArgs e)
        {
            RtcDateTime dateTime = new RtcDateTime();
            this.PrintValue("Set Date and Time: ", dateTime);
            this.PrintResult("SetRtcReq", this.com.SetRtcDateTime(dateTime));
        }

        private void OnGetRtcClicked(object sender, EventArgs e)
        {
            RtcDateTime returnedInfo = this.com.GetRtcDateTime();
            this.PrintResult("GetRtcReq", this.com.LastResult);

            if (this.com.LastResult.Ok)
            {
                this.PrintValue("RTC Date and Time:\n", returnedInfo);
            }
        }

        private void OnSetActiveApplicationClicked(object sender, ActiveApplicationArgs e)
        {
            this.PrintResult("SetActiveApplicationReq", this.com.SetActiveApplication(e.ActiveApplication));
        }

        private void OnGetActiveApplicationClicked(object sender, EventArgs e)
        {
            ActiveApplication returnedInfo = this.com.GetActiveApplication();
            this.PrintResult("GetActiveApplication", this.com.LastResult);

            if (this.com.LastResult.Ok)
            {
                this.Print("\nActive Applications:\n");
                for (int i = 0; i < returnedInfo.Count; i++)
                {
                    this.Print(string.Format("Application {0}: Type = {1} ; Slot = {2}\n", i,
                        Enum.GetName(typeof(ApplicationType), returnedInfo.Applications[i].Type),
                        returnedInfo.Applications[i].ApplicationSlot));
                }
            }
        }

        private void OnGetApplicationsVersionClicked(object sender, EventArgs e)
        {
            ApplicationsVersion returnedInfo = this.com.GetApplicationsVersion();
            this.PrintResult("GetApplicationsVersion", this.com.LastResult);

            if (this.com.LastResult.Ok)
            {
                this.Print("\nApplications Version:\n");
                for (int i = 0; i < returnedInfo.Count; i++)
                {
                    var app = returnedInfo.ApplicationVersion[i];
                    string typeName = Enum.IsDefined(typeof(ApplicationVersionType), (int)app.Type)
                        ? Enum.GetName(typeof(ApplicationVersionType), app.Type)
                        : "Unknown";

                    this.Print(string.Format(
                        "Application {0}: Type = {1} ({2}); Version = {3}.{4}.{5}.{6}\n",
                        i, typeName, (int)app.Type, app.Version0, app.Version1, app.Version2, app.Version3
                    ));
                }
            }
        }

        private void OnGetFrOffsetCtrlStates(object sender, EventArgs e)
        {
            var offsetCtrlStates = this.com.GetRbsFrOffsetControlStates().ToList();
            this.PrintResult("GetFrOffsetControlStates", this.com.LastResult);
            this.PrintValue("Count:", offsetCtrlStates.Count);
            for (int i = 0; i < offsetCtrlStates.Count; i++)
            {
                this.PrintValue(string.Format("OffsetControlStates[{0}]: ", i), offsetCtrlStates[i]);
            }
        }

        private void OnGetLoggingVersion(object sender, EventArgs e)
        {
            var version = this.com.GetLoggingVersion();
            this.PrintResult("LoggingVersion", this.com.LastResult);
            if (version != null)
            {
                this.PrintValue("Version:", version);
            }
        }

        private void OnGetLoggingActive(object sender, EventArgs e)
        {
            var active = this.com.GetLoggingActive();
            this.PrintResult("LoggingActive", this.com.LastResult);
            this.PrintValue("Active:", active);
        }

        private void OnLoggingStopAll(object sender, EventArgs e)
        {
            this.PrintResult("LoggingStopAll", this.com.LoggingStopAll());
        }

        private void OnLoggingStartAll(object sender, EventArgs e)
        {
            this.PrintResult("LoggingStartAll", this.com.LoggingStartAll());
        }

        private void OnAnalyzerVersion(object sender, EventArgs e)
        {
            var version = this.com.AnalyzerVersion();
            this.PrintResult("AnalyzerVersion", this.com.LastResult);
            if (version != null)
            {
                this.PrintValue("Version:", version);
            }
        }

        private void OnAnalyzerConfigure(object sender, AnalyzerConfigureEventArgs e)
        {
            this.PrintResult("AnalyzerConfig", this.com.AnalyzerConfig(e.AnalyzerConfiguration));
        }

        private void OnAnalyzerStartChannel(object sender, AnalyzerChannelStartEventArgs e)
        {
            DateTime dateTime;
            this.PrintResult("AnalyzerStartChannel", this.com.AnalyzerStartChannel(e.ChannelId, out dateTime));
            this.PrintLine(string.Format("DateTime: {0}", dateTime));
        }

        private void OnAnalyzerStopChannel(object sender, AnalyzerChannelStopEventArgs e)
        {
            this.PrintResult("AnalyzerStopChannel", this.com.AnalyzerStopChannel(e.ChannelId));
        }

        private void OnAnalyzerPersistenceControl(object sender, AnalyzerPersistenceControlEventArgs e)
        {
            this.PrintResult("AnalyzerPersistenceControl", this.com.AnalyzerPersistenceControl(e.PersistenceCmd));
        }

        private void OnAnalyzerPTPTimeSyncConfigure(object sender, AnalyzerPTPTimeSyncConfigEventArgs e)
        {
            this.PrintResult("AnalyzerConfigurePTPTimeSync", this.com.ConfigurePTPTimeSync(e.timeSyncConfig));
        }

        private void OnAnalyzerLoggingConfigure(object sender, EventArgs e)
        {
            // Open Dialog
            var dlg = new AnalyzerLoggingConfigurationDialog();

            // Check if latest is stored
            if (this.uselatestLogging)
            {
                dlg.nudChannelID.Value = (decimal)this.latestLoggingConfig.ChannelID;
                dlg.nudReferenceTimeChannelID.Value = (decimal)this.latestLoggingConfig.ReferenceTimeChannelID;
                dlg.nudReferenceTimeChannelSlotID.Value = (decimal)this.latestLoggingConfig.ReferenceTimeChannelSlotID;
                dlg.nudMaxFileSize.Value = (decimal)this.latestLoggingConfig.MaxFileSize;
                dlg.nudPreLoggingRange.Value = (decimal)this.latestLoggingConfig.PreLoggingRange;
                dlg.nudPostLoggingRange.Value = (decimal)this.latestLoggingConfig.PostLoggingRange;
                dlg.comboBoxFileFormat.SelectedItem = (LoggingFileFormat)this.latestLoggingConfig.FileFormat;
                dlg.comboBoxFilePath.SelectedItem = (LoggingFilePath)this.latestLoggingConfig.FilePath;
                dlg.comboBoxLoggingBehaviour.SelectedItem = (LoggingLoggingBehaviour)this.latestLoggingConfig.LoggingBehaviour;
                dlg.comboBoxTimeOption.SelectedItem = (LoggingTimeOption)this.latestLoggingConfig.TimeOption;
                dlg.comboBoxTimeOption.SelectedItem = (LoggingStartupBehaviour)this.latestLoggingConfig.StartupBehaviour;
                dlg.textBoxPrefix.Text = this.latestLoggingPrefix;
                dlg.textBoxSubFolder.Text = this.latestLoggingSubFolder;
            }

            if (dlg.ShowDialog(this) == DialogResult.OK)
            {
                // When Dialog Closes with OK, Map Request Config
                this.latestLoggingConfig.ChannelID = (byte)dlg.nudChannelID.Value;
                this.latestLoggingConfig.ReferenceTimeChannelID = (byte)dlg.nudReferenceTimeChannelID.Value;
                this.latestLoggingConfig.ReferenceTimeChannelSlotID = (byte)dlg.nudReferenceTimeChannelSlotID.Value;
                this.latestLoggingConfig.MaxFileSize = (ushort)dlg.nudMaxFileSize.Value;
                this.latestLoggingConfig.PreLoggingRange = (uint)dlg.nudPreLoggingRange.Value;
                this.latestLoggingConfig.PostLoggingRange = (uint)dlg.nudPostLoggingRange.Value;

                // Handle Enum Values
                LoggingFileFormat FileFormat;
                Enum.TryParse<LoggingFileFormat>(dlg.comboBoxFileFormat.SelectedValue.ToString(), out FileFormat);
                LoggingTimeOption TimeOption;
                Enum.TryParse<LoggingTimeOption>(dlg.comboBoxTimeOption.SelectedValue.ToString(), out TimeOption);
                LoggingFilePath FilePath;
                Enum.TryParse<LoggingFilePath>(dlg.comboBoxFilePath.SelectedValue.ToString(), out FilePath);
                LoggingStartupBehaviour StartupBehaviour;
                Enum.TryParse<LoggingStartupBehaviour>(dlg.comboBoxStartupBehaviour.SelectedValue.ToString(), out StartupBehaviour);
                LoggingLoggingBehaviour LoggingBehaviour;
                Enum.TryParse<LoggingLoggingBehaviour>(dlg.comboBoxLoggingBehaviour.SelectedValue.ToString(), out LoggingBehaviour);
                this.latestLoggingConfig.FileFormat = (byte)FileFormat;
                this.latestLoggingConfig.TimeOption = (byte)TimeOption;
                this.latestLoggingConfig.FilePath = (byte)FilePath;
                this.latestLoggingConfig.StartupBehaviour = (byte)StartupBehaviour;
                this.latestLoggingConfig.LoggingBehaviour = (byte)LoggingBehaviour;
                this.latestLoggingPrefix = dlg.textBoxPrefix.Text;
                this.latestLoggingSubFolder = dlg.textBoxSubFolder.Text;
                this.uselatestLogging = true;

                // Send Request and print result
                this.PrintResult("AnalyzerConfigureLogging", this.com.ConfigureLogging(this.latestLoggingConfig, dlg.textBoxPrefix.Text, dlg.textBoxSubFolder.Text));

                // Close Dialog
                return;
            }
        }

        private void OnSetReplayConfiguration(object sender, ReplayConfigureEventArgs e)
        {
            this.PrintResult("ReplayConfigure", this.com.ReplayConfig(e.ReplayConfig));
        }

        private void OnSetReplayControl(object sender, ReplayControlEventArgs e)
        {
            this.PrintResult("ReplayControl", this.com.ReplayControl(e.ReplayControl));
        }

        private void OnSetReplayStream(object sender, ReplayStreamEventArgs e)
        {
            /* Test Button disabled */
            for (int i = 0; i < 43; i++)
            {
                this.PrintResult("ReplayStreamContainer add", this.com.ReplayStreamContainerAdd(e.ReplayStream));
            }

            this.PrintResult("ReplayStreamContainer Send", this.com.ReplayStreamContainerSend());
        }

        private void OnGetReplayStatistics(object sender, EventArgs e)
        {
            ReplayStatistics replayStatistics = this.com.GetReplayStatistics();
            this.PrintResult("ReplayStatistics", this.com.LastResult);
            if (replayStatistics != null)
            {
                MsgCat86.UpdateStatisticsList(replayStatistics);
            }
        }

        private void OnAppStart(object sender, EventArgs e)
        {
            this.PrintResult("AppStart", this.com.AppStart());
        }

        private void OnAppStop(object sender, EventArgs e)
        {
            this.PrintResult("AppStop", this.com.AppStop());
        }

        private void OnChangeControl(object sender, ChangeSignalPDUControlEventArgs e)
        {
            this.PrintResult("ChangeControl", this.com.ChangeControl(e.Id, e.Length, e.Value));
        }

        private void OnChangeMsg(object sender, EventArgs e)
        {
            byte[] payload = { 0, 1, 2, 3, 4 };
            this.PrintResult("ChangeMsg", this.com.ChangeMsg(BusTypes.FlexRay, 1, 2, 0, payload));
        }

        private void OnChangePdu(object sender, ChangeSignalPDUControlEventArgs e)
        {
            this.PrintResult("ChangePDU", this.com.ChangePDU(e.Id, e.Length, e.Value));
        }

        private void OnChangeSignal(object sender, ChangeSignalPDUControlEventArgs e)
        {
            this.PrintResult("ChangeSignal", this.com.ChangeSignal(e.Id, e.Length, e.Value));
        }

        private void OnCloseConnection(object sender, EventArgs e)
        {
            if (this.com == null)
            {
                return;
            }

            this.com.Dispose();
            this.com = null;
            this.UpdateButtons();
            this.PrintLine("Connection closed");
        }

        private void OnCpuReset(object sender, EventArgs e)
        {
            this.PrintResult("CPU Reset", this.com.CpuReset());
        }

        private void OnCpuRun(object sender, EventArgs e)
        {
            this.PrintResult("CPU Run", this.com.CpuRun());
        }

        private void OnCpuStop(object sender, EventArgs e)
        {
            this.PrintResult("CPU Stop", this.com.CpuStop());
        }

        private void OnDeleteManipulation(object sender, EventArgs e)
        {
            this.PrintResult("Delete Manipulation", this.com.DeleteRbsManipulation());
        }

        private void OnDownload(object sender, EventArgs e)
        {
            var dlg = new OpenFileDialog();
            if (DialogResult.OK == dlg.ShowDialog())
            {
                this.Print(string.Format(CultureInfo.InvariantCulture, "\r\nStarting download ({0})...", dlg.FileName));
                this.PrintResult("Download", this.com.Download(0, dlg.FileName));
            }
        }

        private void OnDownloadDest(object sender, DownloadDestinationEventArgs e)
        {
            var dlg = new OpenFileDialog();
            if (DialogResult.OK == dlg.ShowDialog())
            {
                this.Print(string.Format(CultureInfo.InvariantCulture, "\r\nStarting download ({0}) to {1}...", dlg.FileName, e.Destination));
                this.PrintResult("Download Destination", this.com.Download(e.Destination, dlg.FileName));
            }
        }

        private void OnDownloadFpga(object sender, EventArgs e)
        {
            var dlg = new OpenFileDialog();
            if (DialogResult.OK == dlg.ShowDialog())
            {
                this.Print(string.Format(CultureInfo.InvariantCulture, "\r\nStarting download FPGA ({0})...", dlg.FileName));
                this.PrintResult("Download FPGA", this.com.Download_FPGA(0, dlg.FileName));
            }
        }

        private void OnEcuControlClicked(object sender, ECUControlEventArgs e)
        {
            if (e.UseFullControl)
            {
                var resultFull = this.com.RBSEcuFullControl(e.ECUNumber, e.ECUOn);
                this.PrintResult("RBSEcuFullControl", resultFull);

                return;
            }

            var result = this.com.RBSEcuControl(BusTypes.FlexRay, 1, e.ECUNumber, e.ECUOn);
            this.PrintResult("RBSEcuControl", result);
        }

        private void OnEcuShutdownClicked(object sender, ECUShutdownEventArgs e)
        {
            var result = this.com.RBSEcuShutdown(e.ECUNumber);
            this.PrintResult("RBSEcuShutdown", result);
        }

        private void OnServiceControlClicked(object sender, ServiceControlEventArgs e)
        {
            var result = this.com.RBSServiceControl(e.serviceControl, e.ServiceOn);
            if (true == e.ServiceOn)
            {
                this.PrintResult("RBSServiceOn", result);
            }
            else
            {
                this.PrintResult("RBSServiceOff", result);
            }
        }

        private void OnServiceGetStateClicked(object sender, ServiceControlEventArgs e)
        {
            var serviceState = this.com.RBSServiceState(e.serviceControl);
            this.PrintResult("GetServiceState", this.com.LastResult);
            if (serviceState != null)
            {
                this.Print(serviceState.ToString());
            }
        }

        private void OnChangeRbsApplicationTypeClicked(object sender, RbsChannelAppTypeListEventArgs e)
        {
            var result = this.com.ChangeRBSApplicationType(e.ChannelAppTypes);
            this.PrintResult("ChangeRbsApplicationType", this.com.LastResult);

            if (result != null)
            {
                this.PrintValue("Changed RBS Application types", result);
            }
        }

        private void OnGetConnectedHw(object sender, EventArgs e)
        {
            HardwareCommunicationInfo info = this.com.GetConnectedHw();
            this.PrintResult("GetConnectedHw", this.com.LastResult);
            if (info != null)
            {
                this.PrintValue("HardwareInfo:", info);
            }
        }

        private void OnGetDeviceName(object sender, EventArgs e)
        {
            var deviceName = this.com.GetDeviceName();
            this.PrintResult("GetDeviceName", this.com.LastResult);
            if (deviceName != null)
            {
                this.PrintValue("DeviceName:", deviceName);
            }
        }

        private void OnGetDllVersion(object sender, EventArgs e)
        {
            using (Communication localCom = new Communication("127.0.0.1", 1500))
            {
                var dllVersion = localCom.GetDLLVersion();
                this.PrintResult("GetDLLVersion", localCom.LastResult);
                if (dllVersion != null)
                {
                    this.PrintValue("Version:", dllVersion);
                }
            }
        }

        private void OnGetFpgaConfig(object sender, EventArgs e)
        {
            List<FpgaInfo> fpgaconfig = this.com.GetFPGAConfig();
            this.PrintResult("GetFPGAConfig", this.com.LastResult);
            if (fpgaconfig != null)
            {
                foreach (FpgaInfo info in fpgaconfig)
                {
                    this.PrintValue(string.Format("FPGaInfo[{0}]:", fpgaconfig.IndexOf(info)), info);
                }
            }
            else
            {
                this.PrintLine("FPGaInfo: Nothing received!");
            }
        }

        private void OnGetFpgaImagesInfo(object sender, EventArgs e)
        {
            var fpgaImagesInfo = this.com.GetFpgaImagesInfo();
            this.PrintResult("GetFpgaImages", this.com.LastResult);
            if (fpgaImagesInfo != null)
            {
                this.PrintValue("FpgaImages:", fpgaImagesInfo);
            }
        }

        private void OnGetHwConfig(object sender, EventArgs e)
        {
            HardwareConfigInfo hwConfigInfo = this.com.GetHwConfig();
            this.PrintResult("GetHwConfig", this.com.LastResult);
            if (hwConfigInfo != null)
            {
                this.PrintValue("HardwareConfig:", hwConfigInfo);

                int count = 0;
                foreach (var fpga in hwConfigInfo.FPGA)
                {
                    if (fpga > FpgaTypes.NotUsed)
                    {
                        this.PrintValue(string.Format("FPGA[{0}]: ", count), string.Format("{0} (0x{1:X4})", fpga, (int)fpga));
                    }
                    else
                    {
                        this.PrintValue(string.Format("FPGA[{0}]: ", count), fpga);
                    }

                    count++;
                }

                count = 0;
                foreach (var tiny in hwConfigInfo.Tiny)
                {
                    this.PrintValue(string.Format("TINY[{0}]: ", count), tiny);
                    count++;
                }
            }
        }

        private void OnGetLicenseConfig(object sender, EventArgs e)
        {
            LicenseConfig licenseConfig = this.com.GetLicenseConfig();
            this.PrintResult("GetLicenseConfig", this.com.LastResult);
            if (licenseConfig != null)
            {
                this.PrintValue("LicenseConfig:", licenseConfig);
            }
        }

        private void OnGetNicConfig(object sender, EventArgs e)
        {
            var nicConfig = this.com.GetNicConfig();
            this.PrintResult("GetNicConfig", this.com.LastResult);
            if (nicConfig != null)
            {
                this.PrintValue("NICConfig:", nicConfig);
            }
        }

        private void OnGetOnlineDevices(object sender, EventArgs eventArgs)
        {
            var dlg = new IpDialog("Enter broadcast address", "192.168.1.255");
            if (dlg.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            IEnumerable<IPAddress> onlineDevices;
            var result = Communication.GetOnlineDevices(dlg.IpAddress, out onlineDevices);
            this.PrintResult("GetOnlineDevices", result);

            // ReSharper disable once PossibleMultipleEnumeration
            this.PrintValue("Online Devices:", onlineDevices.Count());

            // ReSharper disable once PossibleMultipleEnumeration
            foreach (var onlineDevice in onlineDevices)
            {
                this.PrintLine(onlineDevice.ToString());
            }
        }

        private void OnGetSlotInfos(object sender, EventArgs eventArgs)
        {
            this.slotInfos = this.com.GetSlotInfos();

            this.PrintResult("GetSlotInfos", this.com.LastResult);

            if (this.slotInfos == null)
            {
                this.com.SetSlotIndex(0);

                this.slotInfos = new SlotInfos();
                this.slotInfos.Count = 2;
                this.slotInfos.SlotInfo[0] = new SlotInfo();
                this.slotInfos.SlotInfo[1] = new SlotInfo() { SlotIndex = 99 };
            }

            if (this.slotInfos != null)
            {
                this.PrintValue("GetSlotInfos", "\n" + this.slotInfos);
            }

            UpdateSlotIndexComboBox();
        }

        private void cbSlotIndexSelection_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbSlotIndexSelection.SelectedIndex < 0)
            {
                return;
            }

            var result = this.com.SetSlotIndex(this.slotInfos.SlotInfo[this.cbSlotIndexSelection.SelectedIndex].SlotIndex);

            this.PrintResult("SetSlotIndex", result);

            if (!result.Ok)
            {
                this.cbSlotIndexSelection.SelectedIndex = -1;
            }
        }

        private void OnGetRbsStatus(object sender, EventArgs e)
        {
            State rbsState = this.com.GetRBSStatus();
            this.PrintResult("GetRbsStatus", this.com.LastResult);
            if (rbsState != null)
            {
                this.PrintValue("GetRbsStatus:", rbsState);
                if (rbsState.Channels != null)
                {
                    foreach (Channel ch in rbsState.Channels)
                    {
                        this.PrintValue("\t", ch);
                    }
                }
            }
        }

        private void OnGetStatus(object sender, EventArgs e)
        {
            var s = this.com.Status();
            this.PrintResult("Status", this.com.LastResult);
            if (s != null)
            {
                this.PrintValue("State: ", s);
            }
        }

        private void OnGetSwConfig(object sender, EventArgs e)
        {
            SoftwareConfig swConfig = this.com.GetSwConfig();
            this.PrintResult("GetSwConfig", this.com.LastResult);
            if (swConfig != null)
            {
                this.PrintValue("SwConfig:", swConfig);
            }
        }

        private void OnGetSwSleepConfig(object sender, EventArgs e)
        {
            var swSleepConfig = this.com.GetSwSleepConfig();
            this.PrintResult("GetSwSleepConfig", this.com.LastResult);
            if (swSleepConfig != null)
            {
                this.PrintValue("SwSleepConfig:", swSleepConfig);
            }
        }

        private void OnGetTerminationConfig(object sender, EventArgs e)
        {
            var terminationConfig = this.com.GetTerminationConfig();
            this.PrintResult("GetTerminationConfig", this.com.LastResult);
            if (terminationConfig != null)
            {
                this.PrintValue("TerminationConfig:", terminationConfig);
            }
        }

        private void OnGetValue(object sender, GetValueEventArgs e)
        {
            if (e.Length < 1 || e.Length > ushort.MaxValue)
            {
                this.PrintLine("Error: Enter a valid length");
                return;
            }

            var data = new byte[e.Length];
            var result = this.com.GetValue(e.Destination, data);
            this.PrintResult("GetValue", result);
            if (result) //Read data
            {
                this.PrintLine(string.Format("0x{0}", BitConverter.ToString(data).Replace('-', ' ')));

                for (int i = 0; i < e.Length; i++)
                {
                    this.PrintLine(string.Format("Data[{0}] : {1}", i, data[i]));
                }
            }
        }

        private void OnGetRbsChannelInfos(object sender, EventArgs e)
        {
            Version v = this.com.GetVersion();
            if (v != null && v.CompareTo(new Version(1, 13, 0, 0)) <= 0)
            {
                this.PrintLine();
                this.PrintLine("The PC-HW-IF version at the device is <= 1.13");
                this.PrintLine("The parameter TinyType must not be used!");
                this.PrintLine("Reason: The parameter TinyType contains the same values as BusType!");
            }

            var rbsChannelsConfig = this.com.GetRbsChannesConfigs();
            this.PrintResult("GetRbsChannelsConfig", this.com.LastResult);
            if (rbsChannelsConfig != null)
            {
                this.PrintValue("RbsChannelConfig:", rbsChannelsConfig);
            }
        }

        private void OnGetVersion(object sender, EventArgs e)
        {
            Version v = this.com.GetVersion();
            this.PrintResult("GetVersion", this.com.LastResult);
            if (v != null)
            {
                this.PrintValue("Version:", v);
            }
        }

        private void OnGetWakeupSleepConfig(object sender, EventArgs e)
        {
            var wakeupSleepConfig = this.com.GetWakeupSleepConfig();
            this.PrintResult("GetWakeupSleepConfig", this.com.LastResult);
            if (wakeupSleepConfig != null)
            {
                this.PrintLine("WakeupSleepConfig: " + wakeupSleepConfig);
            }
        }

        private void OnIsRbsManipulationActive(object sender, EventArgs e)
        {
            ManipulationState state = this.com.IsRbsManipulationActive();
            this.PrintResult("IsRbsManipulationActive", this.com.LastResult);
            this.PrintValue("Manipulation state:", state);
        }

        private void OnGetRbsActiveManipulationsClicked(object sender, EventArgs e)
        {
            ActiveManipulationsInfos manipulationsInfo = this.com.GetRBSActiveManipulations();
            this.PrintResult("GetRbsActiveManipulations", this.com.LastResult);
            if (null == manipulationsInfo) return; // Done here

            if(0 == manipulationsInfo.Count)
            {
                //Nothing to print
                this.Print("RBS has no active manipulations.");
            }
            else
            {
                // Print Active Manipulations
                this.PrintValue("RBS Active Manipulations:", manipulationsInfo);
            }
        }
        
        private void OnGetRBSManipulationStatus(object sender, EventArgs eventArgs)
        {
            /* ToDo: Allow for more then 1 request via GUI */

            // Get Target Value 
            uint manipulationTarget = MsgCat83.GetManipulationTarget();
            byte sequenceNumber = MsgCat83.GetManipulationSequenceNumber();

            // Setup request
            var manipulationStatusReq = new ManipulationStatusReq();

            // Restrict for single target now
            manipulationStatusReq.Count = 1;
            manipulationStatusReq.ReservedU08 = 0;
            manipulationStatusReq.ReservedU16 = 0; 
            manipulationStatusReq.ManipulationInfo[0].ManipulationTarget = manipulationTarget;
            manipulationStatusReq.ManipulationInfo[0].SequenceNumber = sequenceNumber;
            manipulationStatusReq.ManipulationInfo[0].EmptyU08 = 0;
            manipulationStatusReq.ManipulationInfo[0].EmptyU64 = 0;

            // Get response 
            ManipulationStatusRes manipulationStatusRes = this.com.GetRBSManipulationStatus(manipulationStatusReq);
            this.PrintResult("GetRbsManipulationStatus", this.com.LastResult);
            if (null == manipulationStatusRes) return;

            // Print response 
            if (0 == manipulationStatusRes.Count)
            {
                this.PrintValue("Failed to get RBS Manipulation Status for:", manipulationTarget);
            }
            else
            {
                this.PrintValue("RBS Manipulation Status:", manipulationStatusRes);
            }
        }

        private void OnGetRbsManipulationStatus64(object sender, EventArgs eventArgs)
        {
            var manipulationStatusRes = com.GetRBSManipulationStatus64(MsgCat83.ManipulationUIDs);
            PrintResult("GetRbsManipulationStatus64", com.LastResult);
            if (null == manipulationStatusRes) return;

            // Print response 
            PrintValue("RBS Manipulation Status:\n", manipulationStatusRes);
        }

        private void OnGetRbsActiveManipulations64Clicked(object sender, EventArgs e)
        {
            var uids = com.GetRBSActiveManipulations64()?.ToList();
            PrintResult("GetRbsActiveManipulations64", com.LastResult);
            if (null == uids) return; // Done here

            MsgCat83.AddManipulationUids(uids);

            if (0 == uids.Count)
            {
                //Nothing to print
                Print("RBS has no active manipulations.");
            }
            else
            {
                // Print Active Manipulations
                PrintValue("RBS Active Manipulations:", string.Join(", ", uids));
            }
        }

        private void OnLockHw(object sender, LockHardwareEventArgs e)
        {
            this.PrintResult("LockHw", this.com.LockHardware(e.HardwareId, e.Timeout));
        }

        private void OnMtbIpAdressKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                this.OnOpenTcpConnection(sender, e);
            }
        }

        private void OnOpenTcpConnection(object sender, EventArgs e)
        {
            this.com = new Communication(this.mtbIpAdress.Text, Convert.ToUInt16(this.nbdPort.Value));
            if (!this.com.IsValid)
            {
                this.PrintResult("Creation", new Result(ResultType.Failed));
                this.com.Dispose();
                this.com = null;
            }
            else
            {
                this.PrintResult("Creation", new Result(ResultType.Ok));
            }

            this.UpdateButtons();
        }

        private void OnResetAllFilters(object sender, ResetAllFiltersEventArgs e)
        {
            this.PrintResult("AnalyzerResetAllFilters", this.com.AnalyzerResetAllFilters(e.BusType, e.ChannelId));
        }

        private void OnSaveManipulation(object sender, EventArgs e)
        {
            this.PrintResult("Save Manipulation", this.com.SaveRbsManipulation());
        }

        private void OnSendMessage(object sender, SendMessageEventArgs e)
        {
            this.PrintResult("AnalyzerSendMessage", this.com.AnalyzerSendMessage(e.MessageConfiguration));
        }

        private void OnSetChannelConfiguration(object sender, ChannelConfigurationsEventArgs e)
        {
            foreach (var channelConfiguration in e.ChannelConfigurations)
            {
                TimestampType timestampType;
                var result = this.com.AnalyzerConfigureChannel(channelConfiguration, out timestampType);
                this.PrintResult("AnalyzerConfigureChannel", result);
                if (!result.Ok)
                {
                    return;
                }

                this.PrintLine(string.Format("Timestamp type: {0}", timestampType));
            }
        }

        private void OnSetDeviceName(object sender, DeviceNameEventArgs e)
        {
            var result = this.com.SetDeviceName(e.DeviceName);
            this.PrintResult("SetDeviceName", result);
            if (result)
            {
                this.PrintValue("DeviceName:", e.DeviceName);
            }
        }

        private void OnSetFilterConfiguration(object sender, FilterConfigurationEventArgs e)
        {
            this.PrintResult("AnalyzerConfigureFilter", this.com.AnalyzerConfigureFilter(e.FilterConfiguration));
        }

        private void OnSetNicConfig(object sender, NICConfigEventArgs e)
        {
            var result = this.com.SetNicConfig(e.NICConfig);
            this.PrintResult("SetNicConfig", result);
            if (result)
            {
                this.PrintValue("NICConfig:", e.NICConfig);
            }
        }

        private void OnSetSwSleepConfig(object sender, SoftwareSleepConfigEventArgs e)
        {
            Debug.Assert(
                e.SoftwareSleepConfig != null
                && (e.SoftwareSleepConfig.SoftwareSleepInfo == ConfigState.Disabled || e.SoftwareSleepConfig.SoftwareSleepInfo == ConfigState.Enabled));

            var result = this.com.SetSwSleepConfig(e.SoftwareSleepConfig.SoftwareSleepInfo == ConfigState.Enabled);
            this.PrintResult("SetSwSleepConfig", result);
        }

        private void OnGetWifiConfigConfig(object sender, EventArgs e)
        {
            var wifiConfig = this.com.GetWifiConfig();
            this.PrintResult("GetWifiConfig", this.com.LastResult);
            if (wifiConfig != null)
            {
                this.PrintValue("WifiConfig:", wifiConfig);
            }
        }

        private void OnSetWifiConfigConfig(object sender, WifiConfigEventArgs e)
        {
            var result = this.com.SetWifiConfig(e.WifiConfig);
            this.PrintResult("SetWifiConfig", result);
        }

        private void OnGetWifiInfo(object sender, EventArgs e)
        {
            var result = this.com.GetWifiInformation();
            this.PrintResult("GetWifiInformation", this.com.LastResult);
            if (result != null)
            {
                this.PrintValue("WifiInfo:", result);
            }
        }

        private void OnSetTerminationConfig(object sender, TerminationConfigEventArgs e)
        {
            var terminationConfig = this.com.SetTerminationConfig(e.TerminationConfig);
            this.PrintResult("SetTerminationConfig", this.com.LastResult);
            if (terminationConfig != null)
            {
                this.PrintValue("TerminationConfig:", terminationConfig);
            }
        }

        private void OnSetValue(object sender, SetValueEventArgs e)
        {
            this.PrintResult("SetValue", this.com.SetValue(e.Destination, e.Value));
        }

        private void OnSetWakeupSleepConfig(object sender, WakeupSleepConfigEventArgs e)
        {
            var wakeupSleepConfig = this.com.SetWakeupSleepConfig(e.WakeupSleepConfig);
            this.PrintResult("SetWakeupSleepConfig", this.com.LastResult);
            if (wakeupSleepConfig != null)
            {
                this.PrintValue("WakeupSleepConfig:", wakeupSleepConfig);
            }
        }

        private void OnStartAnalyzer(object sender, StartAnalyzerEventArgs e)
        {
            this.PrintResult("AnalyzerStart", this.com.AnalyzerStart(e.Port));
        }

        private void OnStartRbsManipulation(object sender, EventArgs e)
        {
            if (this.rbsSequenceDialog.ShowDialog(this) == DialogResult.OK)
            {
                this.PrintResult(
                    "StartRbsManipulation (Cyclic=" + this.rbsSequenceDialog.Cyclic.ToString() + ")",
                    this.com.StartRbsManipulation(this.rbsSequenceDialog.RbsManipulationSequence, this.rbsSequenceDialog.Cyclic));
            }
        }

        private void OnAddRbsManipulation64(object sender, EventArgs e)
        {
            var manipulation64Dialog = new Manipulation64Dialog();

            using (manipulation64Dialog)
            {
                if (manipulation64Dialog.ShowDialog(this) == DialogResult.OK)
                {
                    var manipulations = manipulation64Dialog.RbsManipulations64;


                    if (manipulation64Dialog.StartManipulations)
                    {
                        var startedUids = com.AddAndStartRbsManipulation64(manipulations, manipulation64Dialog.Cyclic);
                        startedUids = startedUids ?? new List<ulong>();

                        this.PrintResult(
                            $"AddAndStartRbsManipulations (UIDs={string.Join(", ", startedUids)})", com.LastResult);
                        MsgCat83.AddManipulationUids(startedUids);
                    }
                    else
                    {
                        var uids = new List<ulong>();
                        foreach (var manipulation64 in manipulations)
                        {
                            var uid = com.AddRbsManipulation64(manipulation64);
                            if (uid != null)
                            {
                                uids.Add((ulong)uid);
                            }

                            PrintResult($"AddRbsManipulation (UID={uid})", com.LastResult);
                        }

                        MsgCat83.AddManipulationUids(uids);
                    }
                }
            }
        }


        private void OnStartRbsManipulation64(bool cyclic)
        {
            var startedUids = com.StartRbsManipulation64(MsgCat83.ManipulationUIDs, cyclic)?.ToList();
            PrintResult($"StartRbsManipulation64 (Cyclic={cyclic})", com.LastResult);
            if (null == startedUids) return; // Done here

            if (0 == startedUids.Count)
            {
                Print("No manipulation started.");
            }
            else
            {
                PrintValue("Started Manipulations:", string.Join(", ", startedUids));
            }
        }

        private void OnStartStream(object sender, EventArgs e)
        {
            this.PrintResult("StartStream", this.com.StreamStart(BusTypes.FlexRay, 1));
        }

        private void OnStopAnalyzer(object sender, EventArgs e)
        {
            this.PrintResult("AnalyzerStop", this.com.AnalyzerStop());
        }

        private void OnStopRbsManipulation(object sender, EventArgs e)
        {
            this.PrintResult("StopRbsManipulation", this.com.StopRbsManipulation());
        }

        private void OnRemoveRbsManipulation64(object sender, EventArgs e)
        {
            var removedUids = com.RemoveRbsManipulation64(MsgCat83.ManipulationUIDs)?.ToList();
            PrintResult("RemoveRbsManipulation64", com.LastResult);
            if (null == removedUids) return; // Done here

            if (0 == removedUids.Count)
            {
                Print("No manipulation removed.");
            }
            else
            {
                PrintValue("Removed Manipulations:", string.Join(", ", removedUids));
            }
        }

        private void OnStopRbsManipulation64(object sender, EventArgs e)
        {
            var stoppedUids = com.StopRbsManipulation64(MsgCat83.ManipulationUIDs)?.ToList();
            PrintResult("StopRbsManipulation64", com.LastResult);
            if (null == stoppedUids) return; // Done here

            if (0 == stoppedUids.Count)
            {
                Print("No manipulation stopped.");
            }
            else
            {
                PrintValue("Stopped Manipulations:", string.Join(", ", stoppedUids));
            }
        }

        private void OnStopStream(object sender, EventArgs e)
        {
            this.PrintResult("StopStream", this.com.StreamStop(BusTypes.FlexRay, 1));
        }

        private void OnStreamReceive(object sender, EventArgs e)
        {
            IList<StreamPacket> packets = this.com.StreamReceive(BusTypes.FlexRay, 1);
            this.PrintResult("StreamReceive", this.com.LastResult);
            if (packets != null)
            {
                this.PrintValue("Packets received:", packets.Count);
                foreach (StreamPacket packet in packets)
                {
                    this.PrintLine(packet.ToString());
                }
            }
            else
            {
                this.PrintLine("No packets received!");
            }
        }

        private void OnTimeStamp(object sender, EventArgs e)
        {
            DateTime timestamp = this.com.GetTimeStamp();
            this.PrintResult("GetTimeStamp", this.com.LastResult);
            this.PrintValue("RBS TimeStamp:", timestamp);
        }

        private void OnUnLockHw(object sender, LockHardwareEventArgs e)
        {
            this.PrintResult("UnLockHw", this.com.UnLockHardware(e.HardwareId));
        }

        private void OnRBSVersion(object sender, EventArgs e)
        {
            Version v = this.com.GetRBSVersion();
            this.PrintResult("GetRBSVersion", this.com.LastResult);
            if (v != null)
            {
                this.PrintValue("RBS Version:", v);
            }
        }

        private void OnVersionString(object sender, EventArgs e)
        {
            string versionstring = this.com.GetVersionString();
            this.PrintResult("GetVersionString", this.com.LastResult);
            this.PrintValue("VersionString:", versionstring);
        }

        private void Print(string s)
        {
            this.tbLog.AppendText(s);

            this.tbLog.Select(this.tbLog.Text.Length, 0);
            this.tbLog.ScrollToCaret();
        }

        private void PrintLine(string s)
        {
            this.tbLog.AppendText(s);
            this.PrintLine();
        }

        private void PrintLine()
        {
            this.Print(Environment.NewLine);
        }

        private void PrintResult(string s, Result result)
        {
            this.PrintLine();
            this.PrintLine(
                result
                    ? string.Format("{0} succeeded!\r\n\tResult Code: \t{1}\r\n\tMessage: \t{2}", s, result.ResultType, result.Message)
                    : string.Format("{0} failed!\r\n\tError Code: \t{1}\r\n\tMessage: \t{2}", s, result.ResultType, result.Message));
        }

        private void PrintValue(string s, object value)
        {
            this.PrintLine(string.Format(CultureInfo.InvariantCulture, "{0} {1}", s, value));
        }

        private void UpdateButtons()
        {
            var enabled = this.com != null;
            this.mtbIpAdress.Enabled = !enabled;
            this.nbdPort.Enabled = !enabled;
            this.buttonTCPOpen.Enabled = !enabled;
            this.buttonClose.Enabled = enabled;
            this.cbSlotIndexSelection.Enabled = enabled && this.slotInfos != null;
            this.btnGetSlotInfos.Enabled = enabled;
            foreach (TabPage tabPage in this.tabControl1.TabPages)
            {
                tabPage.Enabled = enabled;
            }
        }

        private void UpdateSlotIndexComboBox()
        {
            this.cbSlotIndexSelection.Enabled = this.slotInfos != null && this.slotInfos.Count > 0;
            this.cbSlotIndexSelection.Items.Clear();

            if (this.slotInfos != null)
            {
                for (var i = 0; i < this.slotInfos.Count; i++)
                {
                    this.cbSlotIndexSelection.Items.Add(this.slotInfos.SlotInfo[i].SlotIndex.ToString());
                }

                this.cbSlotIndexSelection.SelectedIndex = 0;
            }
        }

        #endregion

        #region Constants and Fields

        private readonly RbsSequenceDialog rbsSequenceDialog = new RbsSequenceDialog();
        private Communication com;
        private SlotInfos slotInfos;
        private readonly MsgCat86 MsgCat86;
        private readonly MsgCat83 MsgCat83;
        private readonly LoggingConfiguration latestLoggingConfig = new LoggingConfiguration(); // Latest Analyzer logging configuration used
        private string latestLoggingPrefix; // latest used Analyzer logging prefix
        private string latestLoggingSubFolder; // latest used Analyzer logging prefix
        private bool uselatestLogging = false;
        #endregion
    }
}
