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

using Gtk;

using Hiperscan.Common;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;


namespace Hiperscan.Extensions.Acquisition
{

    public class Plugin : IPlugin
    {
        public static readonly string name        = Catalog.GetString("Acquisition");
        public static readonly string version     = "1.0.0";
        public static readonly string vendor      = "Hiperscan GmbH";
        public static readonly string description = Catalog.GetString("Perform standard measurements");
        public static readonly string guid        = "a58abc50-8da4-11df-a4ee-0800200c9a66";
        
        internal static IHost host;
        internal static SpinButton acquisition_count_spin;
        internal static Label remaining_time_label;

        internal static ToolButton button_darkref;
        internal static ToolButton button_zenith;
        internal static ToolButton button_sampleinsert;
        internal static ToolButton button_saveall;

        private static MenuInfo menu_info_solid_autoref;
        private static MenuInfo menu_info_fluid_autoref;
        private static MenuInfo menu_info_solid_sampleinsert;
        private static MenuInfo menu_info_transfl_insert;

        private static ToolbarInfo toolbar_info0;
        private static ToolbarInfo toolbar_info_acqcount;
        private static ToolbarInfo toolbar_info_autoacq_solid;
        private static ToolbarInfo toolbar_info_autoacq_fluid;
        private static ToolbarInfo toolbar_info_autoacq_sampleinsert;
        private static ToolbarInfo toolbar_info_transfl_ref;

        public static DateTime LastExtwhiteTime                      = DateTime.MinValue;
        public static DateTime LastExtemptyTime                      = DateTime.MinValue;
        public static DateTime LastZenithTime                        = DateTime.MinValue;
        public static DateTime LastSampleInsertZenithTime            = DateTime.MinValue;
        public static DateTime LastTransflectanceInsertReferenceTime = DateTime.MinValue;

        private static TimeSpan reference_time_limit;
        private static TimeSpan transflect_reference_time_limit;

        public static readonly Gdk.Pixbuf[] FinderIcons = new Gdk.Pixbuf[5];
        public static bool SampleInsertMode = false;

        
        public Plugin()
        {
            if (int.TryParse(Environment.GetEnvironmentVariable(Env.Plugin.ACQUISITION_TIME_LIMIT), out int ref_time_limit_minutes) == false)
                ref_time_limit_minutes = 20;
            Plugin.reference_time_limit = new TimeSpan(0, ref_time_limit_minutes, 0);

            if (int.TryParse(Environment.GetEnvironmentVariable(Env.Plugin.ACQUISITION_TIME_LIMIT_TRANSFLECT), out int trf_time_limit_seconds) == false)
                trf_time_limit_seconds = 1;
            Plugin.transflect_reference_time_limit = new TimeSpan(0, 0, trf_time_limit_seconds);

            Assembly assembly = Assembly.GetExecutingAssembly();
            FinderIcons[0] = new Gdk.Pixbuf(assembly, "Hiperscan.Extensions.Acquisition.Icons.finder16x16.png");
            FinderIcons[1] = new Gdk.Pixbuf(assembly, "Hiperscan.Extensions.Acquisition.Icons.finder32x32.png");
            FinderIcons[2] = new Gdk.Pixbuf(assembly, "Hiperscan.Extensions.Acquisition.Icons.finder48x48.png");
            FinderIcons[3] = new Gdk.Pixbuf(assembly, "Hiperscan.Extensions.Acquisition.Icons.finder64x64.png");
            FinderIcons[4] = new Gdk.Pixbuf(assembly, "Hiperscan.Extensions.Acquisition.Icons.finder128x128.png");

            IconSet icon_set = new IconSet();
            foreach (Gdk.Pixbuf pixbuf in Plugin.FinderIcons)
            {
                IconSource icon_source = new IconSource
                {
                    Pixbuf = pixbuf
                };
                icon_set.AddSource(icon_source);
            }
            IconFactory icon_factory = new IconFactory();
            icon_factory.Add("hiperscan.acquisition.finder", icon_set);
            icon_factory.AddDefault();

            menu_info_solid_autoref = new MenuInfo(Catalog.GetString("Solid sample (auto reference)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_solid_autoref.Invoked += (sender, e) => Handlers.OnAutoSolidClicked(Plugin.host, false);

            menu_info_fluid_autoref = new MenuInfo(Catalog.GetString("Liquid sample (auto reference)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_fluid_autoref.Invoked += (sender, e) => Handlers.OnAutoFluidClicked(Plugin.host);

            menu_info_solid_sampleinsert = new MenuInfo(Catalog.GetString("Solid sample (Sample Insert)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_solid_sampleinsert.Invoked += (sender, e) => Handlers.OnAutoSolidClicked(Plugin.host, true);

            MenuInfo menu_info_whiteref = new MenuInfo(Catalog.GetString("White Reference"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_whiteref.Invoked += (sender, e) => Handlers.OnTitanClicked(Plugin.host);

            MenuInfo menu_info_darkref = new MenuInfo(Catalog.GetString("Black Reference"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_darkref.Invoked += (sender, e) => Handlers.OnEmptyClicked(Plugin.host);

            MenuInfo menu_info_labsphere = new MenuInfo(Catalog.GetString("Labsphere"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_labsphere.Invoked += (sender, e) => Handlers.OnLabsphereClicked(Plugin.host);

            menu_info_transfl_insert = new MenuInfo(Catalog.GetString("Transflectance Insert"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_transfl_insert.Invoked += (sender, e) => Handlers.OnTransflectanceInsertClicked(Plugin.host);

            MenuInfo menu_info_zenithref = new MenuInfo(Catalog.GetString("Zenith"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_zenithref.Invoked += (sender, e) => Handlers.OnZenithClicked(Plugin.host, false);

            MenuInfo menu_info_zenith_sampleinsert = new MenuInfo(Catalog.GetString("Zenith (Sample Insert)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            menu_info_zenith_sampleinsert.Invoked += (sender, e) => Handlers.OnZenithClicked(Plugin.host, true);

            MenuInfo menu_info_reset_outpath = new MenuInfo(Catalog.GetString("Reset output path"))
            {
                WatchCursor = false,
                NeedIdleDevice = false
            };
            menu_info_reset_outpath.Invoked += (sender, e) => Handlers.OnResetReferencePathClicked(Plugin.host);

            MenuInfo menu_info_reset_extref = new MenuInfo(Catalog.GetString("Reset external reference"))
            {
                WatchCursor = false,
                NeedIdleDevice = false
            };
            menu_info_reset_extref.Invoked += (sender, e) => Plugin.ResetExternalReferences();

            MenuInfo menu_info_acquire_samples = new MenuInfo(Catalog.GetString("Acquire samples"))
            {
                WatchCursor = true,
                NeedIdleDevice = true,
                NeedSingleDevice = true
            };
            menu_info_acquire_samples.Invoked += (sender, e) => new SampleAcquisitionDialog();

            MenuInfo menu_info_settings = new MenuInfo(Catalog.GetString("Settings..."))
            {
                WatchCursor = false,
                NeedIdleDevice = false
            };
            menu_info_settings.Invoked += (sender, e) => new AcquisitionSettingsDialog();

            this.MenuInfos = new MenuInfo[]
            {
                menu_info_solid_autoref,
                menu_info_fluid_autoref,
                menu_info_solid_sampleinsert,
                menu_info_whiteref,
                menu_info_darkref, 
                menu_info_labsphere,
                menu_info_transfl_insert,
                menu_info_zenithref,
                menu_info_reset_outpath,
                menu_info_reset_extref, 
                menu_info_acquire_samples,
                menu_info_settings
            };

            Plugin.remaining_time_label = new Label(" 0 min")
            {
                WidthChars = 7
            };
            ToolItem item = new ToolItem
            {
                Plugin.remaining_time_label
            };
            toolbar_info0 = new ToolbarInfo(item,
                                            Catalog.GetString("Remaining time"),
                                            Catalog.GetString("Remaining time before external references expire"));

            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
            };
            item = new ToolItem
            {
                align
            };
            toolbar_info_acqcount = new ToolbarInfo(item,
                                                    Catalog.GetString("Number of measurements"),
                                                    Catalog.GetString("Specify number of spectra to acquire"))
            {
                NeedIdleDevice = true
            };


            item = new ToolItem();
            EventBox eb = new EventBox();
            ToolButton button_transfl_ref = new ToolButton(new Label("4:S"), string.Empty);
            eb.Add(button_transfl_ref);
            item.Add(eb);
            toolbar_info_transfl_ref = new ToolbarInfo(item,
                                                       Catalog.GetString("Transflectance Reference"),
                                                       Catalog.GetString("Acquire transflectance insert spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            button_transfl_ref.Clicked += (sender, e) => Handlers.OnTransflectanceInsertClicked(Plugin.host);


            item = new ToolItem();
            eb = new EventBox();
            button_sampleinsert = new ToolButton(new Label("2:E"), string.Empty)
            {
                Sensitive = false
            };
            eb.Add(button_sampleinsert);
            item.Add(eb);
            ToolbarInfo toolbar_info_sampleinsert = new ToolbarInfo(item,
                                                                    Catalog.GetString("Sample Insert White Reference"),
                                                                    Catalog.GetString("Acquire sample insert white reference spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            button_sampleinsert.Clicked += (sender, e) => Handlers.OnZenithClicked(Plugin.host, true);

            item = new ToolItem();
            eb = new EventBox();
            eb.ModifyBg(StateType.Normal, new Gdk.Color(100, 255, 100));
            ToolButton button_autoacq_solid = new ToolButton(Stock.Execute);
            eb.Add(button_autoacq_solid);
            item.Add(eb);
            toolbar_info_autoacq_solid = new ToolbarInfo(item,
                                                         Catalog.GetString("Auto acquisition (solids)"),
                                                         Catalog.GetString("Acquire solid sample spectrum (auto referencing)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            button_autoacq_solid.Clicked += (sender, e) => Handlers.OnAutoSolidClicked(Plugin.host, false);
            
            item = new ToolItem();
            eb = new EventBox();
            eb.ModifyBg(StateType.Normal, new Gdk.Color(100, 100, 255));
            ToolButton button_autoacq_fluid = new ToolButton(Stock.Execute);
            eb.Add(button_autoacq_fluid);
            item.Add(eb);
            toolbar_info_autoacq_fluid = new ToolbarInfo(item,
                                                         Catalog.GetString("Auto acquisition (liquids)"),
                                                         Catalog.GetString("Acquire liquid sample spectrum (auto referencing)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            button_autoacq_fluid.Clicked += (sender, e) => Handlers.OnAutoFluidClicked(Plugin.host);
            
            item = new ToolItem();
            eb = new EventBox();
            eb.ModifyBg(StateType.Normal, new Gdk.Color(0, 0, 0));
            ToolButton button_autoacq_sampleinsert = new ToolButton(Stock.Execute)
            {
                Visible = false,
                NoShowAll = true
            };
            eb.Add(button_autoacq_sampleinsert);
            item.Add(eb);
            toolbar_info_autoacq_sampleinsert = new ToolbarInfo(item,
                                                                Catalog.GetString("Auto acquisition (Sample insert)"),
                                                                Catalog.GetString("Acquire solid sample spectrum (Sample insert)"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            button_autoacq_sampleinsert.Clicked += (sender, e) => Handlers.OnAutoSolidClicked(Plugin.host, true);

            // Feature #34017
            /*
            w_button = new ToolButton(new Label("1:W"), string.Empty);
            ToolbarInfo toolbar_info3 = new ToolbarInfo(w_button,
                                                        Catalog.GetString("White Reference"),
                                                        Catalog.GetString("Acquire White Standard spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            toolbar_info3.Invoked += (sender, e) => Handlers.OnTitanClicked(Plugin.host);
            */

            button_darkref = new ToolButton(new Label("3:B"), string.Empty);
            ToolbarInfo toolbar_info_darkref = new ToolbarInfo(button_darkref,
                                                               Catalog.GetString("Black Standard"),
                                                               Catalog.GetString("Acquire Black Standard spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            toolbar_info_darkref.Invoked += (sender, e) => Handlers.OnEmptyClicked(Plugin.host);

            button_zenith = new ToolButton(new Label("1:Z"), string.Empty);
            ToolbarInfo toolbar_info_zenith = new ToolbarInfo(button_zenith,
                                                              Catalog.GetString("Zenith"),
                                                              Catalog.GetString("Acquire Zenith spectrum"))
            {
                WatchCursor = true,
                NeedIdleDevice = true
            };
            toolbar_info_zenith.Invoked += (sender, e) => Handlers.OnZenithClicked(Plugin.host, false);

            ToolButton button_startacq = new ToolButton("hiperscan.acquisition.finder");
            ToolbarInfo toolbar_info_startacq = new ToolbarInfo(button_startacq, 
                                                                Catalog.GetString("Sample Acquisition"), 
                                                                Catalog.GetString("Start Sample Acquisition"));
            ToggleToolButton button_sampleinsert_mode = new ToggleToolButton
            {
                LabelWidget = new Label("SI")
            };
            ToolbarInfo toolbar_info_sampleinsert_mode = new ToolbarInfo(button_sampleinsert_mode,
                                                        Catalog.GetString("Sample Insert Mode"),
                                                        Catalog.GetString("Switch Sample Insert Mode"))
            {
                NeedIdleDevice = false,
                NeedSingleDevice = false
            };
            toolbar_info_sampleinsert_mode.Invoked += (sender, e) =>
            {
                ToggleToolButton ttb = sender as ToggleToolButton;
                Plugin.SampleInsertMode = ttb.Active;
                Plugin.ResetExternalReferences();
                Plugin.UpdateControls();

                if (ttb.Active)
                {
                    button_transfl_ref.Sensitive = false;
                    button_sampleinsert.Sensitive = true;

                    button_autoacq_fluid.HideAll();
                    button_autoacq_fluid.NoShowAll = true;
                    button_autoacq_sampleinsert.NoShowAll = false;
                    button_autoacq_sampleinsert.ShowAll();
                }
                else
                {
                    button_sampleinsert.Sensitive = false;
                    button_transfl_ref.Sensitive = true;

                    button_autoacq_sampleinsert.HideAll();
                    button_autoacq_sampleinsert.NoShowAll = true;
                    button_autoacq_fluid.NoShowAll = false;
                    button_autoacq_fluid.ShowAll();
                }
            };

            button_saveall = new ToolButton(Stock.SaveAs);
            ToolbarInfo toolbar_info_saveall = new ToolbarInfo(button_saveall,
                                                               Catalog.GetString("Save all"),
                                                               Catalog.GetString("Save all Sample Spectra"));
            toolbar_info_saveall.Invoked += (sender, e) => Handlers.OnSaveAllClicked(Plugin.host);

            toolbar_info_startacq.NeedIdleDevice = true;
            toolbar_info_startacq.NeedSingleDevice = true;
            toolbar_info_startacq.Invoked += (sender, e) => new SampleAcquisitionDialog();

            this.ToolbarInfos = new ToolbarInfo[] 
            {
                toolbar_info0,
                toolbar_info_acqcount, 
                toolbar_info_sampleinsert_mode,
                toolbar_info_autoacq_solid,
                toolbar_info_autoacq_fluid, 
                toolbar_info_autoacq_sampleinsert, //toolbar_info3, 
                toolbar_info_zenith,
                toolbar_info_sampleinsert,
                toolbar_info_darkref, 
                toolbar_info_transfl_ref,
                toolbar_info_saveall, 
                toolbar_info_startacq
            };

            Plugin.UpdateControls();
            TestProcess.Init();
        }

        private static bool timer_is_running = false;

        public static bool UpdateControls()
        {
            TimeSpan max_span = TimeSpan.MinValue;
            DateTime now = DateTime.Now;

            Gdk.Color red = Gdk.Color.Zero;
            Gdk.Color green = Gdk.Color.Zero;
            Gdk.Color.Parse("red", ref red);
            Gdk.Color.Parse("darkgreen", ref green);

            bool need_another_update = false;
            bool valid = true;

            TimeSpan span;
            Label l;

            /*
            TimeSpan span = now - Plugin.LastExtwhiteTime;
            Label l = (Label)((Button)(Plugin.w_button.Child)).Child;
            if (span > reference_time_limit)
            {
                l.ModifyFg(StateType.Normal, red);
                valid = false;
            }
            else
            {
                l.ModifyFg(StateType.Normal, green);
                need_another_update = true;
            }
            if (span > max_span)
                max_span = span;
            */               

            span = now - Plugin.LastExtemptyTime;
            l = (Label)((Button)(Plugin.button_darkref.Child)).Child;
            if (span > reference_time_limit)
            {
                l.ModifyFg(StateType.Normal, red);
                valid = false;
            }
            else
            {
                l.ModifyFg(StateType.Normal, green);
                need_another_update = true;
            }
            if (span > max_span)
                max_span = span;

            span = now - Plugin.LastZenithTime;
            l = (Label)((Button)(Plugin.button_zenith.Child)).Child;
            if (span > reference_time_limit)
            {
                l.ModifyFg(StateType.Normal, red);
                valid = false;
            }
            else
            {
                l.ModifyFg(StateType.Normal, green);
                need_another_update = true;
            }
            if (span > max_span)
                max_span = span;

            if (Plugin.SampleInsertMode)
            {
                span = now - Plugin.LastSampleInsertZenithTime;
                l = (Label)((Button)(Plugin.button_sampleinsert.Child)).Child;
                if (span > reference_time_limit)
                {
                    l.ModifyFg(StateType.Normal, red);
                    valid = false;
                }
                else
                {
                    l.ModifyFg(StateType.Normal, green);
                    need_another_update = true;
                }
                if (span > max_span)
                    max_span = span;
            }

            Plugin.menu_info_transfl_insert.IsSensitive = valid;
            Plugin.toolbar_info_transfl_ref.IsSensitive = valid;

            bool insert_valid = false;
            if (now - Plugin.LastTransflectanceInsertReferenceTime < transflect_reference_time_limit)
            {
                insert_valid = valid; // && (now - Plugin.LastTransflectanceInsertReferenceTime < transflect_reference_time_limit);
            }
            else
            {
                insert_valid = false;
            }

            Plugin.menu_info_solid_autoref.IsSensitive           = valid && insert_valid == false;
            Plugin.toolbar_info_autoacq_solid.IsSensitive        = valid && insert_valid == false;
            Plugin.menu_info_solid_sampleinsert.IsSensitive      = valid && insert_valid == false;
            Plugin.toolbar_info_autoacq_sampleinsert.IsSensitive = valid && insert_valid == false;

            Plugin.menu_info_fluid_autoref.IsSensitive = insert_valid;
            Plugin.toolbar_info_autoacq_fluid.IsSensitive = insert_valid;

            Plugin.button_saveall.Sensitive = Plugin.host?.CurrentSpectra?.Values?.Any(s => s.SpectrumType == SpectrumType.SolidSpecimen ||
                                                                                     s.SpectrumType == SpectrumType.FluidSpecimen) ?? false;

            Plugin.remaining_time_label.Sensitive = valid;

            if (Plugin.host != null && valid == false && need_another_update == true)
                Plugin.host.UpdateDeviceControls();

            if (valid)
            {
                double total_minutes = (Plugin.reference_time_limit - max_span).TotalMinutes;
                if (total_minutes < 1.0)
                    Plugin.remaining_time_label.Text = "<1 min";
                else
                    Plugin.remaining_time_label.Text = string.Format("{0,2} min", Math.Round(total_minutes));
            }
            else
                Plugin.remaining_time_label.Text = " 0 min";

            if (Plugin.timer_is_running == false && need_another_update == true)
                GLib.Timeout.Add(10000, Plugin.UpdateControls);

            Plugin.timer_is_running = need_another_update;

            return need_another_update;
        }

        public static void ResetExternalReferences(TimeSpan span)
        {
            TimeSpan limit = Plugin.reference_time_limit - span;

            if (DateTime.Now - Plugin.LastExtwhiteTime > limit)
                Plugin.LastExtwhiteTime = DateTime.MinValue;

            if (DateTime.Now - Plugin.LastExtemptyTime > limit)
                Plugin.LastExtemptyTime = DateTime.MinValue;

            if (DateTime.Now - Plugin.LastZenithTime > limit)
                Plugin.LastZenithTime = DateTime.MinValue;

            if (DateTime.Now - Plugin.LastSampleInsertZenithTime > limit)
                Plugin.LastSampleInsertZenithTime = DateTime.MinValue;

            if (DateTime.Now - Plugin.LastTransflectanceInsertReferenceTime > limit)
                Plugin.LastTransflectanceInsertReferenceTime = DateTime.MinValue;
        }

        public static void ResetExternalReferences()
        {
            Plugin.LastExtwhiteTime           = DateTime.MinValue;
            Plugin.LastExtemptyTime           = DateTime.MinValue;
            Plugin.LastZenithTime             = DateTime.MinValue;
            Plugin.LastSampleInsertZenithTime = DateTime.MinValue;
            Plugin.LastTransflectanceInsertReferenceTime = DateTime.MinValue;
        }
        
        public void ReplaceGui()
        {
        }

        public void Initialize(IHost host)
        {
            Plugin.host = host;
            
            host.SpectrometerSelectionChanged += (sender, e) => Handlers.OnResetReferencePathClicked(host);

            host.ActiveDevices.Changed += active_devices =>
            {
                Plugin.ResetExternalReferences();
                Plugin.UpdateControls();
            };

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

        public static void InitTestProcess(bool is_solid, bool is_insert)
        {
            Plugin.TestProcess = new TestProcess();
            Plugin.TestProcess.IsFluid = is_solid == false;
            Plugin.TestProcess.IsInsert = is_insert;

            Plugin.acquisition_count_spin.Update();
            Plugin.TestProcess.NumberOfAcquisitions = (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;

        public static TestProcess TestProcess { get; set; }
    }
}