// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2022, 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.Threading.Tasks;
using Hiperscan.Common.I18n;
using Hiperscan.SGS;
using Hiperscan.Unix;
using Hiperscan.ApoIdentCore.GuiControl;
using Hiperscan.ApoIdentCore.ActionControl;
using Hiperscan.ApoIdentCore.Misc;
using Hiperscan.ApoIdentCore.Reporting.ReportData;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.IO;
using Hiperscan.GuiExtensions;
using Hiperscan.GuiExtensions.Dialog;

namespace Hiperscan.ApoIdentCore
{
    public partial class AppControl
    {
        public event ApoUpdateHandler UpdateGuiNeeded = null;
        public event ApoActionHandler ActionNeeded = null;

        public AppControl(bool windows_profile_changed, 
                          string configuration_path, 
                          bool is_release_mode,
                          DeviceList device_list,
                         int release_candidate_version)
        {
            this.IsReleaseMode = is_release_mode;

            if (this.IsReleaseMode)
                ApoIdentInfo.ReleaseCandidateVersion = release_candidate_version;

            this.MainThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
            this.Locale = CatalogLocale.GetLocaleType();
            this.WriteSpecialEnvironmentVariables();

            this.GuiSyncControl = new SyncControl();
            this.GuiActionSync = new GuiActionSync();
            this.ProgramSync = new ProcessControl();

            this.FileSystem = new ApoIdentFileSystem(windows_profile_changed, configuration_path);
            this.InitConfig(this.FileSystem.ConfigFile);

            this.InitGlobalStates();

            this.InitPharmacyManager();
            this.InitSubstanceManagement();
            this.InitSpecimenManager();
            this.InitMeasuringManager(device_list);
            this.InitResultManager();
            this.InitProtocolManager();
            this.InitDocumentManager();

        }

        private void InitConfig(string config_dir_file)
        {
            this.Config = new Configurations(config_dir_file);
            this.Config.ConnectionSettingsChanged += this.OnConnectionSettingsChanged;
            this.Config.ProfilesChanged += this.OnProfilesChanged;
            this.Config.ProfileSettingsChanged += this.OnProfileSettingsChanged;
        }

        public void RunFirstConnection()
        {
            Task.Run(() =>
            {
                try
                {
                    this.ProgramSync.EnterCriticialZone();
                    ReportInfo.ConvertToMetaData2_0(this);

                    this.Connect();

                    UpdateArgs arg = new UpdateArgs();
                    arg.DialogArgs.ApoDialogType = ApoDialogType.ImportantCustomerAdvice;
                    this.UpdateGuiNeeded?.Invoke(arg);

                    this.PharmacyManager.CheckSettings();
                }
                catch (Exception ex)
                {
                    UpdateArgs arg = UpdateArgs.GetReloadAllArg();
                    arg.CursorState = CursorState.Normal;
                    arg.DialogArgs.StandardDialogType = StandardDialogType.ErrorWithServiceMessage;
                    arg.DialogArgs.Message = String.Format(Catalog.GetString("Error initialising Apo-Ident: {0}"), ex.Message);
                    arg.DialogArgs.Exception = ex;
                    this.UpdateGuiNeeded?.Invoke(arg);
                }
                finally
                {
                    this.ProgramSync.LeaveCriticalZone();
                }
            });
        }

        private void WriteSpecialEnvironmentVariables()
        {
            string path_env = "PATH=" + Environment.GetEnvironmentVariable("PATH");
            string mono_env = "MONO_PATH=" + Environment.GetEnvironmentVariable("MONO_PATH");
            string mono_config = "MONO_CFG_DIR=" + Environment.GetEnvironmentVariable("MONO_CFG_DIR");
            string lang = "LANG=" + Environment.GetEnvironmentVariable("LANG");

            Console.WriteLine("Apo-Ident-Version: {0}", ApoIdentInfo.FullVersion);
            Console.WriteLine(path_env);
            Console.WriteLine(mono_env);
            Console.WriteLine(mono_config);
            Console.WriteLine(lang);
        }

        public int MainThreadId { get; private set; }
        public CatalogLocale.LocaleType Locale { get; set; }
        public ApoIdentFileSystem FileSystem { get; private set; }

        public ProcessControl ProgramSync { get; private set; }
        public SyncControl GuiSyncControl { get; private set; }
        public GuiActionSync GuiActionSync { get; private set; }
    }
}
