//
//  Plugin.cs
//
// QuickStep: Acquire, view and identify spectra 
// Copyright (C) 2010-2017  Thomas Klose & Torsten Schache, 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.Reflection;

using Gtk;

using Hiperscan.SGS;
using Hiperscan.Spectroscopy.Method;
using Hiperscan.Unix;


namespace Hiperscan.Extensions.OnlineProcessing
{

    public class Plugin : Hiperscan.Extensions.IPlugin
    {
        public static readonly string name        = Catalog.GetString("Online Processing");
        public static readonly string version     = "1.0.0";
        public static readonly string vendor      = "Hiperscan GmbH";
        public static readonly string description = Catalog.GetString("Process acquired spectra online");
        public static readonly string guid        = "aeafe6c3-a2ba-4789-8770-4cef35662fe0";
        
        internal static IHost host;
        internal static SpinButton acquisition_count_spin;


        public Plugin()
        {
            MenuInfo menu_info1 = new MenuInfo(Catalog.GetString("Acquire Reflectance Spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            menu_info1.Invoked += (sender, e) =>
            {
                foreach (IDevice dev in Plugin.host.ActiveDevices.Idle)
                {
                    if (dev.IsFinder)
                        OnlineProcessing.Acquire(dev, SubstanceType.Solid, false, 1, 0);
                }
            };

            MenuInfo menu_info2 = new MenuInfo(Catalog.GetString("Acquire Transflectance Reference Spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            menu_info2.Invoked += (sender, e) =>
            {
                foreach (IDevice dev in Plugin.host.ActiveDevices.Idle)
                {
                    if (dev.IsFinder)
                        OnlineProcessing.AcquireTransflectanceReference(dev);
                }
            };

            MenuInfo menu_info3 = new MenuInfo(Catalog.GetString("Acquire Transflectance Spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            menu_info3.Invoked += (sender, e) =>
            {
                foreach (IDevice dev in Plugin.host.ActiveDevices.Idle)
                {
                    if (dev.IsFinder)
                        OnlineProcessing.Acquire(dev, SubstanceType.Fluid, false, 1, 0);
                }
            };

            MenuInfo menu_info4 = new MenuInfo(Catalog.GetString("Acquire Sample Insert Spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            menu_info4.Invoked += (sender, e) =>
            {
                foreach (IDevice dev in Plugin.host.ActiveDevices.Idle)
                {
                    if (dev.IsFinder)
                        OnlineProcessing.Acquire(dev, SubstanceType.SampleInsertOnly, false, 1, 0);
                }
            };

            MenuInfo menu_info5 = new MenuInfo(Catalog.GetString("Reset Referencing"))
            {
                WatchCursor = false,
                NeedIdleDevice = false,
                NeedSingleDevice = false
            };
            menu_info5.Invoked += (sender, e) => OnlineProcessing.Reset();

            this.MenuInfos = new MenuInfo[]
            {
                menu_info1,
                menu_info2,
                menu_info3,
                menu_info4,
                menu_info5 
            };

            Plugin.acquisition_count_spin = new SpinButton(1f, 20f, 1f)
            {
                WidthChars = 2
            };
            Alignment align = new Alignment(0.5f, 0.5f, 0f, 0f)
            {
                Plugin.acquisition_count_spin
            };
            ToolItem item = new ToolItem
            {
                align
            };
            ToolbarInfo toolbar_info0 = new ToolbarInfo(item,
                                                        Catalog.GetString("Number of measurements"),
                                                        Catalog.GetString("Specify number of spectra to acquire"))
            {
                NeedIdleDevice = true
            };


            ToolButton b = new ToolButton(new Label("O:S"), string.Empty);
            ToolbarInfo toolbar_info1 = new ToolbarInfo(b,
                                                        Catalog.GetString("O:Solid"),
                                                        Catalog.GetString("Acquire and process spectrum (solids)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            toolbar_info1.Invoked += (sender, e) =>
            {
                Plugin.acquisition_count_spin.Update();
                for (int ix = 0; ix < Plugin.acquisition_count_spin.Value; ++ix)
                {
                    foreach (IDevice dev in host.ActiveDevices.Connected)
                    {
                        if (dev.IsFinder)
                            OnlineProcessing.Acquire(dev, SubstanceType.Solid, false, (int)Plugin.acquisition_count_spin.Value, ix);
                    }
                }
            };
            
            b = new ToolButton(new Label("O:E"), string.Empty);
            ToolbarInfo toolbar_info2 = new ToolbarInfo(b,
                                                        Catalog.GetString("O:Transflectance Reference"),
                                                        Catalog.GetString("Acquire transflectance reference spectrum (fluid)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            toolbar_info2.Invoked += (sender, e) =>
            {
                foreach (IDevice dev in Plugin.host.ActiveDevices.Idle)
                {
                    if (dev.IsFinder)
                        OnlineProcessing.AcquireTransflectanceReference(dev);
                }
            };

            b = new ToolButton(new Label("O:F"), string.Empty);
            ToolbarInfo toolbar_info3 = new ToolbarInfo(b,
                                                        Catalog.GetString("O:Transflectance"),
                                                        Catalog.GetString("Acquire and process spectrum (liquids)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            toolbar_info3.Invoked += (sender, e) =>
            {
                Plugin.acquisition_count_spin.Update();
                for (int ix = 0; ix < Plugin.acquisition_count_spin.Value; ++ix)
                {
                    foreach (IDevice dev in host.ActiveDevices.Connected)
                    {
                        if (dev.IsFinder)
                            OnlineProcessing.Acquire(dev, SubstanceType.Fluid, false, (int)Plugin.acquisition_count_spin.Value, ix);
                    }
                }
            };

            b = new ToolButton(new Label("O:I"), string.Empty);
            ToolbarInfo toolbar_info4 = new ToolbarInfo(b,
                                                        Catalog.GetString("S:Sample Insert"),
                                                        Catalog.GetString("Acquire and process Sample Insert spectrum (solids with Sample Insert)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = false
            };
            toolbar_info4.Invoked += (sender, e) =>
            {
                Plugin.acquisition_count_spin.Update();
                for (int ix = 0; ix < Plugin.acquisition_count_spin.Value; ++ix)
                {
                    foreach (IDevice dev in host.ActiveDevices.Connected)
                    {
                        if (dev.IsFinder)
                            OnlineProcessing.Acquire(dev, SubstanceType.SampleInsertOnly, false, (int)Plugin.acquisition_count_spin.Value, ix);
                    }
                }
            };

            this.ToolbarInfos = new ToolbarInfo[] 
            {
                toolbar_info0,
                toolbar_info1, 
                toolbar_info2, 
                toolbar_info3,
                toolbar_info4 
            };
        }

        public void ReplaceGui()
        {
        }

        public void Initialize(IHost host)
        {
            Plugin.host = host;

            Settings.Init();
            Plugin.acquisition_count_spin.Value = Settings.Current.AcquisitionCount;
            Plugin.acquisition_count_spin.Changed += delegate(object sender, EventArgs e) {
                Settings.Current.AcquisitionCount = (int)Plugin.acquisition_count_spin.Value;
            };
        }

        public MenuInfo[]    MenuInfos    { get; }
        public ToolbarInfo[] ToolbarInfos { get; }

        public bool Active { get; set; } = true;

        public PlotTypeInfo[] PlotTypeInfos => null;
        public FileTypeInfo[] FileTypeInfos => null;
        public string Name                  => Plugin.name;
        public string Version               => Plugin.version;
        public string Vendor                => Plugin.vendor;
        public Assembly Assembly            => Assembly.GetExecutingAssembly();
        public string Description           => Plugin.description;
        public Guid Guid                    => new Guid(Plugin.guid);
        public bool CanReplaceGui           => false;
    }
}