// QueueProcessor.cs created with MonoDevelop
// User: klose at 20:29 01.02.2009
// CVS release: $Id: Queues.cs,v 1.23 2011-04-19 12:36: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;
using System.Collections.Generic;
using System.Threading;
using Gtk;

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


namespace Hiperscan.GUI
{

	public class Queues
	{
		
		public class StatusEvent
		{
			private string context;
			private string text;
			
			public StatusEvent(string context, string text)
			{
				this.context = context;
				this.text    = text;
			}

			public string Context
			{
				get { return this.context; }
			}
			
			public string Text
			{
				get { return this.text; }
			}
		}

		private SpectrumQueue spectrum_queue = new SpectrumQueue();
		
		private Queue ds_queue       = Queue.Synchronized(new Queue());
		private Queue message_queue  = Queue.Synchronized(new Queue());
		private Queue status_queue   = Queue.Synchronized(new Queue());
		
		private bool __ds_processor_running = false;
		
		private UserInterface ui;
		private Statusbar     statusbar;
		
		public event EventHandler<EventArgs> InfoMessageShown;
		
//		public delegate void PlotRefreshedHandler();
//		public event         PlotRefreshedHandler PlotRefreshed;
		
		
		public Queues(UserInterface ui)
		{
			this.ui = ui;
			this.statusbar = null;
		}
		
		public void StartProcessing()
		{
			if (this.__ds_processor_running)
				return;
			
			this.__ds_processor_running = true;	
			GLib.Timeout.Add(20, UserInterface.Queues.Process);
		}
		
		private bool Process()
		{
			try
			{
				bool need_update = false;
				
				lock (this.ui.DeviceList)
				{
					List<Device> dev_list = new List<Device>(this.ui.DeviceList.Values);
					foreach (Device dev in dev_list)
					{
						if (dev.SpectrumQueue.Count > 0)
						{
							Spectrum spectrum = null;
							while (dev.SpectrumQueue.Count > 0)
							{
								spectrum = dev.SpectrumQueue.Dequeue();
								if (spectrum == null)
									continue;
								if (spectrum.SpectrumType == SpectrumType.Single)
									break;
							}
//							dev.SpectrumQueue.TrimToSize();
							this.ui.AddSpectrum(spectrum);
							need_update = true;
						}
					}
				}
				
				if (need_update)
					this.ui.ScrolledPlot.Plot.RequestUpdate();
				
				if (this.MessageQueue.Count > 0)
				{
					string message = (string)this.MessageQueue.Dequeue();
//					this.MessageQueue.TrimToSize();
					new InfoMessageNonModal(null, message);
					if (this.InfoMessageShown != null)
						this.InfoMessageShown(message, EventArgs.Empty);
				}
				
				if (this.StatusQueue.Count > 0)
				{
					StatusEvent e = (StatusEvent)this.StatusQueue.Dequeue();
//					this.StatusQueue.TrimToSize();
					
					if (this.Statusbar != null)
					{
						uint id = this.Statusbar.GetContextId(e.Context);
						this.Statusbar.Pop(id);
						this.Statusbar.Push(id, e.Text);
						UserInterface.ProcessEvents_(Thread.CurrentThread.GetHashCode());
					}
				}

				return true;
			}
			catch (Exception ex)
			{
				throw new Exception(Catalog.GetString("Unhandled exception in Queues.Process():") +
				                    " " + ex.ToString());
			}
		}
		
		internal Statusbar Statusbar
		{
			get { return this.statusbar;  }
			set { this.statusbar = value; }
		}
		
		internal Queue DataSetQueue
		{
			get { return this.ds_queue; }
		}
		
		internal SpectrumQueue SpectrumQueue
		{
			get { return this.spectrum_queue; }
		}

		internal Queue MessageQueue
		{
			get { return this.message_queue; }
		}
		
		internal Queue StatusQueue
		{
			get { return this.status_queue; }
		}
		
		internal bool DsProcessorIsRunning
		{
			get
			{
				lock (this)
					return this.__ds_processor_running;
			}
			
			set
			{
				lock (this)
					this.__ds_processor_running = value;
			}
		}		
	}
}
