// UI.Properties.Spectrum.cs created with MonoDevelop
// User: klose at 15:43 04.02.2010
// CVS release: $Id: UI.Properties.Spectrum.cs,v 1.5 2011-04-19 12:36:59 klose Exp $
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2009-2010  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.Drawing;
using Gtk;
using Glade;

using Hiperscan.SGS;
using Hiperscan.FileIO;
using Hiperscan.GUI.Figure;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;


namespace Hiperscan.GUI
{

	public partial class UserInterface
	{
		[Widget] Gtk.Fixed property_spectrum_fixed = null;

		[Widget] Gtk.Label spectrum_time_label           = null;
		[Widget] Gtk.Label spectrum_file_path_label      = null;
		[Widget] Gtk.Label spectrum_serial_label         = null;
		[Widget] Gtk.Label spectrum_dark_intensity_label = null;
		[Widget] Gtk.Label spectrum_average_label        = null;
		
		[Widget] Gtk.CheckButton spectrum_absorbance_checkbutton            = null;
		[Widget] Gtk.CheckButton spectrum_wavelength_correction_checkbutton = null;
		[Widget] Gtk.CheckButton spectrum_resolution_limit_checkbutton      = null;

		[Widget] Gtk.Button spectrum_properties_button = null;
		[Widget] Gtk.Button spectrum_edit_button = null;

		[Widget] Gtk.TextView spectrum_comment_text2 = null;
		
		[Widget] Gtk.ColorButton plot_colorbutton = null;
		[Widget] Gtk.SpinButton  plot_width_spin  = null;
		[Widget] Gtk.ComboBox    plot_style_combo = null;
		
		private List<Spectrum> current_spectra_config;
		
		
		private void InitializePropertiesSpectrum()
		{
			this.spectrum_comment_text2.Buffer.Changed += delegate {
				if (!this.updating_properties_spectrum)
					this.current_spectra_config[0].Comment = this.spectrum_comment_text2.Buffer.Text;
			};
			
			this.UpdatePropertiesSpectrum(null);
		}
		
		
		private volatile bool updating_properties_spectrum = false;
		
		private void UpdatePropertiesSpectrum(List<Spectrum> spectra)
		{
			if (this.property_notebook.Page != 2)
				return;
			
			if (spectra == null || spectra.Count == 0)
			{
				this.current_object_label.Text = string.Empty;
				this.property_spectrum_fixed.Sensitive = false;
				this.spectrum_properties_button.Sensitive = false;
				this.spectrum_edit_button.Sensitive = false;
				return;
			}


			this.updating_properties_spectrum = true;
			
			if (spectra.Count == 1)
			{
				this.current_object_label.Text = "(" + spectra[0].Label + ")";
				
				this.spectrum_time_label.Text = spectra[0].Timestamp.ToString();
				this.spectrum_time_label.Sensitive = true;
				this.spectrum_properties_button.Sensitive = true;
				this.spectrum_edit_button.Sensitive = true;
				
				if (spectra[0].FileInfo != null)
				{
					this.spectrum_file_path_label.Text = spectra[0].FileInfo.FullName;
					this.spectrum_file_path_label.TooltipText = spectra[0].FileInfo.FullName;
					this.spectrum_file_path_label.HasTooltip = true;
				}
				else
				{
					this.spectrum_file_path_label.Text = Catalog.GetString("n/a");
					this.spectrum_file_path_label.HasTooltip = false;
				}
				this.spectrum_file_path_label.Sensitive = true;

				this.spectrum_absorbance_checkbutton.Active = spectra[0].HasAbsorbance;
				this.spectrum_absorbance_checkbutton.Inconsistent = false;
				
				this.spectrum_wavelength_correction_checkbutton.Active = spectra[0].HasWavelengthCorrection;
				this.spectrum_wavelength_correction_checkbutton.Inconsistent = false;

				this.spectrum_resolution_limit_checkbutton.Active = spectra[0].LimitBandwidth;
				this.spectrum_resolution_limit_checkbutton.Inconsistent = false;
				this.spectrum_resolution_limit_checkbutton.Sensitive = !spectra[0].IsPreview;

				if (spectra[0].HasDarkIntensity)
					this.spectrum_dark_intensity_label.Text = spectra[0].DarkIntensity.Intensity.ToString("f4");
				else
					this.spectrum_dark_intensity_label.Text = Catalog.GetString("n/a");
				this.spectrum_dark_intensity_label.Sensitive = true;

				if (string.IsNullOrEmpty(spectra[0].Serial))
					this.spectrum_serial_label.Text = Catalog.GetString("n/a");
				else
				    this.spectrum_serial_label.Text = spectra[0].Serial;
				this.spectrum_serial_label.Sensitive = true;
				
				if (spectra[0].AverageCount > 0)
					this.spectrum_average_label.Text = spectra[0].AverageCount.ToString();
				else
					this.spectrum_average_label.Text = Catalog.GetString("n/a");
				this.spectrum_average_label.Sensitive = !spectra[0].IsPreview;

				this.spectrum_comment_text2.Buffer.Text = spectra[0].Comment;
				this.spectrum_comment_text2.Sensitive = !spectra[0].IsPreview;
			
				this.plot_colorbutton.Color = UserInterface.GdkColor(spectra[0].Color);
				this.plot_colorbutton.Sensitive = !spectra[0].IsPreview;
				
				this.plot_style_combo.Active = (int)spectra[0].LineStyle;
				this.plot_style_combo.Sensitive = true;
				
				this.plot_width_spin.Value = spectra[0].LineWidth;
				this.plot_width_spin.Sensitive = true;
			}
			else
			{
				this.current_object_label.Text = string.Empty;
				
				this.spectrum_time_label.Text = string.Empty;
				this.spectrum_time_label.Sensitive = false;
				this.spectrum_properties_button.Sensitive = false;
				this.spectrum_edit_button.Sensitive = false;
				
				bool active = spectra[0].HasAbsorbance;
				bool inconsistent = false;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.HasAbsorbance != active)
						inconsistent = true;
				}
				this.spectrum_absorbance_checkbutton.Active = active;
				this.spectrum_absorbance_checkbutton.Inconsistent = inconsistent;
				
				active = spectra[0].HasWavelengthCorrection;
				inconsistent = false;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.HasWavelengthCorrection != active)
							active = spectrum.HasWavelengthCorrection;
				}
				this.spectrum_wavelength_correction_checkbutton.Active = active;
				this.spectrum_wavelength_correction_checkbutton.Inconsistent = inconsistent;
				
				active = spectra[0].LimitBandwidth;
				inconsistent = false;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.LimitBandwidth != active)
						inconsistent = true;
				}
				this.spectrum_resolution_limit_checkbutton.Active = active;
				this.spectrum_resolution_limit_checkbutton.Inconsistent = inconsistent;
				
				
				string serial = spectra[0].Serial;
				inconsistent = false;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.Serial != serial)
						inconsistent = true;
				}
				if (!inconsistent)
				{
					this.spectrum_serial_label.Text = serial;
					this.spectrum_serial_label.Sensitive = true;
				}
				else
				{
					this.spectrum_serial_label.Text = string.Empty;
					this.spectrum_serial_label.Sensitive = false;
				}
				
				int average = spectra[0].AverageCount;
				inconsistent = false;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.AverageCount != average)
						inconsistent = true;
				}
				if (!inconsistent)
				{
					if (average > 0)
						this.spectrum_average_label.Text = average.ToString();
					else
						this.spectrum_average_label.Text = Catalog.GetString("n/a");
					this.spectrum_average_label.Sensitive = true;
				}
				else
				{
					this.spectrum_average_label.Text = string.Empty;
					this.spectrum_average_label.Sensitive = false;
				}
				
				this.spectrum_comment_text2.Buffer.Text = spectra[0].Comment;
				this.spectrum_comment_text2.Sensitive = false;
			
				inconsistent = false;
				Color color = spectra[0].Color;
				foreach (Spectrum spectrum in spectra)
				{
					if (spectrum.Color != color)
						inconsistent = true;
				}
				this.plot_colorbutton.Color = inconsistent ? Gdk.Color.Zero : UserInterface.GdkColor(color);
				this.plot_colorbutton.Sensitive = true;
				
				inconsistent = false;
				LineStyle style = spectra[0].LineStyle;
				this.plot_style_combo.Active = (int)style;
				this.plot_style_combo.Sensitive = true;

				inconsistent = false;
				float width = spectra[0].LineWidth;
				this.plot_width_spin.Value = width;
				this.plot_width_spin.Sensitive = true;
			}
			this.updating_properties_spectrum = false;
			this.property_spectrum_fixed.Sensitive = true;
			this.PropertiesSpectrumSetSensitive();

			this.current_spectra_config = spectra;
		}
		
		public static Gdk.Color GdkColor(Color c)
		{
			return new Gdk.Color(c.R, c.G, c.B); 
		}
		
		public static Color DrawingColor(Gdk.Color c)
		{
			return Color.FromArgb(c.Red >> 8, c.Green >> 8, c.Blue >> 8);
		}
		
		private void PropertiesSpectrumSetSensitive()
		{
		}

		internal void OnSpectrumPropertiesButtonClicked(object o, EventArgs e)
		{
			Spectrum spectrum = this.plot_tv.GetSelectedSpectra()[0];
			string msg = Catalog.GetString("<b>Spectrum Properties</b>\n\n") + 
				"<span font_family=\"monospace\">" + spectrum.ToString() + "</span>";
			QSMessageDialog dialog = new QSMessageDialog(UI.MainWindow, DialogFlags.Modal, MessageType.Info, ButtonsType.Ok, msg);
			HBox hbox = dialog.VBox.Children[0] as HBox;
			VBox vbox = hbox.Children[1] as VBox;
			Label label = vbox.Children[0] as Label;
			label.Wrap = false;
			Console.WriteLine(msg);
			dialog.Run();
			dialog.Destroy();
		}

		internal void OnSpectrumEditButtonClicked(object o, EventArgs e)
		{
			Spectrum spectrum = this.plot_tv.GetSelectedSpectra()[0];

			if (!spectrum.IsFromFile || spectrum.FileInfo == null || string.IsNullOrEmpty(spectrum.FileInfo.FullName))
			{
				this.ShowInfoMessage(UI.MainWindow, Catalog.GetString("Cannot open text editor: The spectrum must be available (saved) at a local hard drive."));
				return;
			}

			UserInterface.OpenTextEditor(UI.MainWindow, spectrum.FileInfo.FullName);
		}

		internal void OnSpectrumResolutionLimitToggled(object o, EventArgs e)
		{
			this.spectrum_resolution_limit_checkbutton.Inconsistent = false;
			this.ApplyResolutionLimit();
		}
		
		internal void OnPlotColorbuttonSet(object o, EventArgs e)
		{
			this.ApplyColor();
		}
		
		internal void OnPlotStyleComboChanged(object o, EventArgs e)
		{
			this.ApplyLineStyle();
		}
		
		internal void OnPlotWidthSpinValueChanged(object o, EventArgs e)
		{
			this.ApplyLineWidth();
		}

		internal void OnSpectrumPropertyChanged(object o, System.EventArgs e)
		{
		}
		
		private void ApplyColor()
		{
			if (this.updating_properties_spectrum)
				return;

			if (this.current_spectra_config.Count == 1)
			{
				if (this.current_spectra_config[0].Color.ToArgb() != UserInterface.DrawingColor(this.plot_colorbutton.Color).ToArgb())
					this.current_spectra_config[0].Color = UserInterface.DrawingColor(this.plot_colorbutton.Color);
			}
			else
			{
				foreach (Spectrum spectrum in this.current_spectra_config)
				{
					if (this.plot_colorbutton.Sensitive &&
					    spectrum.Color.ToArgb() != UserInterface.DrawingColor(this.plot_colorbutton.Color).ToArgb())
						spectrum.Color = UserInterface.DrawingColor(this.plot_colorbutton.Color);
				}
			}
			this.UpdatePlot(this.plot_info_list.Current);
		}
		
		private void ApplyResolutionLimit()
		{
			if (this.updating_properties_spectrum)
				return;
			
			if (this.current_spectra_config.Count == 1)
			{
				this.current_spectra_config[0].LimitBandwidth = this.spectrum_resolution_limit_checkbutton.Active;
			}
			else
			{
				foreach (Spectrum spectrum in this.current_spectra_config)
				{
					if (!this.spectrum_resolution_limit_checkbutton.Inconsistent)
						spectrum.LimitBandwidth = this.spectrum_resolution_limit_checkbutton.Active;
				}
			}
			this.UpdatePlot(this.plot_info_list.Current);
		}
		
		private void ApplyComment()
		{
			if (this.updating_properties_spectrum)
				return;
			
			if (this.current_spectra_config.Count == 1)
			{
				this.current_spectra_config[0].Comment = this.spectrum_comment_text2.Buffer.Text;
			}
			else
			{
				foreach (Spectrum spectrum in this.current_spectra_config)
				{
					if (this.plot_colorbutton.Sensitive &&
					    spectrum.Color.ToArgb() != UserInterface.DrawingColor(this.plot_colorbutton.Color).ToArgb())
						spectrum.Color = UserInterface.DrawingColor(this.plot_colorbutton.Color);
				}
			}
			this.UpdatePlot(this.plot_info_list.Current);
		}
		
		private void ApplyLineStyle()
		{
			if (this.updating_properties_spectrum)
				return;

			if (this.current_spectra_config.Count == 1)
			{
				if (this.current_spectra_config[0].LineStyle != (LineStyle)this.plot_style_combo.Active)
					this.current_spectra_config[0].LineStyle = (LineStyle)this.plot_style_combo.Active;
			}
			else
			{
				foreach (Spectrum spectrum in this.current_spectra_config)
				{
					if (this.plot_style_combo.Sensitive &&
					    spectrum.LineStyle != (LineStyle)this.plot_style_combo.Active)
						spectrum.LineStyle = (LineStyle)this.plot_style_combo.Active;
				}
			}
			this.UpdatePlot(this.plot_info_list.Current);
		}

		private void ApplyLineWidth()
		{
			if (this.updating_properties_spectrum)
				return;

			if (this.current_spectra_config.Count == 1)
			{
				if (this.current_spectra_config[0].LineWidth != (float)this.plot_width_spin.Value)
					this.current_spectra_config[0].LineWidth = (float)this.plot_width_spin.Value;
			}
			else
			{
				foreach (Spectrum spectrum in this.current_spectra_config)
				{
					if (this.plot_width_spin.Sensitive &&
					    spectrum.LineWidth != (float)this.plot_width_spin.Value)
						spectrum.LineWidth = (float)this.plot_width_spin.Value;
				}
			}
			this.UpdatePlot(this.plot_info_list.Current);
		}
		
//		internal void OnSpectrumPropertyApplyButtonClicked(object o, System.EventArgs e)
//		{
//			if (this.updating_properties_spectrum)
//				return;
//			
//			if (this.current_spectra_config.Count == 1)
//			{
//				this.current_spectra_config[0].LimitBandwidth = this.spectrum_resolution_limit_checkbutton.Active;
//				this.current_spectra_config[0].Comment = this.spectrum_comment_text2.Buffer.Text;
//				
//				if (this.current_spectra_config[0].Color.ToArgb() != UserInterface.DrawingColor(this.plot_colorbutton.Color).ToArgb())
//					this.current_spectra_config[0].Color = UserInterface.DrawingColor(this.plot_colorbutton.Color);
//					
//				if (this.current_spectra_config[0].LineStyle != (LineStyle)this.plot_style_combo.Active)
//					this.current_spectra_config[0].LineStyle = (LineStyle)this.plot_style_combo.Active;
//				
//				if (this.current_spectra_config[0].LineWidth != (float)this.plot_width_spin.Value)
//					this.current_spectra_config[0].LineWidth = (float)this.plot_width_spin.Value;
//			}
//			else
//			{
//				foreach (Spectrum spectrum in this.current_spectra_config)
//				{
//					if (!this.spectrum_resolution_limit_checkbutton.Inconsistent)
//						spectrum.LimitBandwidth = this.spectrum_resolution_limit_checkbutton.Active;
//					
//					if (this.plot_colorbutton.Sensitive &&
//					    spectrum.Color.ToArgb() != UserInterface.DrawingColor(this.plot_colorbutton.Color).ToArgb())
//						spectrum.Color = UserInterface.DrawingColor(this.plot_colorbutton.Color);
//					
//					if (this.plot_style_combo.Sensitive &&
//					    spectrum.LineStyle != (LineStyle)this.plot_style_combo.Active)
//						spectrum.LineStyle = (LineStyle)this.plot_style_combo.Active;
//					
//					if (this.plot_width_spin.Sensitive &&
//					    spectrum.LineWidth != (float)this.plot_width_spin.Value)
//						spectrum.LineWidth = (float)this.plot_width_spin.Value;
//				}
//			}
//			
//			this.spectrum_property_apply_button.Sensitive = false;
//			this.UpdatePlot(this.plot_info_list.Current);
//		}
		
		private void OnPlotTvSpectrumDoubleClicked(Spectrum spectrum)
		{
			this.PropertyType = Config.PropertyType.Spectrum;
			this.PropertyEditorVisible = true;
			
			this.SetCurrentFigure(spectrum.PlotId);
		}
		
		private void OnPlotTvFigureDoubleClicked(PlotInfo plot_info)
		{
			this.SetCurrentFigure(plot_info.UUID);
		}
		
		private void SetCurrentFigure(string uuid)
		{
			int found = -1;
			for (int ix=0; ix < this.plot_info_list.Count; ++ix)
			{
				if (uuid == this.plot_info_list[ix].UUID)
					found = ix;
			}
			
			if (found > -1)
				this.plot_notebook.CurrentPage = found;
		}
		
		private void OnPlotTvSelectionChanged(List<PlotInfo> plot_infos, List<Spectrum> spectra, bool clicked)
		{
			this.ScrolledPlot.Plot.DataSetSelections.Clear();

			if (clicked)
				this.PropertyType = Config.PropertyType.Spectrum;
			
			if (spectra.Count < 1)
				this.UpdatePropertiesSpectrum(null);
			else
				this.UpdatePropertiesSpectrum(spectra);

			bool visible = false;
			bool not_visible = false;
			bool in_current_plot = true;
			foreach (Spectrum spectrum in spectra)
			{
				try
				{
					if (spectrum.PlotId == this.plot_info_list.Current.UUID)
						this.ScrolledPlot.Plot.DataSetSelections.Add(new DataSetSelection(this.ScrolledPlot.Plot, spectrum));
					else
						in_current_plot = false;
				}
				catch (KeyNotFoundException)
				{
					// this happens if the selected spectrum cannot be displayed in the current plot type
					continue;
				}
				
				if (spectrum.IsVisible)
				{
					if (!visible && !spectrum.IsPreview)
						visible = true;
				}
				else 
				{
					not_visible = true;
				}
			}
			
			this.ScrolledPlot.Plot.AsyncRefresh(true);

			this.plot_tv_save_button.Sensitive       = visible;
			this.plot_tv_copy_button.Sensitive       = visible && in_current_plot;
			this.plot_tv_delete_button.Sensitive     = visible;
			this.plot_tv_auto_color_button.Sensitive = visible || plot_infos.Count > 0;
			this.plot_tv_remove_button.Sensitive     = visible;
			this.plot_tv_add_button.Sensitive        = not_visible;

			if (this.ScrolledPlot.Plot.DataSetSelections.Count == 0)
				this.plot_tv_auto_color_button.Sensitive = plot_infos.Count > 0;

			this.OnPlotTvSpectrumSelectionPositionChanged(spectra);
		}
		
		private void OnPlotTvSpectrumSelectionPositionChanged(List<Spectrum> spectra)
		{
			bool not_preview = spectra.Count == 1 && !spectra[0].IsPreview;
			this.plot_tv_move_up_button.Sensitive   = not_preview && !this.plot_tv.IsFirst(spectra[0]);
			this.plot_tv_move_down_button.Sensitive = not_preview && !this.plot_tv.IsLast(spectra[0]);
		}

		public static void OpenTextEditor(Window parent, string path)
		{
			System.Diagnostics.Process process = new System.Diagnostics.Process();

			process.StartInfo.CreateNoWindow = true;
			process.StartInfo.UseShellExecute = false;

			if (MainClass.OS == MainClass.OSType.Windows)
			{
				// start notepad
				process.StartInfo.Arguments = "\"" + path + "\"";
				process.StartInfo.FileName = "notepad.exe";
				
				try
				{
					process.Start();
					return;
				}
				catch {}
			}
			else
			{
				// try to start one of Linux' text editors
				process.StartInfo.Arguments = "\"" + path + "\"";
				string[] editors = new string[] {"gedit", "kwrite", "kate"};
				
				foreach (string filemanager in editors)
				{
					process.StartInfo.FileName = filemanager;
					try
					{
						process.Start();
						return;
					}
					catch {}
				}
			}

			new InfoMessage(parent, Catalog.GetString("Cannot start text editor."));
		}
	}
}
