// 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.Linq;

using Gtk;

using Hiperscan.QuickStep.Dialog;
using Hiperscan.SGS;
using Hiperscan.SGS.Common;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;


namespace Hiperscan.QuickStep
{

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

            public string Context { get; }
            public string Text    { get; }
        }

        private bool __ds_processor_running = false;
        private readonly UserInterface ui;

        public event EventHandler<EventArgs> InfoMessageShown;
        

        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)
                {
                    foreach (IDevice dev in this.ui.DeviceList.Values)
                    {
                        if (dev.SpectrumQueue.Count <= 0)
                            continue;

                        Spectrum spectrum = null;

                        while (dev.SpectrumQueue.Count > 0)
                        {
                            spectrum = dev.SpectrumQueue.Dequeue();
                            if (spectrum == null)
                                continue;
                            if (spectrum.SpectrumType == SpectrumType.Single)
                                break;
                        }

                        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();
                    if (UserInterface.Instance.DontShowInfoMessage == false)
                    {
                        var d = new InfoMessageDialogNonModal(null, message);
                    }
                    else
                    {
                        Console.WriteLine("InfoMessageDialogNonModal:\n{0}", message);
                    }

                    this.InfoMessageShown?.Invoke(message, EventArgs.Empty);
                }

                if (this.StatusQueue.Count > 0)
                {
                    StatusEvent e = (StatusEvent)this.StatusQueue.Dequeue();

                    if (this.Statusbar != null)
                    {
                        uint id = this.Statusbar.GetContextId(e.Context);
                        this.Statusbar.Pop(id);
                        this.Statusbar.Push(id, e.Text);
                        UserInterface.Instance.ProcessEvents();
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                throw new Exception(Catalog.GetString("Unhandled exception in Queues.Process():") +
                                    " " +
                                    ex.ToString());
            }
        }

        internal bool DsProcessorIsRunning
        {
            get
            {
                lock (this)
                    return this.__ds_processor_running;
            }
            
            set
            {
                lock (this)
                    this.__ds_processor_running = value;
            }
        }

        internal Statusbar Statusbar         { get; set; }
        internal Queue DataSetQueue          { get; } = Queue.Synchronized(new Queue());
        internal SpectrumQueue SpectrumQueue { get; } = new SpectrumQueue();
        internal Queue MessageQueue          { get; } = Queue.Synchronized(new Queue());
        internal Queue StatusQueue           { get; } = Queue.Synchronized(new Queue());
    }
}