// HardwareDialog.cs created with MonoDevelop
// User: klose at 15:03 03.02.2009
// CVS release: $Id: HardwareDialog.cs,v 1.48 2011-06-15 15:52:58 klose Exp $
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2009  Thomas Klose, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;

using Glade;

using Gtk;

using Hiperscan.QuickStep.Figure;
using Hiperscan.SGS;
using Hiperscan.SGS.Common;
using Hiperscan.SGS.SerialInterface;
using Hiperscan.Spectroscopy;
using Hiperscan.Spectroscopy.IO;
using Hiperscan.Unix;


namespace Hiperscan.QuickStep.Dialog
{

    public class ServiceDialog
    {
        [Widget] Gtk.Label vendor_label                = null;
        [Widget] Gtk.Label product_label               = null;
        [Widget] Gtk.Label serial_label                = null;
        [Widget] Gtk.Label driver_type_label           = null;
        [Widget] Gtk.Label protocol_version_label      = null;
        [Widget] Gtk.Label firmware_version_label      = null;
        [Widget] Gtk.Label firmware_revision_label     = null;
        [Widget] Gtk.Label scan_engine_version_label   = null;
        [Widget] Gtk.Label hardware_version_label      = null;
        [Widget] Gtk.Label is_finder_label             = null;
        [Widget] Gtk.Label finder_version_label        = null;
        [Widget] Gtk.Label device_name_label           = null;
        [Widget] Gtk.Label status_label                = null;
        [Widget] Gtk.Label frequency_label             = null;
        [Widget] Gtk.Label samples_label               = null;
        [Widget] Gtk.Label samplerate_label            = null;
        [Widget] Gtk.Label temperature_label           = null;
        [Widget] Gtk.Label di_label                    = null;
        [Widget] Gtk.Label di_sigma_label              = null;
        [Widget] Gtk.Label max_absorbance_label        = null;
        [Widget] Gtk.Label bg_label                    = null;
        [Widget] Gtk.Label wavelength_correction_label = null;
        [Widget] Gtk.Label adc_correction_label        = null;
        [Widget] Gtk.Label resolution_limit_label      = null;
        [Widget] Gtk.Label spectrum_count_label        = null;
        [Widget] Gtk.Label time_interval_label         = null;
        [Widget] Gtk.Label lut_timestamp_label         = null;
        [Widget] Gtk.Label has_key_pads_label          = null;

        [Widget] Gtk.Expander  advanced_expander = null;
        
        [Widget] Gtk.CheckButton timeout_checkbutton = null;
        [Widget] Gtk.CheckButton eeprom_checkbutton  = null;
        
        [Widget] Gtk.SpinButton trigger_delay_spin      = null;
        [Widget] Gtk.SpinButton lambda_center_spin      = null;
        [Widget] Gtk.SpinButton amplitude_spin          = null;
        [Widget] Gtk.SpinButton grid_spin               = null;
        [Widget] Gtk.SpinButton deviation_spin          = null;
        [Widget] Gtk.SpinButton sample_count_spin       = null;
        [Widget] Gtk.SpinButton timeout_spin            = null;
        [Widget] Gtk.SpinButton quick_average_spin      = null;
        [Widget] Gtk.SpinButton quick_sample_count_spin = null;

        [Widget] Gtk.Button apply_button = null;
        
        [Widget] Gtk.Dialog hardware_dialog = null;
                
        private readonly string title;
        private static Dictionary<IDevice,ServiceDialog> Instances = new Dictionary<IDevice,ServiceDialog>();

        private readonly UserInterface ui;
        
        private readonly IDevice device;
        private Spectrometer.Config new_device_config;
        
        private ScrolledPlot freq_plot;
        
        private bool run_frequency_dialog;


        public ServiceDialog(UserInterface ui, IDevice dev)
        {
            Console.WriteLine("Open new ServiceDialog...");
            
            this.ui = ui;
            
            if (ServiceDialog.Instances.ContainsKey(dev))
            {
                ServiceDialog.Instances[dev].hardware_dialog.Present();
                return;
            }
            
            ServiceDialog.Instances.Add(dev, this);
            this.device = dev;
            
            Glade.XML gui;
            
            try
            {
                gui = new Glade.XML(null, "UserInterface.glade", "hardware_dialog", MainClass.ApplicationDomain);
            }
            catch
            {
                Console.WriteLine("UserInterface: No embedded resource for GUI found. Trying to read external Glade file."); 
                gui = new Glade.XML("UserInterface.glade", "hardware_dialog", null);
            }
            gui.Autoconnect(this);

            this.title = this.hardware_dialog.Title;
            Gdk.Pixbuf[] icons = new Gdk.Pixbuf[5];
            icons[0] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Menu,         string.Empty);
            icons[1] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.SmallToolbar, string.Empty);
            icons[2] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.LargeToolbar, string.Empty);
            icons[3] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Button,       string.Empty);
            icons[4] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Dialog,       string.Empty);
            this.hardware_dialog.IconList = icons;

            this.Update(dev);

            this.device.StateChanged += this.Update;
            this.device.Removed      += this.OnDeviceRemoved;
            
            this.hardware_dialog.DeleteEvent += this.OnDeleteEvent;            

            this.hardware_dialog.TransientFor = this.ui.MainWindow;
            this.hardware_dialog.Show();
        }
        
        public void Update()
        {
            this.Update(this.device);
        }
        
        private void Update(IDevice dev)
        {
            try
            {
                this.advanced_expander.Sensitive = dev.IsIdle;

                this.hardware_dialog.Title = $"{this.title} ({dev.Info.SerialNumber})";
                
                if (dev.Info.VendorId == 0)
                {
                    this.vendor_label.Text  = $"{Catalog.GetString("n/a")} / {Catalog.GetString("n/a")}";
                    this.product_label.Text = $"{Catalog.GetString("n/a")} / '{dev.Info.Description}'";
                }
                else
                {
                    this.vendor_label.Text =
                        $"0x{dev.Info.VendorId.ToString("X04")} / '{dev.Info.Manufacturer}'";
                    
                    this.product_label.Text =
                        $"0x{dev.Info.ProductId.ToString("X04")} / '{dev.Info.Description}'";
                }

                try
                {
                    this.serial_label.Text = dev.Info.SerialNumber;
                    
                    this.driver_type_label.Text = Enum.GetName(typeof(DriverType), dev.DriverType);
                    this.driver_type_label.Text += " / " + this.device.Info.UsbBackend;
                    if (this.device.Info.IsRemote)
                    {
                        this.driver_type_label.Text += "@" + 
                                                       this.device.Info.RemoteSerialInterfaceClient.Server + ":" + 
                                                       this.device.Info.RemoteSerialInterfaceClient.Port;
                    }

                    this.protocol_version_label.Text  = dev.ProtocolVersion.ToString();
                    this.firmware_version_label.Text  = dev.FirmwareVersion.ToString();
                    this.firmware_revision_label.Text = dev.FirmwareRevision.ToString();

                    string msa_factor = Catalog.GetString("n/a");
                    if (dev.GetState() == Spectrometer.State.Idle)
                    {
                        try
                        {
                            dev.StateNotification = false;
                            msa_factor = dev.ReadScanEngineMsaFactor().ToString("F4");
                        }
                        catch (Exception ex) when (ex is NotSupportedException || ex is NotImplementedException)
                        {
                        }
                        finally
                        {
                            dev.StateNotification = true;
                            UserInterface.DeviceStateChanged(dev);
                        }
                    }
                    this.scan_engine_version_label.Text = $"{dev.ScanEngineVersion.ToString()} / {msa_factor}";

                    this.hardware_version_label.Text = dev.HardwareVersion.ToString();
                    
                    if (dev.LutTimestamp == DateTime.MinValue)
                        this.lut_timestamp_label.Text = Catalog.GetString("n/a");
                    else
                        this.lut_timestamp_label.Text = dev.LutTimestamp.ToString();
                    
                    string finder_version = string.Empty;
                    if (dev.IsFinder && dev.FinderVersion != null)
                    {
                        finder_version = string.Format(" (Board {0}, Wheel {1}, Light {2}, Casing {3})",
                                                       dev.FinderVersion.Board,
                                                       dev.FinderVersion.ReferenceWheel,
                                                       dev.FinderVersion.LightSource,
                                                       dev.FinderVersion.Casing);
                    }
                    
                    this.is_finder_label.Text = dev.IsFinder.ToString() + finder_version;

                    if (dev.IsFinder && dev.FinderVersion != null && 
                        dev.FinderVersion.FirmwareVersion.Id != 0 && 
                        dev.FinderVersion.ProtocolVersion.Id != 0)
                    {
                        this.finder_version_label.Text =
                            $"{dev.FinderVersion.FirmwareVersion} / {dev.FinderVersion.ProtocolVersion} / {dev.FinderVersion.Peripheral}";
                    }

                    this.device_name_label.Text = dev.CurrentConfig.Name;
                    this.status_label.Text      = Enum.GetName(typeof(Spectrometer.State), dev.GetState());
                }
                catch (NullReferenceException) { }

                if (dev.AcquisitionInfo == null)
                {
                    this.frequency_label.Text  = Catalog.GetString("n/a");
                    this.samples_label.Text    = Catalog.GetString("n/a");
                    this.samplerate_label.Text = Catalog.GetString("n/a");
                }
                else
                {
                    this.frequency_label.Text  = dev.AcquisitionInfo.MirrorFreq.ToString("f3") + " Hz";
                    this.samples_label.Text    = dev.AcquisitionInfo.Samples.ToString();
                    this.samplerate_label.Text = dev.AcquisitionInfo.SampleRate.ToString("f1") + " 1/s";
                }

                if (dev.GetState() == Spectrometer.State.Idle)
                {
                    try
                    {
                        dev.StateNotification = false;
                        this.temperature_label.Text = $"{dev.ReadStatus().ToString("f1")}°C";
                        this.temperature_label.TooltipText = Catalog.GetString("Sensor");
                        if (dev.IsFinder)
                        {
                            this.temperature_label.Text += $" / {dev.ReadFinderTemperature().ToString("f1")}°C";
                            this.temperature_label.TooltipText = Catalog.GetString("Sensor/Casing");
                        }
                        if (dev.TemperatureHistory != null)
                        {
                            double gradient = dev.TemperatureHistory.Gradient;
                            if (!double.IsNaN(gradient))
                            {
                                this.temperature_label.Text += $" / {gradient.ToString("f1")}K/h";
                                this.temperature_label.TooltipText = Catalog.GetString("Sensor/Casing/Sensor gradient");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Cannot update temperature info: " + ex.Message);
                        this.temperature_label.Text = Catalog.GetString("n/a");
                    }
                    finally
                    {
                        dev.StateNotification = true;
                        UserInterface.DeviceStateChanged(dev);
                    }
                    
                    try
                    {
                        dev.StateNotification = false;
                        this.has_key_pads_label.Text = dev.HasKeyPad.ToString();
                    }
                    catch (Exception ex) when (ex is NotSupportedException || ex is NotImplementedException)
                    {
                        this.has_key_pads_label.Text = Catalog.GetString("n/a");
                    }
                    finally
                    {
                        dev.StateNotification = true;
                        UserInterface.DeviceStateChanged(dev);
                    }
                }
                
                this.di_label.Text       = dev.CurrentConfig.DarkIntensity.Intensity.ToString("f5");
                this.di_sigma_label.Text = dev.CurrentConfig.DarkIntensity.Sigma.ToString("f5");
                
                if (dev.CurrentConfig.HasReferenceSpectrum)
                    this.max_absorbance_label.Text =  DataSet.AbsorbanceLimit(dev.CurrentConfig.ReferenceSpectrum.Intensity, 
                                                                              dev.CurrentConfig.DarkIntensity).ToString("f5");
                else
                    this.max_absorbance_label.Text = Catalog.GetString("n/a");
                
                this.bg_label.Text                    = dev.CurrentConfig.HasReferenceSpectrum.ToString();
                this.wavelength_correction_label.Text = dev.CurrentConfig.HasWavelengthCorrection.ToString();
                this.adc_correction_label.Text        = dev.CurrentConfig.HasAdcCorrection.ToString();
                this.resolution_limit_label.Text      = dev.LimitBandwith.ToString();
                
                this.time_interval_label.Text  = $"{dev.CurrentConfig.TimedSpan.ToString()} s";
                this.spectrum_count_label.Text = dev.SpectrumCount.ToString();
                
                if ((dev.CurrentConfig.StreamType == Spectrometer.StreamType.Timed) &&
                    (dev.CurrentConfig.TimedCount > 0))
                {
                    this.spectrum_count_label.Text += $" / {dev.CurrentConfig.TimedCount.ToString()}";
                }
                
                this.trigger_delay_spin.Value = (double)dev.CurrentConfig.TriggerDelay;
                this.lambda_center_spin.Value = (double)dev.CurrentConfig.LambdaCenter;
                this.amplitude_spin.Value     = (double)dev.CurrentConfig.Amplitude;
                this.grid_spin.Value          = (double)dev.CurrentConfig.Grid;
                this.deviation_spin.Value     = (double)dev.CurrentConfig.Deviation;
                this.sample_count_spin.Value  = (double)dev.CurrentConfig.Samples;
                
                this.timeout_checkbutton.Active = dev.CurrentConfig.AutoTimeout == false;
                this.timeout_spin.Sensitive     = dev.CurrentConfig.AutoTimeout == false;
                this.timeout_spin.Value         = (double)dev.CurrentConfig.Timeout;

                this.quick_average_spin.Value      = (double)dev.CurrentConfig.QuickAverage;
                this.quick_sample_count_spin.Value = (double)dev.CurrentConfig.QuickSamples;
                
                this.eeprom_checkbutton.Active = UserInterface.Settings.Current.WriteToEEPROM;
                
                this.new_device_config = new Spectrometer.Config(dev.CurrentConfig);                
                
                this.apply_button.Sensitive = false;
            }
            catch (NullReferenceException) { }
        }
            
        private void OnDeviceRemoved(IDevice dev)
        {
            ServiceDialog.Instances.Remove(dev);
            this.hardware_dialog.Destroy();
        }
        
        internal void OnAdvancedExpanderActivate(object o, System.EventArgs e)
        {
            Expander expander = o as Expander;
            
            if (expander.Expanded && MainClass.IsRelease)
            {
                expander.Expanded = false;
                PasswordDialog dialog = new PasswordDialog(this.hardware_dialog,
                                                           Catalog.GetString("Enter password"));

                if (dialog.Query("83-21-B1-FD-3E-15-70-7E-EA-17-86-2B-0E-CD-D0-41"))
                    expander.Expanded = true;
            }
        }
        
        internal void OnTimeoutCheckbuttonToggled(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            CheckButton c = o as CheckButton;

            this.new_device_config.AutoTimeout = !c.Active;
            
            this.timeout_spin.Sensitive = c.Active;
            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }

        internal void OnTriggerDelaySpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.TriggerDelay = (ushort)s.Value;
            
            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnLambdaCenterSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.LambdaCenter = (double)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnAmplitudeSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.Amplitude = (double)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnGridSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.Grid = (ushort)s.Value;
            
            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnDeviationSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.Deviation = (double)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnSampleCountSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.Samples = (ushort)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnQuickAverageSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.QuickAverage = (ushort)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnQuickSampleCountSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.QuickSamples = (ushort)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }
        
        internal void OnTimeoutSpinValueChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config == null)
                return;
            
            SpinButton s = o as SpinButton;
            this.new_device_config.Timeout = (int)s.Value;

            this.apply_button.Sensitive = this.device.IsIdle || 
                                          this.device.GetState() == Spectrometer.State.Unprogrammed;
        }

        internal void OnEepromCheckbuttonToggled(object o, EventArgs e)
        {
            CheckButton b = o as CheckButton;
            UserInterface.Settings.Current.WriteToEEPROM = b.Active; 
        }

        internal void OnSettingChanged(object o, System.EventArgs e)
        {
            if (this.new_device_config != null)
                this.apply_button.Sensitive = this.device.IsIdle || 
                                              this.device.GetState() == Spectrometer.State.Unprogrammed;
        }

        internal void OnApplyButtonClicked(object o, System.EventArgs e)
        {
            Button b = o as Gtk.Button;
            
            b.HasFocus = true;
            
            try
            {
                this.device.CurrentConfig = this.new_device_config;
            }
            catch (System.Exception ex)
            {
                InfoMessageDialog.Show(this.hardware_dialog, 
                                       Catalog.GetString("Cannot apply device settings: {0}"),
                                       ex.Message);
                return;
            }
            
            if (this.eeprom_checkbutton.Active)
            {
                try
                {
                    this.device.WriteEEPROM();
                    InfoMessageDialog.Show(this.hardware_dialog, 
                                           Catalog.GetString("Successfully wrote hardware settings to EEPROM."));
                }
                catch (System.Exception ex)
                {
                    InfoMessageDialog.Show(this.hardware_dialog, 
                                           Catalog.GetString("Cannot write EEPROM: {0}"),
                                           ex.Message);
                }
            }
            this.ui.UpdatePropertiesSpectrometerControls();
            
            b.Sensitive = false;
        }

        internal void OnFrequencyButtonClicked(object o, System.EventArgs e)
        {
            if (this.device.Frequency.Count < 4)
            {
                InfoMessageDialog.Show(this.hardware_dialog, 
                                       Catalog.GetString("Not enough mirror frequency data available."));
                return;
            }

            DataSet freq  = this.device.Frequency.GetRange(2, this.device.Frequency.Count-2);
            var dialog = new Gtk.Dialog($"{Catalog.GetString("Frequency characteristic")} ({this.device.Info.SerialNumber})",
                                        this.hardware_dialog,
                                        DialogFlags.Modal);
            dialog.AddButton(Stock.Save,    0);
            dialog.AddButton(Stock.Print,   1);
            dialog.AddButton(Stock.Refresh, 2);
            dialog.AddButton(Stock.Close, ResponseType.Close);
            
            dialog.Response += this.OnFrequencyDialogResponse;
            
            dialog.HasSeparator  = true;
            dialog.WidthRequest  = 780;
            dialog.HeightRequest = 400;
            
            this.freq_plot = new ScrolledPlot(null);
            this.freq_plot.Plot.BackgroundColor = this.ui.BackgroundColor;
            this.freq_plot.Plot.AddDataSet(freq / new DataSet.Operand(60f, 1f));
            this.freq_plot.Plot.XLabel = Catalog.GetString("Time / min");
            this.freq_plot.Plot.YLabel = Catalog.GetString("Mirror frequency / Hz");
            this.freq_plot.Plot.Title = $"{Catalog.GetString("Device serial:")} {this.device.Info.SerialNumber}";
            this.freq_plot.Plot.LegendVisible = false;
            dialog.VBox.PackStart(this.freq_plot);
            this.freq_plot.ShowAll();
            
            do
            {
                dialog.Run();
            }
            while (this.run_frequency_dialog);
            
            dialog.Destroy();
        }
        
        private void OnFrequencyDialogResponse(object o, ResponseArgs e)
        {
            switch ((int)e.ResponseId)
            {
                
            case 0:
                FileChooserDialog chooser = new FileChooserDialog(Catalog.GetString("Specify file name to save frequency characteristic"), 
                                                                  this.hardware_dialog, 
                                                                  FileChooserAction.Save,
                                                                  Stock.Save,
                                                                  ResponseType.Ok,
                                                                  Stock.Cancel,
                                                                  ResponseType.Cancel);
                FileFilter filter = new FileFilter
                {
                    Name = Catalog.GetString("CSV files")
                };
                filter.AddPattern("*.csv");
                chooser.AddFilter(filter);
                
                chooser.CurrentName = $"frequency{DateTime.Now.ToString("_yyyy-MM-dd_HH-mm_")}{this.device.Info.SerialNumber}.csv";
                
                if (string.IsNullOrEmpty(UserInterface.Settings.Current.SaveFrequencyFilePath) == false)
                    chooser.SetCurrentFolder(UserInterface.Settings.Current.SaveFrequencyFilePath);
                else
                    chooser.SetCurrentFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
                
                try
                {
                    ResponseType choice = (ResponseType)chooser.Run();
                    
                    if (choice == ResponseType.Ok)
                    {
                        chooser.Hide();
                        
                        CSV.Write(this.device.Frequency.GetRange(2, this.device.Frequency.Count-2),
                                  chooser.Filename, 
                                  this.ui.OutputCultureInfo());

                        UserInterface.Settings.Current.SaveFrequencyFilePath = chooser.CurrentFolder;
                    }
                }
                catch (Exception ex)
                {
                    InfoMessageDialog.Show(this.hardware_dialog, 
                                           Catalog.GetString("Error while saving frequency characteristic: {0}"),
                                           ex.Message);
                }
                finally
                {
                    chooser.Destroy();
                }
                this.run_frequency_dialog = true;
                break;
                
            case 1:
                var printer = new Integration.Printer(this.hardware_dialog, this.freq_plot.Plot);
                this.run_frequency_dialog = true;
                break;
                
            case 2:
                DataSet freq = this.device.Frequency.GetRange(2, this.device.Frequency.Count - 2);
                this.freq_plot.Plot.Clear();
                this.freq_plot.Plot.AddDataSet(freq / new DataSet.Operand(60.0, 1.0));
                
                this.run_frequency_dialog = true;
                break;
                
            default:
                this.run_frequency_dialog = false;
                break;
                
            }
        }
        
        internal void OnWavelengthCorrectionButtonClicked(object o, EventArgs e)
        {
            if (this.device.HasReference == false && this.device.IsFinder == false)
            {
                InfoMessageDialog.Show(this.hardware_dialog, 
                                       Catalog.GetString("Cannot perform wavelength correction: " +
                                                         "Please specify reference spectrum and dark intensity first."));
                return;
            }
            try
            {
                var c = new CorrectionDialog(this.device, this, this.ui);
            }
            catch (Exception ex)
            {
                InfoMessageDialog.Show(this.hardware_dialog, ex.Message);
            }
        }

        internal void OnHardwarePropertiesButtonClicked(object o, EventArgs e)
        {
            string msg = Catalog.GetString("<b>Hardware Properties</b>\n\n") +
                         $"<span font_family=\"monospace\">{this.device.HardwareProperties.ToString()}</span>";
            MessageDialog dialog = new MessageDialog(this.hardware_dialog,
                                                     DialogFlags.Modal,
                                                     MessageType.Info,
                                                     ButtonsType.Ok,
                                                     msg);
            Console.WriteLine(msg);
            dialog.Run();
            dialog.Destroy();
        }
        
        internal void OnResolutionLimitButtonClicked(object o, EventArgs e)
        {
            this.device.LimitBandwith = this.device.LimitBandwith == false;
            this.Update();
        }
        
        internal void OnCloseButtonClicked(object o, System.EventArgs e)
        {
            this.device.StateChanged -= this.Update;
            this.OnDeviceRemoved(this.device);
        }

        private void OnDeleteEvent(System.Object o, DeleteEventArgs e)
        {
            this.device.StateChanged -= this.Update;
            this.OnDeviceRemoved(this.device);
            e.RetVal = true;
        }
    }
}