// UI.Properties.Spectrometer.cs created with MonoDevelop
// User: klose at 10:51 26.01.2009
// CVS release: $Id: UI.Properties.Spectrometer.cs,v 1.59 2011-04-19 12:36:59 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 System.IO;
using Gtk;
using Glade;

using Hiperscan.SGS;
using Hiperscan.FileIO;
using Hiperscan.Extensions;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;


namespace Hiperscan.GUI
{
	
	public partial class UserInterface
	{
		[Widget] Gtk.Frame device_properties_frame = null;
		[Widget] Gtk.Frame references_frame        = null;
		[Widget] Gtk.Frame default_comment_frame   = null;
		[Widget] Gtk.Frame auto_save_frame         = null;
		[Widget] Gtk.Frame stream_frame            = null;
		
		[Widget] Gtk.SpinButton average_spin        = null;
		[Widget] Gtk.SpinButton timed_interval_spin = null;
		[Widget] Gtk.SpinButton timed_count_spin    = null;
		[Widget] Gtk.SpinButton di_specify_spin     = null;

		//[Widget] Gtk.Label timed_interval_label = null;
		//[Widget] Gtk.Label timed_count_label    = null;
		[Widget] Gtk.Label device_name_label2    = null;
		[Widget] Gtk.Label bg_type_label         = null;
		[Widget] Gtk.Label di_type_label         = null;
		[Widget] Gtk.Label single_fmask_label    = null;
		[Widget] Gtk.Label stream_fmask_label    = null;
		[Widget] Gtk.Label single_csv_label      = null;
		[Widget] Gtk.Label stream_csv_label      = null;
		
		//[Widget] Gtk.ComboBox stream_type_combo = null;
		
		[Widget] Gtk.Entry device_name_entry = null;
				
		[Widget] Gtk.FileChooserButton bg_filechooser     = null;
		[Widget] Gtk.FileChooserButton single_filechooser = null;
		[Widget] Gtk.FileChooserButton stream_filechooser = null;

		[Widget] Gtk.Button bg_delete_button             = null;
		[Widget] Gtk.Button di_delete_button             = null;
		[Widget] Gtk.Button device_property_apply_button = null;
		
		[Widget] Gtk.Image activate_associated_dir_image = null;
		
		[Widget] Gtk.TextView default_comment_text = null;

		[Widget] Gtk.CheckButton auto_single_checkbutton = null;
		[Widget] Gtk.CheckButton auto_stream_checkbutton = null;
		
		[Widget] Gtk.Entry single_fmask_entry = null;
		[Widget] Gtk.Entry stream_fmask_entry = null;
		
		Gtk.LinkButton service_dialog_button = null;

		private Device.Config new_device_config;
		private Device current_device = null;
		
		
		private void InitializePropertiesSpectrometer()
		{
			this.device_name_entry.MaxLength = 19;
			
			this.bg_filechooser.FileSet += new EventHandler(OnBgFilechooserSet);

			if (!string.IsNullOrEmpty(Settings.Current.OpenBgFilePath)) 
				this.bg_filechooser.SetCurrentFolder(Settings.Current.OpenBgFilePath);
			else
				this.bg_filechooser.SetCurrentFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

			this.single_filechooser.CurrentFolderChanged += this.OnSingleFolderChanged;
			this.stream_filechooser.CurrentFolderChanged += this.OnStreamFolderChanged;
			this.default_comment_text.Buffer.Changed     += this.OnDefaultCommentTextChanged;

			this.UpdatePropertiesSpectrometer();
		}
		
		private void UpdatePropertiesSpectrometer()
		{
			this.UpdatePropertiesSpectrometer(false);
		}
		
		private void UpdatePropertiesSpectrometer(bool force_update)
		{
			if (this.property_notebook.Page != 0)
				return;
			
			try
			{
				if ( this.active_devices.Count == 1   && 
				    !this.active_devices[0].IsUnknown && 
				     this.active_devices[0].IsConnected)
				{
					this.service_dialog_button.Sensitive = true;
					this.current_object_label.Text = "(" + this.active_devices[0].Info.SerialNumber + ")";
				}
				else
				{
					this.service_dialog_button.Sensitive = false;
					this.current_object_label.Text = string.Empty;
				}

				switch (this.active_devices.Idle.Count)
				{
					
				case 0:
					this.current_device = null;
					
					if (this.device_property_apply_button.Sensitive)
					{
						this.device_property_apply_button.Sensitive = false;
						new StatusMessage(this.parent, 
						                  Catalog.GetString("WARNING: Changes in device properties have been discarded. Use the Apply button to enable changes."), 
						                  true);
					}
					this.stream_frame.Sensitive                 = false;
					this.device_properties_frame.Sensitive      = false;
					this.default_comment_frame.Sensitive        = false;
					this.references_frame.Sensitive             = false;
					if ((this.active_devices.Count         == 1)                         &&
					    (this.current_device               != this.active_devices[0])    &&
					    (this.active_devices[0].GetState() != Device.State.Disconnected) &&
					    (this.active_devices[0].GetState() != Device.State.Unknown))
					{
						//this.current_device = this.active_devices[0];
						this.UpdatePropertiesSpectrometerControls(this.active_devices[0]);
					}
					this.SetAutoSaveControls(false);
					return;
					
				case 1:
					this.device_properties_frame.Sensitive = true;
					this.stream_frame.Sensitive            = true;
					this.default_comment_frame.Sensitive   = true;
					this.references_frame.Sensitive        = true;
					this.device_name_label2.Sensitive      = true;
					this.device_name_entry.Sensitive       = true;
					this.SetAutoSaveControls(true);
					break;
					
				default:
					this.device_properties_frame.Sensitive = true;
					this.stream_frame.Sensitive            = true;
					this.default_comment_frame.Sensitive   = false;
					this.references_frame.Sensitive        = false;
					this.device_name_label2.Sensitive      = false;
					this.device_name_entry.Sensitive       = false;
					this.SetAutoSaveControls(false);
					break;
					
				}

				Device dev = this.active_devices.Idle[0];
				
				//this.PopulateAssociatedDirsCombo(dev);
				
				if (this.current_device == dev && !force_update)
					return;
				
				switch (dev.CurrentConfig.BackgroundSpectrumType)
				{
					
				case Device.BackgroundSpectrumType.None:
					this.bg_type_label.Text = Catalog.GetString("(None)");
					this.bg_delete_button.Sensitive = false;
					break;
					
				case Device.BackgroundSpectrumType.File:
					this.bg_type_label.Text = Catalog.GetString("(From file)");
					this.bg_delete_button.Sensitive = true;
					break;
					
				case Device.BackgroundSpectrumType.Record:
					this.bg_type_label.Text = Catalog.GetString("(Acquired)");
					this.bg_delete_button.Sensitive = true;
					break;
					
				}			
				
				switch (dev.CurrentConfig.DarkIntensityType)
				{
					
				case Device.DarkIntensityType.None:
					this.di_type_label.Text = Catalog.GetString("(None)");
					this.di_delete_button.Sensitive = false;
					break;
					
				case Device.DarkIntensityType.Specify:
					this.di_type_label.Text = Catalog.GetString("(Specified)");
					this.di_delete_button.Sensitive = true;
					break;
					
				case Device.DarkIntensityType.Record:
					this.di_type_label.Text = Catalog.GetString("(Acquired)");
					this.di_delete_button.Sensitive = true;
					break;
					
				}
				
				this.device_property_apply_button.Sensitive = false;
				this.UpdatePropertiesSpectrometerControls(dev);
				this.current_device = dev;
			}
			catch (Exception ex)
			{
				Console.WriteLine("Exception in UpdatePropertiesSpectrometer(): " + ex);
				// something is wrong -> deaktivate property editor for now
				if (this.service_dialog_button != null)
					this.service_dialog_button.Sensitive = false;
				
				this.current_device = null;
					
				this.device_property_apply_button.Sensitive = false;
				this.device_properties_frame.Sensitive      = false;
				this.references_frame.Sensitive             = false;
			}			
		}

		private void SetAutoSaveControls(bool active)
		{
			this.auto_save_frame.Sensitive = active;

			active = this.auto_single_checkbutton.Active;
			this.single_filechooser.Sensitive = active;
			this.single_fmask_label.Sensitive = active;
			this.single_fmask_entry.Sensitive = active;
			this.single_csv_label.Sensitive   = active;
			
			active = this.auto_stream_checkbutton.Active;
			this.stream_filechooser.Sensitive = active;
			this.stream_fmask_label.Sensitive = active;
			this.stream_fmask_entry.Sensitive = active;
			this.stream_csv_label.Sensitive   = active;
		}			
		
		private void UpdatePropertiesSpectrometerControls(Device dev)
		{
			if (dev.GetState() == Device.State.WriteConfig)
				return;

			if (!this.device_property_apply_button.Sensitive)
			{
				this.new_device_config = null;

				// update device controls
				this.average_spin.Value        = (double)dev.CurrentConfig.Average;
				//this.stream_type_combo.Active  = (int)dev.CurrentConfig.StreamType;
				this.timed_interval_spin.Value = (double)dev.CurrentConfig.TimedSpan;
				this.timed_count_spin.Value    = (double)dev.CurrentConfig.TimedCount;
				this.device_name_entry.Text    = dev.CurrentConfig.Name;
				this.di_specify_spin.Value     = dev.CurrentConfig.DarkIntensity.Intensity;
				
				this.default_comment_text.Buffer.Text = dev.CurrentConfig.DefaultComment; 
				
				// update auto save controls
				if (dev.CurrentConfig.UserData == null)
				{
					DirectoryProperty single_dir;

					if (!string.IsNullOrEmpty(Settings.Current.AutoSaveSingleDirectory))
						single_dir = new DirectoryProperty(Settings.Current.AutoSaveSingleDirectory);
					else
						single_dir = new DirectoryProperty(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

					single_dir.Active           = false;
					single_dir.AssociatedDevice = dev;
					single_dir.SingleFilemask   = Settings.Current.SingleFileMask;
					single_dir.AutoSaveSingle   = true;
					single_dir.AutoSaveStream   = false;
					single_dir.SingleFiletype   = SpectrumFileType.CSV;

					
					DirectoryProperty stream_dir;

					if (!string.IsNullOrEmpty(Settings.Current.AutoSaveStreamDirectory))
						stream_dir = new DirectoryProperty(Settings.Current.AutoSaveStreamDirectory);
					else
						stream_dir = new DirectoryProperty(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

					stream_dir.Active            = false;
					stream_dir.AssociatedDevice  = dev;
					stream_dir.StreamFilemask    = Settings.Current.StreamFileMask;
					stream_dir.AutoSaveSingle    = false;
					stream_dir.AutoSaveStream    = true;
					stream_dir.StreamFiletype    = SpectrumFileType.CSV;
					
					dev.CurrentConfig.UserData = new AutoSaveConfig(single_dir, stream_dir); 
				}
				
				AutoSaveConfig save_config = dev.CurrentConfig.UserData as AutoSaveConfig;
				
				this.auto_single_checkbutton.Active = save_config.SingleDir.Active;
				if (this.single_filechooser.CurrentFolder != save_config.SingleDir.Info.FullName)
					this.single_filechooser.SetCurrentFolder(save_config.SingleDir.Info.FullName);
				this.single_fmask_entry.Text = save_config.SingleDir.SingleFilemask;
				
				this.auto_stream_checkbutton.Active = save_config.StreamDir.Active;
				if (this.stream_filechooser.CurrentFolder != save_config.StreamDir.Info.FullName)
					this.stream_filechooser.SetCurrentFolder(save_config.StreamDir.Info.FullName);
				this.stream_fmask_entry.Text = save_config.StreamDir.StreamFilemask;
				
				this.new_device_config = new Device.Config(dev.CurrentConfig);
				
				this.device_property_apply_button.Sensitive = false;
			}
		}
		
		public void UpdatePropertiesSpectrometerControls()
		{
			if (this.current_device != null)
				this.UpdatePropertiesSpectrometerControls(this.current_device);
		}
		
		private void SetAutoSaveAssociations()
		{
			// check filemasks
			try
			{
				string fname = DirectoryProperty.AssembleFilename(this.single_filechooser.CurrentFolder, new Spectrum(WavelengthLimits.DefaultWavelengthLimits), this.single_fmask_entry.Text, ".csv");

				if (this.auto_single_checkbutton.Active)
				{
					DirectoryInfo dir = new DirectoryInfo(this.single_filechooser.CurrentFolder);
					FileInfo[] files = dir.GetFiles(Path.GetFileName(fname));
					if (files.Length > 0)
						new InfoMessage(this.parent,
						                Catalog.GetString("Warning: The chosen directory already contains files " + 
						                                  "matching the single file mask. This could result in " +
						                                  "data loss due to overwritten files."));
				}
			}
			catch (DirectoryNotFoundException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(Catalog.GetString("Cannot parse filename mask for single spectra:") +
				                    " " + ex.Message);
			}
			
			try
			{
				string fname = DirectoryProperty.AssembleFilename(this.stream_filechooser.CurrentFolder, new Spectrum(WavelengthLimits.DefaultWavelengthLimits), this.stream_fmask_entry.Text, ".csv");
				Console.WriteLine(fname);
				
				if (this.auto_stream_checkbutton.Active)
				{
					DirectoryInfo dir = new DirectoryInfo(this.stream_filechooser.CurrentFolder);
					FileInfo[] files = dir.GetFiles(Path.GetFileName(fname));
					if (files.Length > 0)
						new InfoMessage(this.parent,
						                Catalog.GetString("Warning: The chosen directory already contains files " + 
						                                  "matching the stream file mask. This could result in " +
						                                  "data loss due to overwritten files."));
				}
			}
			catch (DirectoryNotFoundException ex)
			{
				throw ex;
			}
			catch (System.Exception ex)
			{
				throw new Exception(Catalog.GetString("Cannot parse filename mask for stream spectra:") +
				                    " " + ex.Message);
			}

			try
			{
				UserInterface.Settings.Current.SingleFileMask = this.single_fmask_entry.Text;
				UserInterface.Settings.Current.StreamFileMask = this.stream_fmask_entry.Text;

				AutoSaveConfig save_config = this.new_device_config.UserData as AutoSaveConfig;
				
				save_config.SingleDir.Active         = false;
				save_config.SingleDir.OutputCulture  = this.StandardOutputCulture;
				save_config.SingleDir.SingleFilemask = this.single_fmask_entry.Text;
				save_config.SingleDir.SingleFiletype = SpectrumFileType.CSV;
				save_config.SingleDir.Active         = this.auto_single_checkbutton.Active;
				
				save_config.StreamDir.Active         = false;
				save_config.StreamDir.OutputCulture  = this.StandardOutputCulture;
				save_config.StreamDir.StreamFilemask = this.stream_fmask_entry.Text;
				save_config.StreamDir.StreamFiletype = SpectrumFileType.CSV;
				save_config.StreamDir.Active         = this.auto_stream_checkbutton.Active;
			}
			catch (System.Exception ex)
			{
				throw new Exception(Catalog.GetString("Cannot apply autosave settings:") +
				                    " " + ex.Message);
			}
		}

//		private void PopulateAssociatedDirsCombo(Device dev)
//		{
//			this.associated_dirs_combo.Clear();
//			
//			this.activate_associated_dir_button.Sensitive = false;
//			this.show_associated_dir_button.Sensitive     = false;
//			this.delete_associated_dirs_button.Sensitive  = false;
//			
//			ListStore store = new ListStore(typeof(bool),               // connected
//			                                typeof(string),             // directory name
//			                                typeof(DirectoryProperty)); // directory property class
//			this.associated_dirs_combo.Model = store;
//
//			CellRendererToggle toggle = new CellRendererToggle();
//			CellRendererText   text   = new CellRendererText();
//			
//			this.associated_dirs_combo.PackStart(toggle, false);
//			this.associated_dirs_combo.PackStart(text,   true);
//			this.associated_dirs_combo.SetAttributes(toggle, "active", 0);
//			this.associated_dirs_combo.SetAttributes(text,   "text", 1);
//
//			default_comment_label.Text = string.Empty;
//			
//			int dir_ix = -1;
//			int ix     = 0;
//			foreach (DirectoryProperty dp in this.GetAssociatedDirectories(dev))
//			{
//				Console.WriteLine("Add associated directory: " + dp.Info.Name);
//				store.AppendValues(dp.Active, dp.Info.Name, dp);
//				
//				if (dp.Active && dp.HasComment && this.new_device_config.HasDefaultComment)
//					default_comment_label.Markup 
//						= "<span color=\"red\">Warning: Comment may be replaced</span>";
//				
//				if (this.current_directory_config == dp)
//					dir_ix = ix;
//				
//				this.delete_associated_dirs_button.Sensitive = true;
//
//				++ix;
//			}
//			
//			this.associated_dirs_combo.Active = dir_ix;
////			TreeViewColumn   column;
////				
////			// filename column
////			text = new CellRendererText();
////			text.Xalign = 0f;
////			this.columns.Add(text);
////			column = new TreeViewColumn("Spectrum file", text,
////			                            "markup",        Store.Filename,
////			                            "mode",          Store.Mode);
////			column.Clickable = true;
////			column.SortOrder = SortType.Ascending;
////			column.Clicked  += new EventHandler(this.OnFilenameColumnClicked);
////			column.SetCellDataFunc(text, new TreeCellDataFunc(this.RenderEntry));
////			this.tv.InsertColumn(column, (int)Store.Filename);
////			column.SortIndicator = true;
////			
////			// serial column
////			text = new CellRendererText();
////			text.Xalign = 0f;
////			this.columns.Add(text);
////			column = new TreeViewColumn("Serial number", text,
////			                            "markup",        Store.Serial,
////			                            "mode",          Store.Mode);
////			column.Clickable = true;
////			column.SortOrder = SortType.Ascending;
////			column.Clicked  += new EventHandler(this.OnSerialColumnClicked);
////			column.SetCellDataFunc(text, new TreeCellDataFunc(this.RenderEntry));
////			this.tv.InsertColumn(column, (int)Store.Serial);
////						
////			tv.Model = this.store;
////			tv.HeadersClickable = true;
////			tv.HeadersVisible   = true;
////
//		}

		internal void OnOpenAssociatedDirButtonClicked(object o, System.EventArgs e)
		{
			this.OnOpenDirectoryClicked(o, e);
			
			if (this.current_directory_config == null)
				return;
				
			this.current_directory_config.AssociatedDevice = this.active_devices[0];
			this.UpdatePropertiesDirectory(this.current_directory_config);
		}
		
		internal void OnAssociatedDirsComboChanged(object o, System.EventArgs e)
		{
			ComboBox c = o as ComboBox;

			TreeIter iter;
			if (c.GetActiveIter(out iter))
			{
				this.current_directory_config = (DirectoryProperty)c.Model.GetValue(iter, 2);
				
				if (this.current_directory_config.Active)
					this.activate_associated_dir_image.Stock = Stock.Remove;
				else
					this.activate_associated_dir_image.Stock = Stock.Add;
				
				//this.activate_associated_dir_button.Sensitive = true;
				//this.show_associated_dir_button.Sensitive     = true;
			}
		}
		
		internal void OnActivateAssociatedDirButtonClicked(object o, System.EventArgs e)
		{
			this.current_directory_config.Active = !this.current_directory_config.Active;
			this.UpdatePropertiesSpectrometer();
		}
		
		internal void OnShowAssociatedDirButtonClicked(object o, System.EventArgs e)
		{
			this.ShowDirectoryProperty(this.current_directory_config);
		}
		
		internal void OnDeleteAssociatedDirsButtonClicked(object o, System.EventArgs e)
		{
			if (this.current_device == null)
				return;
			
			foreach (DirectoryProperty dp in this.GetAssociatedDirectories(this.current_device))
			{
				dp.AssociatedDevice = null;
			}
			
			this.UpdatePropertiesSpectrometer();
		}
		
		private void ShowBgPreview()
		{
			this.PlotType = this.plot_types["quickstep"][0];

			this.ScrolledPlot.Plot.Clear();
			this.ScrolledPlot.Plot.DataSetSelections.Clear();
			
			DataSet ds  = this.new_device_config.BackgroundSpectrum.Intensity;
			ds.DataType = DataType.Preview;
//			ds.PlotId   = UserInterface.plot_instance;
			ds.Id       = "9_preview";
			ds.Label    = Catalog.GetString("Preview");
			ds.XLabel   = Catalog.GetString("Wavelength / nm");
			ds.YLabel   = Catalog.GetString("Intensity / a.u.");
			ds.Color    = UserInterface.Config.PreviewColor;
			
			this.ScrolledPlot.Plot.DataSets.Add(ds.Id, ds);
			this.ScrolledPlot.Plot.RequestUpdate();
			
			this.PlotType = new UndefinedPlotTypeInfo();
			return;
		}
		
		private void ShowDiPreview(Spectrum spectrum)
		{
			this.PlotType = this.plot_types["quickstep"][0];

			this.ScrolledPlot.Plot.Clear();
			this.ScrolledPlot.Plot.Annotations.Clear();
			this.ScrolledPlot.Plot.DataSetSelections.Clear();
			
			DataSet ds  = new DataSet(spectrum.RawIntensity);
			ds.DataType = DataType.Preview;
//			ds.PlotId   = UserInterface.plot_instance;
			ds.Id       = "9_preview";
			ds.Label    = Catalog.GetString("Preview");
			ds.XLabel = Catalog.GetString("Wavelength / nm");
			ds.YLabel = Catalog.GetString("Intensity / a.u.");
			ds.Color    = UserInterface.Config.PreviewColor;
			ds.SetYMin(-0.1f);
			ds.SetYMax( 2.6f);
			
			this.ScrolledPlot.Plot.DataSets.Add(ds.Id, ds);
			this.ScrolledPlot.Plot.RequestUpdate();
			
			this.PlotType = new UndefinedPlotTypeInfo();
			return;
		}
		
		internal void CheckForChangedDeviceProperties()
		{
			if (!this.device_property_apply_button.Sensitive || Settings.Current.DontShowDiscardPropertiesDialogAgain)
				return;
			
			MessageDialog dialog = new MessageDialog(this.parent, DialogFlags.Modal,
			                                         MessageType.Question, ButtonsType.YesNo,
			                                         Catalog.GetString("You did not apply changes in device properties. Do you want to apply the modified configuration now?\n\nIf you choose 'No', recent changes are discarded."));
			dialog.IconList = MainClass.QuickStepIcons;
			CheckButton cb = new CheckButton(Catalog.GetString("Always auto-apply properties if possible"));
			cb.Active = false;
			cb.CanFocus = false;
			dialog.VBox.PackStart(cb);
			cb.Show();
			
			ResponseType choice = (ResponseType)dialog.Run();
			Settings.Current.DontShowDiscardPropertiesDialogAgain = cb.Active;
			dialog.Destroy();

			if (choice != ResponseType.Yes)
				return;
			
			this.OnDevicePropertyApplyButtonClicked(this.device_property_apply_button, EventArgs.Empty);
		}

		internal void SetWatchCursor(object o, System.EventArgs e)
		{
			if (this.parent?.GdkWindow == null)
				return;
			this.parent.GdkWindow.Cursor = new Gdk.Cursor(Gdk.CursorType.Watch);
		}

		internal void SetArrowCursor(object o, System.EventArgs e)
		{
			if (this.parent?.GdkWindow == null)
				return;
			this.parent.GdkWindow.Cursor = new Gdk.Cursor(Gdk.CursorType.Arrow);
		}
		
		internal void OnDeviceNameEntryChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			Entry t = o as Entry;
			this.new_device_config.Name = t.Text;
			this.device_property_apply_button.Sensitive = true;			
		}
		
		private void OnSpectrometerTvDoubleClicked(List<Device> devices)
		{
			this.PropertyType = Config.PropertyType.Spectrometer;
			this.PropertyEditorVisible = true;
		}
		
		internal void OnAverageSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Average = (ushort)s.Value;
			this.device_property_apply_button.Sensitive = true;						
		}
		
		internal void OnDiSpecifySpinChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.DarkIntensity = new DarkIntensity(s.Value, 0f);
			
			if (s.Value != 0f)
				this.new_device_config.DarkIntensityType = Device.DarkIntensityType.Specify;
			else
				this.new_device_config.DarkIntensityType = Device.DarkIntensityType.None;
			
			this.di_delete_button.Sensitive             = true;
			this.device_property_apply_button.Sensitive = true;						
		}

//		internal void OnStreamTypeComboChanged(object o, System.EventArgs e)
//		{
//			ComboBox c = o as ComboBox;
//			
//			switch ((Device.StreamType)c.Active)
//			{
//				
//			case Device.StreamType.Continuous:
//				this.timed_interval_spin.Sensitive  = false;
//				this.timed_count_spin.Sensitive     = false;
//				this.timed_interval_label.Sensitive = false;
//				this.timed_count_label.Sensitive    = false;
//				break;
//				
//			case Device.StreamType.Timed:
//				this.timed_interval_spin.Sensitive  = true;
//				this.timed_count_spin.Sensitive     = true;
//				this.timed_interval_label.Sensitive = true;
//				this.timed_count_label.Sensitive    = true;
//				break;
//				
//			}
//			
//			if (this.new_device_config == null)
//				return;
//			
//			this.new_device_config.StreamType = (Device.StreamType)c.Active;
//			this.device_property_apply_button.Sensitive = true;						
//		}
		
		internal void OnTimedIntervalSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.TimedSpan = (uint)s.Value;
			this.device_property_apply_button.Sensitive = true;						
		}
		
		internal void OnTimedCountSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.TimedCount = (uint)s.Value;
			this.device_property_apply_button.Sensitive = true;						
		}
		
		private void OnDefaultCommentTextChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
		
			TextBuffer b = o as TextBuffer;
			this.new_device_config.DefaultComment = b.Text;
			
			this.device_property_apply_button.Sensitive = true;						
		}
		
		private void OnBgFilechooserSet(object o, System.EventArgs e)
		{
			FileChooserButton chooser = o as FileChooserButton;
			
			if (chooser.Filename == null)
			{
				// canceled
				return;
			}
			
			try
			{
				FileTypeInfo file_type = this.GetFileTypeInfo(chooser.Filter, true, false);
				
				Spectrum spectrum = file_type.Read(chooser.Filename);
				this.new_device_config.BackgroundSpectrum     = spectrum;
				this.new_device_config.BackgroundSpectrumType = Device.BackgroundSpectrumType.File;
				
				this.ShowBgPreview();
				
				this.bg_delete_button.Sensitive             = true;
				this.device_property_apply_button.Sensitive = true;
				
				Settings.Current.OpenBgFilePath = chooser.CurrentFolder;
			}
			catch (Exception ex)
			{
				new InfoMessage(this.parent,
				                Catalog.GetString("Error while reading file: {0}"),
				                ex.Message);
				this.new_device_config.BackgroundSpectrumType = Device.BackgroundSpectrumType.None;
				this.bg_delete_button.Sensitive = false;
				chooser.UnselectAll();
			}
		}
		
		internal void OnBgDeleteButtonClicked(object o, System.EventArgs e)
		{
			this.new_device_config.BackgroundSpectrumType = Device.BackgroundSpectrumType.None;
			this.new_device_config.BackgroundSpectrum     = null;
			this.bg_filechooser.UnselectAll();
			
			this.bg_delete_button.Sensitive             = false;
			this.device_property_apply_button.Sensitive = true;
		}

		internal void OnBgRecordButtonClicked(object o, System.EventArgs e)
		{
			Spectrum spectrum = null;
			Device dev = null;

			bool apply_sensitive = this.device_property_apply_button.Sensitive; 
			this.device_property_apply_button.Sensitive = false;
			this.GUI.Sensitive = false;
			UserInterface.ProcessEvents_();
			
			try
			{
				dev = this.active_devices.Idle[0];
				dev.StateNotification = false;
				
				if (dev.CurrentConfig.Average != (ushort)this.average_spin.Value)
				{
					ushort sav_average = dev.CurrentConfig.Average;
					dev.CurrentConfig.Average = (ushort)this.average_spin.Value;
					dev.WriteConfig();
					spectrum = this.Single(dev, true);
					dev.CurrentConfig.Average = sav_average;
					dev.WriteConfig();
				}
				else
				{
					spectrum = this.Single(dev, true);
				}
			}
			catch (Exception ex)
			{
				new InfoMessage(this.parent,
				                Catalog.GetString("Error while getting spectrum: {0}"),
				                ex.Message);
			}
			finally
			{
				try
				{
					dev.StateNotification = true;
				} 
				catch {}
				this.GUI.Sensitive = true;
			}
			
			if (spectrum == null)
			{
				// state notification was deactivated
				this.spectrometer_tv.UpdateDevice(dev);
				this.OnDeviceStateChanged(dev);
				this.new_device_config.BackgroundSpectrumType = Device.BackgroundSpectrumType.None;
				this.device_property_apply_button.Sensitive = apply_sensitive;
				return;
			}

			this.new_device_config.BackgroundSpectrum     = spectrum;
			this.new_device_config.BackgroundSpectrumType = Device.BackgroundSpectrumType.Record;
			this.ShowBgPreview();
			
			this.bg_delete_button.Sensitive             = true;
			this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnDiDeleteButtonClicked(object o, System.EventArgs e)
		{
			this.new_device_config.DarkIntensityType = Device.DarkIntensityType.None;
			this.new_device_config.DarkIntensity = new DarkIntensity(0f, 0f);
			this.di_specify_spin.Value = 0f;
			
			this.di_delete_button.Sensitive              = false;
			this.device_property_apply_button.Sensitive  = true;
		}
		
		internal void OnDiRecordButtonClicked(object o, System.EventArgs e)
		{
			Spectrum spectrum = null;
			Device dev = null;
			
			bool apply_sensitive = this.device_property_apply_button.Sensitive; 
			this.device_property_apply_button.Sensitive = false;
			this.GUI.Sensitive = false;
			UserInterface.ProcessEvents_();

			try
			{
				dev = this.active_devices.Idle[0];
				dev.StateNotification = false;
				dev.SetFinderWheel(FinderWheelPosition.White, UserInterface.ProcessEvents_);
				
				if (dev.CurrentConfig.Average != (ushort)this.average_spin.Value)
				{
					ushort sav_average = dev.CurrentConfig.Average;
					dev.CurrentConfig.Average = (ushort)this.average_spin.Value;
					dev.WriteConfig();
					spectrum = this.Single(dev, false);
					dev.CurrentConfig.Average = sav_average;
					dev.WriteConfig();
				}
				else
				{
					spectrum = this.Single(dev, false);
				}
			}
			catch (Exception ex)
			{
				new InfoMessage(this.parent, 
				                Catalog.GetString("Error while getting spectrum: {0}"),
				                ex.Message);
			}
			finally
			{
				try
				{
					dev.StateNotification = true;
				} 
				catch {}
				this.GUI.Sensitive = true;
			}
			
			if (spectrum == null)
			{
				// state notification was deactivated
				this.spectrometer_tv.UpdateDevice(dev);
				this.OnDeviceStateChanged(dev);
				this.new_device_config.DarkIntensityType = Device.DarkIntensityType.None;
				this.device_property_apply_button.Sensitive = apply_sensitive;
				return;
			}

			this.ShowDiPreview(spectrum);

			double mean  = spectrum.RawIntensity.YMean();
			double sigma = spectrum.RawIntensity.YSigma();
			
			this.di_specify_spin.Value = mean;
			this.new_device_config.DarkIntensity = new DarkIntensity(mean, sigma);
			this.new_device_config.DarkIntensityType = Device.DarkIntensityType.Record;

			this.di_delete_button.Sensitive             = true;
			this.device_property_apply_button.Sensitive = true;
		}

		private void OnSingleFolderChanged(object o, System.EventArgs e)
		{
			FileChooser chooser = o as FileChooser;

			if (this.new_device_config == null)
				return;
			
			AutoSaveConfig save_config = this.new_device_config.UserData as AutoSaveConfig;
			
			if (this.new_device_config == null || save_config == null)
				return;

			if (save_config.SingleDir.Info.FullName == chooser.Filename)
				return;
			
			save_config.SingleDir.DisconnectSingleDevice();
			
			try
			{
				DirectoryProperty single_dir = new DirectoryProperty(chooser.Filename);
				single_dir.Active            = false;
				single_dir.AssociatedDevice  = this.current_device;
				single_dir.AutoSaveSingle    = true;
				single_dir.AutoSaveStream    = false;
				single_dir.SingleFilemask    = this.single_fmask_entry.Text;
				single_dir.SingleFiletype    = SpectrumFileType.CSV;
				single_dir.Active            = this.auto_single_checkbutton.Active;
				
				save_config.DisconnectSingleDevice();
				save_config.SingleDir = single_dir;

				Settings.Current.AutoSaveSingleDirectory = chooser.Filename;
				this.device_property_apply_button.Sensitive = true;
			}
			catch (Exception ex)
			{
				new InfoMessage(this.parent,
				                Catalog.GetString("Error while selecting directory: {0}"),
				                ex.Message);
				chooser.UnselectAll();
			}
		}

		private void OnStreamFolderChanged(object o, System.EventArgs e)
		{
			FileChooser chooser = o as FileChooser;
			
			if (this.new_device_config == null)
				return;
			
			AutoSaveConfig save_config = this.new_device_config.UserData as AutoSaveConfig;
			
			if (save_config == null)
				return;

			if (save_config.StreamDir.Info.FullName == chooser.Filename)
				return;
			
			save_config.StreamDir.DisconnectStreamDevice();

			try
			{
				DirectoryProperty stream_dir = new DirectoryProperty(chooser.Filename);
				stream_dir.Active            = false;
				stream_dir.AssociatedDevice  = this.current_device;
				stream_dir.AutoSaveSingle    = false;
				stream_dir.AutoSaveStream    = true;
				stream_dir.SingleFilemask    = this.stream_fmask_entry.Text;
				stream_dir.SingleFiletype    = SpectrumFileType.CSV;
				stream_dir.Active            = this.auto_stream_checkbutton.Active;
				
				save_config.DisconnectStreamDevice();
				save_config.StreamDir = stream_dir;
				
				Settings.Current.AutoSaveStreamDirectory     = chooser.Filename;
				this.device_property_apply_button.Sensitive  = true;
			}
			catch (Exception ex)
			{
				new InfoMessage(this.parent,
				                Catalog.GetString("Error while selecting directory: {0}"),
				                ex.Message);
				chooser.UnselectAll();
			}
		}

		internal void OnServiceDialogButtonClicked(object o, System.EventArgs e)
		{
			new ServiceDialog(this, this.active_devices[0]);
		}
		
		internal void OnAutoSingleCheckbuttonToggled(object o, System.EventArgs e)
		{
			this.SetAutoSaveControls(true);
			this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnAutoStreamCheckbuttonToggled(object o, System.EventArgs e)
		{
			this.SetAutoSaveControls(true);
			this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnSingleFmaskEntryChanged(object o, System.EventArgs e)
		{
			this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnStreamFmaskEntryChanged(object o, System.EventArgs e)
		{
			this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnDevicePropertyInputChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config != null)
				this.device_property_apply_button.Sensitive = true;
		}
		
		internal void OnDevicePropertyApplyButtonClicked(object o, System.EventArgs e)
		{
			this.device_property_apply_button.HasFocus  = true;

			try
			{
				List<string> warning_devices = new List<string>();
				if (this.active_devices.Idle.Count == 1)
				{
					if (this.new_device_config.HasBackgroundSpectrum &&
					    this.new_device_config.Average > this.new_device_config.BackgroundSpectrum.AverageCount)
						warning_devices.Add(string.Format("{0} ({1})",
						                                  this.active_devices.Idle[0].CurrentConfig.Name,
						                                  this.active_devices.Idle[0].Info.SerialNumber));
				}
				else
				{
					foreach (Device dev in this.active_devices.Idle)
					{
						if (dev.CurrentConfig.HasBackgroundSpectrum && 
						    this.new_device_config.Average > dev.CurrentConfig.BackgroundSpectrum.AverageCount)
							warning_devices.Add(string.Format("\"{0}\" ({1})",
							                                  dev.CurrentConfig.Name,
							                                  dev.Info.SerialNumber));
					}
				}
				
				if (warning_devices.Count > 0)
				{
					string msg;
					if (warning_devices.Count == 1)
					{
						msg = string.Format(Catalog.GetString("Configuration settings for device {0} define a background intensity which was acquired with lower average count than new value ({1}).\n\n" +
							"Apply configuration anyway?"), warning_devices[0], this.new_device_config.Average);
					}
					else
					{
						string devices = warning_devices[0];
						for (int ix=1; ix < warning_devices.Count; ++ix)
						{
							devices += ", " + warning_devices[ix];
						}
						msg = string.Format(Catalog.GetString("Configuration settings for devices {0} define background intensities which were acquired with lower average count than new value ({1}).\n\n" +
							"Apply configuration anyway?"), devices, this.new_device_config.Average);
					}
					MessageDialog dialog = new MessageDialog(this.parent, DialogFlags.Modal,
					                                         MessageType.Question, ButtonsType.YesNo,
					                                         msg);
					dialog.IconList = MainClass.QuickStepIcons;
					ResponseType choice = (ResponseType)dialog.Run();
					dialog.Destroy();
					
					if (choice != ResponseType.Yes)
						return;
				}

				if (this.active_devices.Idle.Count == 1)
				{
					this.SetAutoSaveAssociations();
					Device dev = this.active_devices.Idle[0];
					dev.CurrentConfig = this.new_device_config;
				}
				else
				{
					foreach (Device dev in this.active_devices.Idle)
					{
						Device.Config config = dev.CurrentConfig;
						
						config.Samples = this.new_device_config.Samples;
						config.Average = this.new_device_config.Average;
						config.Timeout = this.new_device_config.Timeout;
						
						config.StreamType = this.new_device_config.StreamType;
						config.TimedCount = this.new_device_config.TimedCount;
						config.TimedSpan  = this.new_device_config.TimedSpan;
						
						dev.CurrentConfig = config;
					}
				}
				this.current_device = null;

				this.device_property_apply_button.Sensitive = false;
			}
			catch (System.Exception ex)
			{
				Console.WriteLine("Error while writing configuration: " + ex.ToString());
				new InfoMessage(this.parent, 
				                Catalog.GetString("Error while writing configuration: {0}"),
				                ex.Message);
				this.current_device = null;
				this.UpdatePropertiesSpectrometer();
			}
		}
		
//		internal void __OnDiButtonClicked(object o, System.EventArgs e)
//		{
//			Spectrum spectrum = null;
//			Device dev = null;
//			
//			try
//			{
//				dev = this.active_devices.Idle[0];
//				dev.StateNotification = false;
//				spectrum = this.SingleShot(dev);
//			}
//			catch (Exception ex)
//			{
//				new InfoMessage(this.parent, "Error while getting spectrum:  {0}", ex.Message);
//			}
//			finally
//			{
//				try
//				{
//					dev.StateNotification = true;
//				} 
//				catch {}
//			}
//			
//			if (spectrum == null)
//			{
//				// state notification was deactivated
//				this.spectrometer_tv.UpdateDevice(dev);
//				this.OnDeviceStateChanged(dev);
//				this.new_device_config.DarkIntensityType = Device.DarkIntensityType.None;
//				return;
//			}
//
//			this.new_device_config.DarkIntensity.Intensity = spectrum.RawIntensity.YMean();
//			this.new_device_config.DarkIntensity.Sigma     = spectrum.RawIntensity.YSigma();
//			this.new_device_config.DarkIntensity.DateTime  = DateTime.Now;
//			this.new_device_config.DarkIntensityType       = Device.DarkIntensityType.Record;
//			this.device_property_apply_button.Sensitive    = true;
//		}
	}
}
