
using System;
using System.IO;
using System.Collections.Concurrent;
using Mono.Unix;
using Gtk;

using Hiperscan.Common;
using Hiperscan.SGS;
using Hiperscan.FileIO;
using Hiperscan.Spectroscopy;


namespace Hiperscan.Extensions.Acquisition
{

	public class Handlers
	{
		public static string AutoSaveFirstFilename = string.Empty;
		public volatile static bool Running = false;
		public volatile static string SavePath = string.Empty;
		public volatile static bool NeedClearPlot = false;

		private static ConcurrentDictionary<string,Spectrum> _current_tio2_spectra = new ConcurrentDictionary<string,Spectrum>();
		private static ConcurrentDictionary<string,Finder> _finders = new ConcurrentDictionary<string,Finder>();

		private static readonly bool no_wavelength_correction = Environment.GetEnvironmentVariable(Env.Plugin.ACQUISITION_NO_WLC) == "1";
		private static readonly bool no_plausibility_checks   = Environment.GetEnvironmentVariable(Env.Plugin.ACQUISITION_NO_PLAUSIBILITY_CHECKS) == "1";

		private static object create_directory_mutex = new object();
		
		public static void OnAutoSolidClicked(IHost host, bool sample_insert_mode)
		{
			Running = true;
			Plugin.host.MainWindow.Sensitive = false;

			try
			{
				Plugin.acquisition_count_spin.Update();

				if (Handlers.NeedClearPlot)
				{
					Plugin.host.ClearPlot();
					Handlers.NeedClearPlot = false;
				}

				for (int ix=0; ix < Plugin.acquisition_count_spin.Value; ++ix)
				{
					ConcurrentBag<Spectrum> current_spectra = new ConcurrentBag<Spectrum>();
					ConcurrentBag<Exception> exceptions = new ConcurrentBag<Exception>();

					AForge.Parallel.ThreadsCount = host.ActiveDevices.Connected.Count;
					AForge.Parallel.For(0, host.ActiveDevices.Connected.Count, jx => {

						try
						{
							Device dev = host.ActiveDevices.Connected[jx];

							if (!dev.IsFinder)
								return;

							dev.WaitForIdle(5000);

							dev.SetFinderWheel(FinderWheelPosition.Sample, null);

							ushort sav_average = dev.CurrentConfig.Average;
							if (sample_insert_mode)
								dev.CurrentConfig.Average = 2000;
							else
								dev.CurrentConfig.Average = Settings.Current.AcquisitionAverage;
							dev.WriteConfig();

							Spectrum current_spectrum = dev.Single(true, null);
                            SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
							current_spectrum.SpectrumType = SpectrumType.SolidSpecimen;

							if (sample_insert_mode)
							{
								if (current_spectrum.ProbeType == ProbeType.FinderSDStandard)
									current_spectrum.ProbeType = ProbeType.FinderSDInsert;
								else
									current_spectrum.ProbeType = ProbeType.FinderInsert;
							}

							dev.CurrentConfig.Average = sav_average;
							dev.WriteConfig();

							if (dev.AutoRecalibrationIsPending)
								Handlers.Recalibrate(dev, null);

							dev.SetAbsorbance(current_spectrum);
							dev.SetWavelengthCorrection(current_spectrum);

							current_spectra.Add(current_spectrum);
						}
						catch (Exception ex)
						{
							exceptions.Add(ex);
						}
					});

					if (exceptions.Count > 0)
						throw exceptions.ToArray()[0];

					foreach (Spectrum spectrum in current_spectra)
					{
						host.AddToCurrentPlot(spectrum);
					}
					host.FitPlot();
					host.ProcessEvents();
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow, 
				                     Catalog.GetString("Error while acquisition with auto-recalibration: {0}"),
				                     ex.ToString());
			}
			finally
			{
				Running = false;
				Plugin.host.MainWindow.Sensitive = true;
			}

			try
			{
				if (!string.IsNullOrEmpty(Handlers.AutoSaveFirstFilename))
					host.SaveAll(host.CurrentSpectra, Handlers.AutoSaveFirstFilename, true);
				
				Handlers.AutoSaveFirstFilename = string.Empty;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				Plugin.host.ShowInfoMessage(Plugin.host.MainWindow, Catalog.GetString("Cannot save spectra: {0}"), ex.Message);
			}
				
			host.UpdateProperties();
		}

		public static void OnAutoFluidClicked(IHost host)
		{
			Running = true;

			Plugin.host.MainWindow.Sensitive = false;

			try
			{
				if (Plugin.SampleInsertMode)
					throw new Exception(Catalog.GetString("Sample Insert mode is not supported for transflectance measurements."));

				Plugin.acquisition_count_spin.Update();

				for (int ix=0; ix < Plugin.acquisition_count_spin.Value; ++ix)
				{
					foreach (Device dev in host.ActiveDevices.Connected)
					{
						if (!dev.IsFinder)
							continue;

						if (Handlers.NeedClearPlot)
						{
							Plugin.host.ClearPlot();
							Handlers.NeedClearPlot = false;
						}

						dev.WaitForIdle(5000);
						
						dev.SetFinderWheel(FinderWheelPosition.Sample, host.ProcessEvents);

						ushort sav_average = dev.CurrentConfig.Average;
						dev.CurrentConfig.Average = Settings.Current.AcquisitionAverage;
						dev.WriteConfig();
						Spectrum current_spectrum = dev.Single(true, Plugin.host.ProcessEvents);
                        SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                        current_spectrum.SpectrumType = SpectrumType.FluidSpecimen;
						dev.CurrentConfig.Average = sav_average;
						dev.WriteConfig();
						
						dev.SetAbsorbance(current_spectrum);
						dev.SetWavelengthCorrection(current_spectrum);
						
						host.AddToCurrentPlot(current_spectrum);
						host.FitPlot();
					}
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow, 
				                     Catalog.GetString("Error while acquisition with auto-recalibration: {0}"),
				                     ex.Message);
			}
			finally
			{
				Running = false;
				Plugin.host.MainWindow.Sensitive = true;
			}

			try
			{
				if (!string.IsNullOrEmpty(Handlers.AutoSaveFirstFilename))
					host.SaveAll(host.CurrentSpectra, Handlers.AutoSaveFirstFilename, true);
				
				Handlers.AutoSaveFirstFilename = string.Empty;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				Plugin.host.ShowInfoMessage(Plugin.host.MainWindow, Catalog.GetString("Cannot save spectra: {0}"), ex.Message);
			}
				
			host.UpdateProperties();
		}
		
		public static void OnTitanClicked(IHost host)
		{
			try
			{
				Plugin.host.MainWindow.Sensitive = false;

				Handlers.GetSavePath();
				host.ProcessEvents();

				ConcurrentBag<Spectrum> current_spectra = new ConcurrentBag<Spectrum>();
				ConcurrentBag<Exception> exceptions = new ConcurrentBag<Exception>();

				AForge.Parallel.ThreadsCount = host.ActiveDevices.Connected.Count;
				AForge.Parallel.For(0, host.ActiveDevices.Connected.Count, jx => {

					try
					{
						Device dev = host.ActiveDevices.Connected[jx];

						if (!dev.IsFinder)
							return;

						dev.WaitForIdle(5000);

						if (dev.AutoRecalibrationIsPending)
							Handlers.Recalibrate(dev, host.ProcessEvents);

						dev.SetFinderWheel(FinderWheelPosition.Sample, null);

						ushort sav_average = dev.CurrentConfig.Average;
						dev.CurrentConfig.Average = Settings.Current.ReferenceAverage;
						dev.WriteConfig();
						Spectrum white_spectrum = dev.Single(true, null);
                        SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                        dev.CurrentConfig.Average = sav_average;
						dev.WriteConfig();

						string fname = white_spectrum.Id.Remove(0, 2) + "_extwhite";
						white_spectrum.Id = "1_" + "%%reference%%_" + dev.Info.SerialNumber;
						dev.SetAbsorbance(white_spectrum);
						dev.SetWavelengthCorrection(white_spectrum);
						white_spectrum.Label += " " + Catalog.GetString("White Reference");
						white_spectrum.SpectrumType = SpectrumType.ExternalWhite;

						if (Handlers.no_plausibility_checks == false)
							Handlers.GetFinder(dev).CheckWhiteReference(white_spectrum);

						string qs_home = GetSavePath();
						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(qs_home))
								Directory.CreateDirectory(qs_home);
						}

						string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(data_dir))
								Directory.CreateDirectory(data_dir);
						}

						string white_dir = Path.Combine(data_dir, Catalog.GetString("White Reference"));
						Plugin.host.SetCreator(white_spectrum);

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(white_dir))
								Directory.CreateDirectory(white_dir);
						}

						CSV.Write(white_spectrum, Path.Combine(white_dir, fname));

						Handlers.SetCurrentTiO2Spectrum(dev, white_spectrum);

						current_spectra.Add(white_spectrum);
					}
					catch (Exception ex)
					{
						exceptions.Add(ex);
					}
				});

				if (exceptions.Count > 0)
				{
					Console.WriteLine(exceptions.ToArray()[0]);
					throw exceptions.ToArray()[0];
				}

				foreach (Spectrum spectrum in current_spectra)
				{
					host.AddToCurrentPlot(spectrum);
				}
				host.FitPlot();
				host.ProcessEvents();

				Handlers.NeedClearPlot = true;

//					Plugin.toolbar_info1.IsSensitive = true;
				Plugin.LastExtwhiteTime = DateTime.Now;
				Plugin.LastTransflectanceInsertReferenceTime = DateTime.MinValue;
				Plugin.ResetExternalReferences(new TimeSpan(0, 10, 0));
				Plugin.UpdateControls();
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow,
				                     Catalog.GetString("Error while acquisition of White Standard spectrum: {0}"),
				                     ex.Message);
			}
			finally
			{
				Plugin.host.MainWindow.Sensitive = true;
			}
				
			host.UpdateProperties();
			//GLib.Timeout.Add(100, delegate() { this.OnZoomFitButtonClicked(o, e); return false; });
		}
		
		public static void OnEmptyClicked(IHost host)
		{
			try
			{
				Plugin.host.MainWindow.Sensitive = false;

				Handlers.GetSavePath();
				host.ProcessEvents();

				ConcurrentBag<Spectrum> current_spectra = new ConcurrentBag<Spectrum>();
				ConcurrentBag<Exception> exceptions = new ConcurrentBag<Exception>();

				AForge.Parallel.ThreadsCount = host.ActiveDevices.Connected.Count;
				AForge.Parallel.For(0, host.ActiveDevices.Connected.Count, jx => {

					try
					{
						Device dev = host.ActiveDevices.Connected[jx];

						if (!dev.IsFinder)
							return;
					
						dev.WaitForIdle(5000);
					
						if (dev.AutoRecalibrationIsPending)
							Handlers.Recalibrate(dev, host.ProcessEvents);

						dev.SetFinderWheel(FinderWheelPosition.Sample, host.ProcessEvents);

						ushort sav_average = dev.CurrentConfig.Average;
						dev.CurrentConfig.Average = Settings.Current.ReferenceAverage;
						dev.WriteConfig();
						Spectrum black_spectrum = dev.Single(true, Plugin.host.ProcessEvents);
                        SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                        dev.CurrentConfig.Average = sav_average;
						dev.WriteConfig();

						string fname = black_spectrum.Id.Remove(0, 2) + "_extblack";
						black_spectrum.Id = "1_" + "%%reference%%_" + dev.Info.SerialNumber;
						dev.SetAbsorbance(black_spectrum);
						dev.SetWavelengthCorrection(black_spectrum);
						black_spectrum.Label += " " + Catalog.GetString("Black Reference");
						black_spectrum.SpectrumType = SpectrumType.ExternalEmpty;

						if (Handlers.no_plausibility_checks == false)
                            Handlers.GetFinder(dev).CheckBlackReference(black_spectrum);

						string qs_home = GetSavePath();

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(qs_home))
								Directory.CreateDirectory(qs_home);
						}
					
						string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));


						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(data_dir))
								Directory.CreateDirectory(data_dir);
						}
					
						string black_ref_dir = Path.Combine(data_dir, Catalog.GetString("Black Reference"));
						Plugin.host.SetCreator(black_spectrum);

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(black_ref_dir))
								Directory.CreateDirectory(black_ref_dir);
						}
                        CSV.Write(black_spectrum, Path.Combine(black_ref_dir, fname));

						current_spectra.Add(black_spectrum);

						Handlers.GetFinder(dev).__SetSpectra(null, null, null, null, null, null, black_spectrum, null, null, null);
					}
					catch (Exception ex)
					{
						exceptions.Add(ex);
					}
				});

				if (exceptions.Count > 0)
					throw exceptions.ToArray()[0];

				foreach (Spectrum spectrum in current_spectra)
				{
					host.AddToCurrentPlot(spectrum);
				}

				host.FitPlot();
				host.ProcessEvents();

				Handlers.NeedClearPlot = true;

				Plugin.LastExtemptyTime = DateTime.Now;
				Plugin.ResetExternalReferences(new TimeSpan(0, 10, 0));

				Plugin.UpdateControls();
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow,
				                     Catalog.GetString("Error while acquisition of Empty Standard spectrum: {0}"),
				                     ex.Message);
			}
			finally
			{
				Plugin.host.MainWindow.Sensitive = true;
			}
				
			host.UpdateProperties();
//			GLib.Timeout.Add(100, delegate() { this.OnZoomFitButtonClicked(o, e); return false; });
		}
		
		public static void OnLabsphereClicked(IHost host)
		{
			try
			{
				Plugin.host.MainWindow.Sensitive = false;

				if (Plugin.SampleInsertMode)
					throw new Exception(Catalog.GetString("Sample Insert mode is not supported for Labsphere measurements."));

				foreach (Device dev in host.ActiveDevices.Connected)
				{
					if (!dev.IsFinder)
						continue;

					dev.WaitForIdle(5000);
					
					dev.SetFinderWheel(FinderWheelPosition.Sample, host.ProcessEvents);
					
					ushort sav_average = dev.CurrentConfig.Average;
					dev.CurrentConfig.Average = Settings.Current.ReferenceAverage;
					dev.WriteConfig();
					Spectrum spectrum = dev.Single(true, Plugin.host.ProcessEvents);
                    SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                    dev.CurrentConfig.Average = sav_average;
					dev.WriteConfig();
					
					string fname = spectrum.Id.Remove(0, 2) + "_labsphere";
					spectrum.Id = "1_" + "%%reference%%_" + dev.Info.SerialNumber;
					dev.SetAbsorbance(spectrum);
					dev.SetWavelengthCorrection(spectrum);
					spectrum.Label += " Labsphere";
					spectrum.SpectrumType = SpectrumType.ExternalWhite;
					
					string qs_home = GetSavePath();
					if (!Directory.Exists(qs_home))
						Directory.CreateDirectory(qs_home);
					
					string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));
					if (!Directory.Exists(data_dir))
						Directory.CreateDirectory(data_dir);
					
					string labsphere_dir = Path.Combine(data_dir, "Labsphere");
					Plugin.host.SetCreator(spectrum);
					if (!Directory.Exists(labsphere_dir))
						Directory.CreateDirectory(labsphere_dir);
					CSV.Write(spectrum, Path.Combine(labsphere_dir, fname));

					host.AddToCurrentPlot(spectrum);
					host.FitPlot();

					Handlers.NeedClearPlot = true;
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow,
				                     Catalog.GetString("Error while acquisition of Labsphere spectrum: {0}"),
				                     ex.Message);
			}
			finally
			{
				Plugin.host.MainWindow.Sensitive = true;
			}
				
			host.UpdateProperties();
//			GLib.Timeout.Add(100, delegate() { this.OnZoomFitButtonClicked(o, e); return false; });
		}
		
		public static void OnZenithClicked(IHost host, bool sample_insert_mode)
		{
			try
			{
				Plugin.host.MainWindow.Sensitive = false;

				Handlers.GetSavePath();
				host.ProcessEvents();

				ConcurrentBag<Spectrum> current_spectra = new ConcurrentBag<Spectrum>();
				ConcurrentBag<Exception> exceptions = new ConcurrentBag<Exception>();

				AForge.Parallel.ThreadsCount = host.ActiveDevices.Connected.Count;
				AForge.Parallel.For(0, host.ActiveDevices.Connected.Count, jx => {

					try
					{
						Device dev = host.ActiveDevices.Connected[jx];

						if (!dev.IsFinder)
							return;

						dev.WaitForIdle(5000);

						if (dev.AutoRecalibrationIsPending)
							Handlers.Recalibrate(dev, host.ProcessEvents);

						dev.SetFinderWheel(FinderWheelPosition.Sample, host.ProcessEvents);

						ushort sav_average = dev.CurrentConfig.Average;
						dev.CurrentConfig.Average = Settings.Current.ReferenceAverage;
						dev.WriteConfig();
						Spectrum extwhite = dev.Single(true, Plugin.host.ProcessEvents);
                        SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                        dev.CurrentConfig.Average = sav_average;
						dev.WriteConfig();

						string fname = extwhite.Id.Remove(0, 2) + "_extzenith";
						if (sample_insert_mode)
							fname = extwhite.Id.Remove(0, 2) + "_zenith_insert";

                        extwhite.Id = "1_" + "%%reference%%_" + dev.Info.SerialNumber;
						dev.SetAbsorbance(extwhite);
						dev.SetWavelengthCorrection(extwhite);

						extwhite.Label += " Zenith";
						if (sample_insert_mode)
						    extwhite.Label += " Insert";

						extwhite.SpectrumType = SpectrumType.ExternalWhite;

						if (sample_insert_mode)
						{
							if (extwhite.ProbeType == ProbeType.FinderSDStandard)
								extwhite.ProbeType = ProbeType.FinderSDInsert;
							else
								extwhite.ProbeType = ProbeType.FinderInsert;

							if (Handlers.no_plausibility_checks == false)
								Handlers.GetFinder(dev).CheckSampleInsertWhiteReference(extwhite);
						}
						else
						{
							if (Handlers.no_plausibility_checks == false)
								Handlers.GetFinder(dev).CheckWhiteReference(extwhite);

							if (Environment.GetEnvironmentVariable(Env.Plugin.ACQUISITION_NO_PLAUSIBILITY_CHECKS) != "1" &&
								Handlers.GetCurrentTiO2Spectrum(dev) != null && Handlers.GetCurrentTiO2Spectrum(dev).Intensity.YMax() > extwhite.Intensity.YMax())
								throw new Exception(Catalog.GetString("Zenith intensity is less than TiO2 intensity. Please repeat external referencing."));
						}

						string qs_home = GetSavePath();

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(qs_home))
								Directory.CreateDirectory(qs_home);
						}

						string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(data_dir))
								Directory.CreateDirectory(data_dir);
						}
					
						string zenith_dir = Path.Combine(data_dir, "Zenith");

						if (sample_insert_mode)
							zenith_dir = Path.Combine(data_dir, "Zenith Insert");

                        Plugin.host.SetCreator(extwhite);

						lock (Handlers.create_directory_mutex)
						{
							if (!Directory.Exists(zenith_dir))
								Directory.CreateDirectory(zenith_dir);
						}
					
						CSV.Write(extwhite, Path.Combine(zenith_dir, fname));
						current_spectra.Add(extwhite);

                        Handlers.GetFinder(dev).__SetSpectra(null, null, null, null, extwhite, null, null, 
						                                     Handlers.GetFinder(dev).CurrentInternalOxidSpectrum, 
						                                     Handlers.GetFinder(dev).CurrentInternalWhiteSpectrum,
						                                     Handlers.GetFinder(dev).CurrentInternalDarkSpectrum);
					}
					catch (Exception ex)
					{
						exceptions.Add(ex);
					}
				});

				if (exceptions.Count > 0)
					throw exceptions.ToArray()[0];

				foreach (Spectrum spectrum in current_spectra)
				{
					host.AddToCurrentPlot(spectrum);
				}

				host.FitPlot();
				host.ProcessEvents();

				Handlers.NeedClearPlot = true;

				if (sample_insert_mode)
					Plugin.LastSampleInsertZenithTime = DateTime.Now;
				else
					Plugin.LastZenithTime = DateTime.Now;
				Plugin.ResetExternalReferences(new TimeSpan(0, 10, 0));

				Plugin.UpdateControls();
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow,
				                     Catalog.GetString("Error while acquisition of white reference spectrum: {0}"),
				                     ex.Message);
			}
			finally
			{
				Plugin.host.MainWindow.Sensitive = true;
			}
				
			host.UpdateProperties();
//			GLib.Timeout.Add(100, delegate() { this.OnZoomFitButtonClicked(o, e); return false; });
		}
		
		public static void OnTransflectanceInsertClicked(IHost host)
		{
			try
			{
				Plugin.host.MainWindow.Sensitive = false;

				if (Plugin.SampleInsertMode)
					throw new Exception(Catalog.GetString("Sample Insert mode is not supported for transflectance measurements."));

				foreach (Device dev in host.ActiveDevices.Connected)
				{
					if (!dev.IsFinder)
						continue;

					dev.WaitForIdle(5000);
					
					if (dev.AutoRecalibrationIsPending)
						Handlers.Recalibrate(dev, host.ProcessEvents);

					dev.SetFinderWheel(FinderWheelPosition.Sample, host.ProcessEvents);
					
					ushort sav_average = dev.CurrentConfig.Average;
					dev.CurrentConfig.Average = Settings.Current.ReferenceAverage;
					dev.WriteConfig();
					Spectrum spectrum = dev.Single(true, Plugin.host.ProcessEvents);
                    SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
                    dev.CurrentConfig.Average = sav_average;
					dev.WriteConfig();
					
					
					string fname = spectrum.Id.Remove(0, 2) + "_transflectref";
					spectrum.Id = "1_" + "%%transflectref%%_" + dev.Info.SerialNumber;
					spectrum.Label += " " + Catalog.GetString("Transflectance Insert");
					spectrum.SpectrumType = SpectrumType.ExternalFluidWhite;

					dev.SetWavelengthCorrection(spectrum);
					dev.CurrentConfig.BackgroundSpectrum = spectrum.Clone();

					if (Handlers.no_plausibility_checks == false)
                    {
                        Finder finder = Handlers.GetFinder(dev);

                        if (finder.CurrentExternalWhiteSpectrum != null)
                            finder.CheckTransflectanceInsert(spectrum, 
							     finder.CurrentExternalWhiteSpectrum,
							     finder.Device.CurrentConfig.DarkIntensity);
                    }

					string qs_home = GetSavePath();
					if (!Directory.Exists(qs_home))
						Directory.CreateDirectory(qs_home);
					
					string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));
					if (!Directory.Exists(data_dir))
						Directory.CreateDirectory(data_dir);
					
					string white_dir = Path.Combine(data_dir, Catalog.GetString("Transflectance Insert"));
					Plugin.host.SetCreator(spectrum);
					if (!Directory.Exists(white_dir))
						Directory.CreateDirectory(white_dir);
					CSV.Write(spectrum, Path.Combine(white_dir, fname));

					host.AddToCurrentPlot(spectrum);
					host.FitPlot();

					Handlers.NeedClearPlot = true;

//					Plugin.toolbar_info1.IsSensitive = false;
					Plugin.LastTransflectanceInsertReferenceTime = DateTime.Now;
					Plugin.UpdateControls();
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				host.ShowInfoMessage(Plugin.host.MainWindow,
				                     Catalog.GetString("Error while acquisition of Transflectance Insert spectrum: {0}"),
				                     ex.Message);
			}
			finally
			{
				Plugin.host.MainWindow.Sensitive = true;
			}
				
			host.UpdateProperties();
			//GLib.Timeout.Add(100, delegate() { this.OnZoomFitButtonClicked(o, e); return false; });
		}

		public static void OnSaveAllClicked(IHost host)
		{
			new SampleIdWindow();
		}
		
		public static void OnSaveAfterAcquisitionClicked(IHost host)
		{
			new LocationChooser();
		}
		
		public static void OnResetReferencePathClicked(IHost host)
		{
			Handlers.SavePath = string.Empty;
		}

		private static void Recalibrate(Device dev, IdleTaskHandler idle_handler)
		{
			dev.CurrentConfig.WavelengthCorrection = null;
			
			ushort sav_average = dev.CurrentConfig.Average;
			dev.CurrentConfig.Average = Settings.Current.AcquisitionAverage;
			dev.WriteConfig();
			
			// dark intensity
			//UserInterface.ProcessEvents();
			dev.SetFinderWheel(FinderWheelPosition.White, idle_handler);
			Spectrum di_spectrum = dev.Single(false);
            SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
            dev.CurrentConfig.DarkIntensity = new DarkIntensity(di_spectrum.RawIntensity.YMean(),
			                                                    di_spectrum.RawIntensity.YSigma());
			dev.CurrentConfig.DarkIntensityType = Device.DarkIntensityType.Record;
			
			// background
			//UserInterface.ProcessEvents();
			dev.SetFinderWheel(FinderWheelPosition.White, idle_handler);
			Spectrum bg_spectrum = dev.Single(true, idle_handler);
            SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
            dev.CurrentConfig.BackgroundSpectrum     = new Spectrum(bg_spectrum);
			dev.CurrentConfig.BackgroundSpectrumType = Device.BackgroundSpectrumType.Record;
			
			// calibration
			//UserInterface.ProcessEvents();
			dev.SetFinderWheel(FinderWheelPosition.Reference, idle_handler);
			Spectrum rf_spectrum = dev.Single(true, idle_handler);
            SampleIdWindow.SerialNumber = dev.Info.SerialNumber;
            dev.CurrentConfig.Average = sav_average;
			dev.WriteConfig();
			dev.SetAbsorbance(rf_spectrum);
			rf_spectrum.LimitBandwidth = true;

			if (Handlers.no_wavelength_correction == false)
			{
				if ((int)dev.FinderVersion.ReferenceWheel < 2)
				{
					DataSet references = WavelengthCorrection.GetWavelengthReferences(WavelengthCorrection.ReferenceType.NIST15nm);
					dev.CurrentConfig.WavelengthCorrection = WavelengthCorrection.Calculate(references, rf_spectrum.Absorbance.SNV());
				}
				else
				{
					Spectrum ref_spectrum = Finder.GetWavelengthReference(dev.FinderVersion.ReferenceWheel);
					if (Finder.HasZenithRecalibrationReference(dev))
						dev.CurrentConfig.WavelengthCorrection = new WavelengthCorrection(ref_spectrum, rf_spectrum, Finder.ZenithRecalibrationWavelengths, false);
					else
						dev.CurrentConfig.WavelengthCorrection = new WavelengthCorrection(ref_spectrum, rf_spectrum, null, true);
				}
			}

			dev.SetWavelengthCorrection(rf_spectrum);
			
			dev.CalibrationInfo = new CalibrationInfo(DateTime.Now, 
			                                          dev.Frequency.Y[dev.Frequency.Count-1],
			                                          2.0, 0.0005);
			
			string qs_home = GetSavePath();
			if (!Directory.Exists(qs_home))
				Directory.CreateDirectory(qs_home);
			
			string data_dir = Path.Combine(qs_home, Catalog.GetString("Referencing"));
			if (!Directory.Exists(data_dir))
				Directory.CreateDirectory(data_dir);
			
			string di_dir = Path.Combine(data_dir, Catalog.GetString("Dark"));
			Plugin.host.SetCreator(di_spectrum);
			if (!Directory.Exists(di_dir))
				Directory.CreateDirectory(di_dir);
			CSV.Write(di_spectrum, Path.Combine(di_dir, di_spectrum.Id.Remove(0, 2) + "_intdark"));
			
			string bg_dir = Path.Combine(data_dir, Catalog.GetString("White"));
			Plugin.host.SetCreator(bg_spectrum);
			if (!Directory.Exists(bg_dir))
				Directory.CreateDirectory(bg_dir);
			CSV.Write(bg_spectrum, Path.Combine(bg_dir, bg_spectrum.Id.Remove(0, 2) + "_intwhite"));
			
			string rf_dir = Path.Combine(data_dir, Catalog.GetString("Oxide"));
			Plugin.host.SetCreator(rf_spectrum);
			if (!Directory.Exists(rf_dir))
				Directory.CreateDirectory(rf_dir);
			CSV.Write(rf_spectrum, Path.Combine(rf_dir, rf_spectrum.Id.Remove(0, 2) + "_intoxid"));

			Handlers.GetFinder(dev).__SetSpectra(null, bg_spectrum, di_spectrum, rf_spectrum, null, null, null, null, null, null);
		}
		
		internal static string GetSavePath()
		{
			if (string.IsNullOrEmpty(Handlers.SavePath))
			{
				FileChooserDialog dialog = new FileChooserDialog(Catalog.GetString("Choose output directory"),
				                                                 Plugin.host.MainWindow,
				                                                 FileChooserAction.SelectFolder,
				                                                 Stock.Open, ResponseType.Ok,
				                                                 Stock.Cancel, ResponseType.Cancel);
				dialog.SetCurrentFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
				int choice = dialog.Run();
				
				if (choice == (int)ResponseType.Ok)
					Handlers.SavePath = dialog.Filename;
				dialog.Destroy();
			}
			
			if (string.IsNullOrEmpty(Handlers.SavePath))
			{
				string home = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
				string qs_home = Path.Combine(home, ".QuickStep");
				Handlers.SavePath = qs_home;
			}

			if (Handlers.SavePath.EndsWith("_SI"))
				return Handlers.SavePath.Substring(0, Handlers.SavePath.Length-3);

			return Handlers.SavePath;
		}

		private static Finder GetFinder(Device dev)
		{
			string serial = dev.Info.SerialNumber;

			if (Handlers._finders.ContainsKey(serial) == false)
			{
				foreach (Device device in Plugin.host.ActiveDevices.Idle)
				{
					if (device.IsFinder == false)
						continue;

					if (Handlers._finders.ContainsKey(device.Info.SerialNumber))
						continue;

					Handlers._finders.TryAdd(device.Info.SerialNumber, new Finder(dev, (ReferenceWheelVersion)dev.FinderVersion.ReferenceWheel, ExternalWhiteReferenceType.Zenith, "finder_dummy"));
				}
			}

			return Handlers._finders[serial];
		}

		private static Spectrum GetCurrentTiO2Spectrum(Device dev)
		{
			string serial = dev.Info.SerialNumber;

			if (Handlers._current_tio2_spectra.ContainsKey(serial) == false)
				return null;

			return Handlers._current_tio2_spectra[serial];
		}

		private static void SetCurrentTiO2Spectrum(Device dev, Spectrum spectrum)
		{
			string serial = dev.Info.SerialNumber;

			if (Handlers._current_tio2_spectra.ContainsKey(serial))
			{
				Handlers._current_tio2_spectra[serial] = spectrum;
			}
			else
			{
				Handlers._current_tio2_spectra.TryAdd(serial, spectrum);
			}
		}
	}
}
