/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Apache.Ignite.Core 
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime;
    using System.Threading;
    using Apache.Ignite.Core.Binary;
    using Apache.Ignite.Core.Cache.Affinity;
    using Apache.Ignite.Core.Client;
    using Apache.Ignite.Core.Common;
    using Apache.Ignite.Core.Impl;
    using Apache.Ignite.Core.Impl.Binary;
    using Apache.Ignite.Core.Impl.Binary.IO;
    using Apache.Ignite.Core.Impl.Cache.Affinity;
    using Apache.Ignite.Core.Impl.Client;
    using Apache.Ignite.Core.Impl.Common;
    using Apache.Ignite.Core.Impl.Handle;
    using Apache.Ignite.Core.Impl.Log;
    using Apache.Ignite.Core.Impl.Memory;
    using Apache.Ignite.Core.Impl.Unmanaged;
    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
    using Apache.Ignite.Core.Lifecycle;
    using Apache.Ignite.Core.Log;
    using Apache.Ignite.Core.Resource;
    using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
    using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;

    /// <summary>
    /// This class defines a factory for the main Ignite API.
    /// <p/>
    /// Use <see cref="Start()"/> method to start Ignite with default configuration.
    /// <para/>
    /// All members are thread-safe and may be used concurrently from multiple threads.
    /// </summary>
    public static class Ignition
    {
        /// <summary>
        /// Default configuration section name.
        /// </summary>
        public const string ConfigurationSectionName = "igniteConfiguration";

        /// <summary>
        /// Default configuration section name.
        /// </summary>
        public const string ClientConfigurationSectionName = "igniteClientConfiguration";

        /// <summary>
        /// Environment variable name to enable alternate stack checks on .NET Core 3+ and .NET 5+.
        /// This is required to fix "Stack smashing detected" errors that occur instead of NullReferenceException
        /// on Linux and macOS when Java overwrites SIGSEGV handler installed by .NET in thick client or server mode.
        /// </summary>
        private const string EnvEnableAlternateStackCheck = "COMPlus_EnableAlternateStackCheck";

        /** */
        private static readonly object SyncRoot = new object();

        /** GC warning flag. */
        private static int _diagPrinted;

        /** */
        private static readonly IDictionary<NodeKey, Ignite> Nodes = new Dictionary<NodeKey, Ignite>();
        
        /** Current DLL name. */
        private static readonly string IgniteDllName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);

        /** Startup info. */
        [ThreadStatic]
        private static Startup _startup;

        /** Client mode flag. */
        [ThreadStatic]
        private static bool _clientMode;

        /// <summary>
        /// Static initializer.
        /// </summary>
        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
        static Ignition()
        {
            AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
        }

        /// <summary>
        /// Gets or sets a value indicating whether Ignite should be started in client mode.
        /// Client nodes cannot hold data in caches.
        /// </summary>
        public static bool ClientMode
        {
            get { return _clientMode; }
            set { _clientMode = value; }
        }

        /// <summary>
        /// Starts Ignite with default configuration. By default this method will
        /// use Ignite configuration defined in <c>{IGNITE_HOME}/config/default-config.xml</c>
        /// configuration file. If such file is not found, then all system defaults will be used.
        /// </summary>
        /// <returns>Started Ignite.</returns>
        public static IIgnite Start()
        {
            return Start(new IgniteConfiguration());
        }

        /// <summary>
        /// Starts all grids specified within given Spring XML configuration file. If Ignite with given name
        /// is already started, then exception is thrown. In this case all instances that may
        /// have been started so far will be stopped too.
        /// </summary>
        /// <param name="springCfgPath">Spring XML configuration file path or URL. Note, that the path can be
        /// absolute or relative to IGNITE_HOME.</param>
        /// <returns>Started Ignite. If Spring configuration contains multiple Ignite instances, then the 1st
        /// found instance is returned.</returns>
        public static IIgnite Start(string springCfgPath)
        {
            return Start(new IgniteConfiguration {SpringConfigUrl = springCfgPath});
        }

        /// <summary>
        /// Reads <see cref="IgniteConfiguration"/> from application configuration
        /// <see cref="IgniteConfigurationSection"/> with <see cref="ConfigurationSectionName"/>
        /// name and starts Ignite.
        /// </summary>
        /// <returns>Started Ignite.</returns>
        public static IIgnite StartFromApplicationConfiguration()
        {
            // ReSharper disable once IntroduceOptionalParameters.Global
            return StartFromApplicationConfiguration(ConfigurationSectionName);
        }

        /// <summary>
        /// Reads <see cref="IgniteConfiguration"/> from application configuration 
        /// <see cref="IgniteConfigurationSection"/> with specified name and starts Ignite.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <returns>Started Ignite.</returns>
        public static IIgnite StartFromApplicationConfiguration(string sectionName)
        {
            IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");

            var section = ConfigurationManager.GetSection(sectionName) as IgniteConfigurationSection;

            if (section == null)
                throw new ConfigurationErrorsException(string.Format("Could not find {0} with name '{1}'",
                    typeof(IgniteConfigurationSection).Name, sectionName));

            if (section.IgniteConfiguration == null)
                throw new ConfigurationErrorsException(
                    string.Format("{0} with name '{1}' is defined in <configSections>, " +
                                  "but not present in configuration.",
                        typeof(IgniteConfigurationSection).Name, sectionName));

            return Start(section.IgniteConfiguration);
        }

        /// <summary>
        /// Reads <see cref="IgniteConfiguration" /> from application configuration
        /// <see cref="IgniteConfigurationSection" /> with specified name and starts Ignite.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <param name="configPath">Path to the configuration file.</param>
        /// <returns>Started Ignite.</returns>
        public static IIgnite StartFromApplicationConfiguration(string sectionName, string configPath)
        {
            var section = GetConfigurationSection<IgniteConfigurationSection>(sectionName, configPath);

            if (section.IgniteConfiguration == null)
            {
                throw new ConfigurationErrorsException(
                    string.Format("{0} with name '{1}' in file '{2}' is defined in <configSections>, " +
                                  "but not present in configuration.",
                        typeof(IgniteConfigurationSection).Name, sectionName, configPath));
            }

            return Start(section.IgniteConfiguration);
        }

        /// <summary>
        /// Gets the configuration section.
        /// </summary>
        private static T GetConfigurationSection<T>(string sectionName, string configPath)
            where T : class
        {
            IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");
            IgniteArgumentCheck.NotNullOrEmpty(configPath, "configPath");

            var fileMap = GetConfigMap(configPath);
            var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            var section = config.GetSection(sectionName) as T;

            if (section == null)
            {
                throw new ConfigurationErrorsException(
                    string.Format("Could not find {0} with name '{1}' in file '{2}'",
                        typeof(T).Name, sectionName, configPath));
            }

            return section;
        }

        /// <summary>
        /// Gets the configuration file map.
        /// </summary>
        private static ExeConfigurationFileMap GetConfigMap(string fileName)
        {
            var fullFileName = Path.GetFullPath(fileName);

            if (!File.Exists(fullFileName))
                throw new ConfigurationErrorsException("Specified config file does not exist: " + fileName);

            return new ExeConfigurationFileMap { ExeConfigFilename = fullFileName };
        }

        /// <summary>
        /// Starts Ignite with given configuration.
        /// </summary>
        /// <returns>Started Ignite.</returns>
        public static IIgnite Start(IgniteConfiguration cfg)
        {
            IgniteArgumentCheck.NotNull(cfg, "cfg");

            cfg = new IgniteConfiguration(cfg);  // Create a copy so that config can be modified and reused.

            lock (SyncRoot)
            {
                // 0. Init logger
                var log = cfg.Logger ?? new JavaLogger();

                log.Debug("Starting Ignite.NET " + Assembly.GetExecutingAssembly().GetName().Version);

                // 1. Log diagnostics.
                LogDiagnosticMessages(cfg, log);

                // 2. Create context.
                JvmDll.Load(cfg.JvmDllPath, log);

                var cbs = IgniteManager.CreateJvmContext(cfg, log);
                var env = cbs.Jvm.AttachCurrentThread();
                log.Debug("JVM started.");

                var gridName = cfg.IgniteInstanceName;

                if (cfg.AutoGenerateIgniteInstanceName)
                {
                    gridName = (gridName ?? "ignite-instance-") + Guid.NewGuid();
                }

                // 3. Create startup object which will guide us through the rest of the process.
                _startup = new Startup(cfg, cbs);

                PlatformJniTarget interopProc = null;

                try
                {
                    // 4. Initiate Ignite start.
                    UU.IgnitionStart(env, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null, cbs.IgniteId,
                        cfg.RedirectJavaConsoleOutput);

                    // 5. At this point start routine is finished. We expect STARTUP object to have all necessary data.
                    var node = _startup.Ignite;
                    interopProc = (PlatformJniTarget)node.InteropProcessor;

                    var javaLogger = log as JavaLogger;
                    if (javaLogger != null)
                    {
                        javaLogger.SetIgnite(node);
                    }

                    // 6. On-start callback (notify lifecycle components).
                    node.OnStart();

                    Nodes[new NodeKey(_startup.Name)] = node;

                    return node;
                }
                catch (Exception ex)
                {
                    // 1. Perform keys cleanup.
                    string name = _startup.Name;

                    if (name != null)
                    {
                        NodeKey key = new NodeKey(name);

                        if (Nodes.ContainsKey(key))
                            Nodes.Remove(key);
                    }

                    // 2. Stop Ignite node if it was started.
                    if (interopProc != null)
                        UU.IgnitionStop(gridName, true);

                    // 3. Throw error further (use startup error if exists because it is more precise).
                    if (_startup.Error != null)
                    {
                        // Wrap in a new exception to preserve original stack trace.
                        throw new IgniteException("Failed to start Ignite.NET, check inner exception for details",
                            _startup.Error);
                    }

                    var jex = ex as JavaException;

                    if (jex == null)
                    {
                        throw;
                    }

                    throw ExceptionUtils.GetException(null, jex);
                }
                finally
                {
                    var ignite = _startup.Ignite;

                    _startup = null;

                    if (ignite != null)
                    {
                        ignite.ProcessorReleaseStart();
                    }
                }
            }
        }

        /// <summary>
        /// Performs system checks and logs diagnostic messages.
        /// </summary>
        /// <param name="cfg">Configuration.</param>
        /// <param name="log">Log.</param>
        private static void LogDiagnosticMessages(IgniteConfiguration cfg, ILogger log)
        {
            if (!cfg.SuppressWarnings &&
                Interlocked.CompareExchange(ref _diagPrinted, 1, 0) == 0)
            {
                if (!GCSettings.IsServerGC)
                {
                    log.Warn("GC server mode is not enabled, this could lead to less " +
                             "than optimal performance on multi-core machines (to enable see " +
                             "https://docs.microsoft.com/en-us/dotnet/core/run-time-config/garbage-collector).");
                }

                if ((Os.IsLinux || Os.IsMacOs) &&
                    Environment.GetEnvironmentVariable(EnvEnableAlternateStackCheck) != "1")
                {
                    log.Warn("Alternate stack check is not enabled, this will cause 'Stack smashing detected' " +
                             "error when NullReferenceException occurs on .NET Core on Linux and macOS. " +
                             "To enable alternate stack check on .NET Core 3+ and .NET 5+, " +
                             "set {0} environment variable to 1.", EnvEnableAlternateStackCheck);
                }
            }
        }

        /// <summary>
        /// Prepare callback invoked from Java.
        /// </summary>
        /// <param name="inStream">Input stream with data.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="handleRegistry">Handle registry.</param>
        /// <param name="log">Log.</param>
        internal static void OnPrepare(PlatformMemoryStream inStream, PlatformMemoryStream outStream,
            HandleRegistry handleRegistry, ILogger log)
        {
            try
            {
                BinaryReader reader = BinaryUtils.Marshaller.StartUnmarshal(inStream);

                PrepareConfiguration(reader, outStream, log);

                PrepareLifecycleHandlers(reader, outStream, handleRegistry);

                PrepareAffinityFunctions(reader, outStream);

                outStream.SynchronizeOutput();
            }
            catch (Exception e)
            {
                _startup.Error = e;

                throw;
            }
        }

        /// <summary>
        /// Prepare configuration.
        /// </summary>
        /// <param name="reader">Reader.</param>
        /// <param name="outStream">Response stream.</param>
        /// <param name="log">Log.</param>
        private static void PrepareConfiguration(BinaryReader reader, PlatformMemoryStream outStream, ILogger log)
        {
            // 1. Load assemblies.
            IgniteConfiguration cfg = _startup.Configuration;

            LoadAllAssemblies(cfg.Assemblies);

            ICollection<string> cfgAssembllies;
            BinaryConfiguration binaryCfg;

            BinaryUtils.ReadConfiguration(reader, out cfgAssembllies, out binaryCfg);

            LoadAllAssemblies(cfgAssembllies);

            // 2. Create marshaller only after assemblies are loaded.
            if (cfg.BinaryConfiguration == null)
                cfg.BinaryConfiguration = binaryCfg;

            _startup.Marshaller = new Marshaller(cfg.BinaryConfiguration, log);

            // 3. Send configuration details to Java
            cfg.Validate(log);
            // Use system marshaller.
            cfg.Write(BinaryUtils.Marshaller.StartMarshal(outStream));
        }

        /// <summary>
        /// Prepare lifecycle handlers.
        /// </summary>
        /// <param name="reader">Reader.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="handleRegistry">Handle registry.</param>
        private static void PrepareLifecycleHandlers(IBinaryRawReader reader, IBinaryStream outStream,
            HandleRegistry handleRegistry)
        {
            IList<LifecycleHandlerHolder> beans = new List<LifecycleHandlerHolder>
            {
                new LifecycleHandlerHolder(new InternalLifecycleHandler())   // add internal bean for events
            };

            // 1. Read beans defined in Java.
            int cnt = reader.ReadInt();

            for (int i = 0; i < cnt; i++)
                beans.Add(new LifecycleHandlerHolder(CreateObject<ILifecycleHandler>(reader)));

            // 2. Append beans defined in local configuration.
            ICollection<ILifecycleHandler> nativeBeans = _startup.Configuration.LifecycleHandlers;

            if (nativeBeans != null)
            {
                foreach (ILifecycleHandler nativeBean in nativeBeans)
                    beans.Add(new LifecycleHandlerHolder(nativeBean));
            }

            // 3. Write bean pointers to Java stream.
            outStream.WriteInt(beans.Count);

            foreach (LifecycleHandlerHolder bean in beans)
                outStream.WriteLong(handleRegistry.AllocateCritical(bean));

            // 4. Set beans to STARTUP object.
            _startup.LifecycleHandlers = beans;
        }

        /// <summary>
        /// Prepares the affinity functions.
        /// </summary>
        private static void PrepareAffinityFunctions(BinaryReader reader, PlatformMemoryStream outStream)
        {
            var cnt = reader.ReadInt();

            var writer = reader.Marshaller.StartMarshal(outStream);

            for (var i = 0; i < cnt; i++)
            {
                var objHolder = new ObjectInfoHolder(reader);
                AffinityFunctionSerializer.Write(writer, objHolder.CreateInstance<IAffinityFunction>(), objHolder);
            }
        }

        /// <summary>
        /// Creates an object and sets the properties.
        /// </summary>
        /// <param name="reader">Reader.</param>
        /// <returns>Resulting object.</returns>
        private static T CreateObject<T>(IBinaryRawReader reader)
        {
            return IgniteUtils.CreateInstance<T>(reader.ReadString(),
                reader.ReadDictionaryAsGeneric<string, object>());
        }

        /// <summary>
        /// Kernal start callback.
        /// </summary>
        /// <param name="interopProc">Interop processor.</param>
        /// <param name="stream">Stream.</param>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
            Justification = "PlatformJniTarget is passed further")]
        internal static void OnStart(GlobalRef interopProc, IBinaryStream stream)
        {
            try
            {
                // 1. Read data and leave critical state ASAP.
                BinaryReader reader = BinaryUtils.Marshaller.StartUnmarshal(stream);
                
                // ReSharper disable once PossibleInvalidOperationException
                var name = reader.ReadString();
                
                // 2. Set ID and name so that Start() method can use them later.
                _startup.Name = name;

                if (Nodes.ContainsKey(new NodeKey(name)))
                    throw new IgniteException("Ignite with the same name already started: " + name);

                _startup.Ignite = new Ignite(_startup.Configuration, _startup.Name,
                    new PlatformJniTarget(interopProc, _startup.Marshaller), _startup.Marshaller,
                    _startup.LifecycleHandlers, _startup.Callbacks);
            }
            catch (Exception e)
            {
                // 5. Preserve exception to throw it later in the "Start" method and throw it further
                //    to abort startup in Java.
                _startup.Error = e;

                throw;
            }
        }

        /// <summary>
        /// Load assemblies.
        /// </summary>
        /// <param name="assemblies">Assemblies.</param>
        private static void LoadAllAssemblies(IEnumerable<string> assemblies)
        {
            if (assemblies != null)
            {
                foreach (var s in assemblies)
                {
                    LoadAssembly(s);
                }
            }
        }

        /// <summary>
        /// Load assembly from file, directory, or full name.
        /// </summary>
        /// <param name="asm">Assembly file, directory, or full name.</param>
        internal static void LoadAssembly(string asm)
        {
            // 1. Try loading as directory.
            if (Directory.Exists(asm))
            {
                string[] files = Directory.GetFiles(asm, "*.dll");

                foreach (string dllPath in files)
                {
                    if (!SelfAssembly(dllPath))
                    {
                        try
                        {
                            Assembly.LoadFile(dllPath);
                        }

                        catch (BadImageFormatException)
                        {
                            // No-op.
                        }
                    }
                }

                return;
            }

            // 2. Try loading using full-name.
            try
            {
                Assembly assembly = Assembly.Load(asm);

                if (assembly != null)
                    return;
            }
            catch (Exception e)
            {
                if (!(e is FileNotFoundException || e is FileLoadException))
                    throw new IgniteException("Failed to load assembly: " + asm, e);
            }

            // 3. Try loading using file path.
            try
            {
                Assembly assembly = Assembly.LoadFrom(asm);

                // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                if (assembly != null)
                    return;
            }
            catch (Exception e)
            {
                if (!(e is FileNotFoundException || e is FileLoadException))
                    throw new IgniteException("Failed to load assembly: " + asm, e);
            }

            // 4. Not found, exception.
            throw new IgniteException("Failed to load assembly: " + asm);
        }

        /// <summary>
        /// Whether assembly points to Ignite binary.
        /// </summary>
        /// <param name="assembly">Assembly to check..</param>
        /// <returns><c>True</c> if this is one of GG assemblies.</returns>
        private static bool SelfAssembly(string assembly)
        {
            return assembly.EndsWith(IgniteDllName, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// Gets a named Ignite instance. If Ignite name is <c>null</c> or empty string,
        /// then default no-name Ignite will be returned. Note that caller of this method
        /// should not assume that it will return the same instance every time.
        /// <p />
        /// Note that single process can run multiple Ignite instances and every Ignite instance (and its
        /// node) can belong to a different grid. Ignite name defines what grid a particular Ignite
        /// instance (and correspondingly its node) belongs to.
        /// </summary>
        /// <param name="name">Ignite name to which requested Ignite instance belongs. If <c>null</c>,
        /// then Ignite instance belonging to a default no-name Ignite will be returned.</param>
        /// <returns>
        /// An instance of named grid.
        /// </returns>
        /// <exception cref="IgniteException">When there is no Ignite instance with specified name.</exception>
        public static IIgnite GetIgnite(string name)
        {
            var ignite = TryGetIgnite(name);

            if (ignite == null)
                throw new IgniteException("Ignite instance was not properly started or was already stopped: " + name);

            return ignite;
        }

        /// <summary>
        /// Gets the default Ignite instance with null name, or an instance with any name when there is only one.
        /// <para />
        /// Note that caller of this method should not assume that it will return the same instance every time.
        /// </summary>
        /// <returns>Default Ignite instance.</returns>
        /// <exception cref="IgniteException">When there is no matching Ignite instance.</exception>
        public static IIgnite GetIgnite()
        {
            lock (SyncRoot)
            {
                if (Nodes.Count == 0)
                {
                    throw new IgniteException("Failed to get default Ignite instance: " +
                                              "there are no instances started.");
                }

                if (Nodes.Count == 1)
                {
                    return Nodes.Single().Value;
                }

                Ignite result;

                if (Nodes.TryGetValue(new NodeKey(null), out result))
                {
                    return result;
                }

                throw new IgniteException(string.Format("Failed to get default Ignite instance: " +
                    "there are {0} instances started, and none of them has null name.", Nodes.Count));
            }
        }

        /// <summary>
        /// Gets all started Ignite instances.
        /// </summary>
        /// <returns>All Ignite instances.</returns>
        public static ICollection<IIgnite> GetAll()
        {
            lock (SyncRoot)
            {
                return Nodes.Values.ToArray();
            }
        }

        /// <summary>
        /// Gets a named Ignite instance, or <c>null</c> if none found. If Ignite name is <c>null</c> or empty string,
        /// then default no-name Ignite will be returned. Note that caller of this method
        /// should not assume that it will return the same instance every time.
        /// <p/>
        /// Note that single process can run multiple Ignite instances and every Ignite instance (and its
        /// node) can belong to a different grid. Ignite name defines what grid a particular Ignite
        /// instance (and correspondingly its node) belongs to.
        /// </summary>
        /// <param name="name">Ignite name to which requested Ignite instance belongs. If <c>null</c>,
        /// then Ignite instance belonging to a default no-name Ignite will be returned.
        /// </param>
        /// <returns>An instance of named grid, or null.</returns>
        public static IIgnite TryGetIgnite(string name)
        {
            lock (SyncRoot)
            {
                Ignite result;

                return !Nodes.TryGetValue(new NodeKey(name), out result) ? null : result;
            }
        }

        /// <summary>
        /// Gets the default Ignite instance with null name, or an instance with any name when there is only one.
        /// Returns null when there are no Ignite instances started, or when there are more than one,
        /// and none of them has null name.
        /// </summary>
        /// <returns>An instance of default no-name grid, or null.</returns>
        public static IIgnite TryGetIgnite()
        {
            lock (SyncRoot)
            {
                if (Nodes.Count == 1)
                {
                    return Nodes.Single().Value;
                }

                return TryGetIgnite(null);
            }
        }

        /// <summary>
        /// Stops named grid. If <c>cancel</c> flag is set to <c>true</c> then
        /// all jobs currently executing on local node will be interrupted. If
        /// grid name is <c>null</c>, then default no-name Ignite will be stopped.
        /// </summary>
        /// <param name="name">Grid name. If <c>null</c>, then default no-name Ignite will be stopped.</param>
        /// <param name="cancel">If <c>true</c> then all jobs currently executing will be cancelled
        /// by calling <c>ComputeJob.cancel</c>method.</param>
        /// <returns><c>true</c> if named Ignite instance was indeed found and stopped, <c>false</c>
        /// othwerwise (the instance with given <c>name</c> was not found).</returns>
        public static bool Stop(string name, bool cancel)
        {
            lock (SyncRoot)
            {
                NodeKey key = new NodeKey(name);

                Ignite node;

                if (!Nodes.TryGetValue(key, out node))
                    return false;

                node.Stop(cancel);

                Nodes.Remove(key);
                
                GC.Collect();

                return true;
            }
        }

        /// <summary>
        /// Stops <b>all</b> started grids. If <c>cancel</c> flag is set to <c>true</c> then
        /// all jobs currently executing on local node will be interrupted.
        /// </summary>
        /// <param name="cancel">If <c>true</c> then all jobs currently executing will be cancelled
        /// by calling <c>ComputeJob.Cancel()</c> method.</param>
        public static void StopAll(bool cancel)
        {
            lock (SyncRoot)
            {
                while (Nodes.Count > 0)
                {
                    var entry = Nodes.First();
                    
                    entry.Value.Stop(cancel);

                    Nodes.Remove(entry.Key);
                }
            }

            GC.Collect();
        }

        /// <summary>
        /// Connects Ignite lightweight (thin) client to an Ignite node.
        /// <para />
        /// Thin client connects to an existing Ignite node with a socket and does not start JVM in process.
        /// </summary>
        /// <param name="clientConfiguration">The client configuration.</param>
        /// <returns>Ignite client instance.</returns>
        public static IIgniteClient StartClient(IgniteClientConfiguration clientConfiguration)
        {
            IgniteArgumentCheck.NotNull(clientConfiguration, "clientConfiguration");

            return new IgniteClient(clientConfiguration);
        }

        /// <summary>
        /// Reads <see cref="IgniteClientConfiguration"/> from application configuration
        /// <see cref="IgniteClientConfigurationSection"/> with <see cref="ClientConfigurationSectionName"/>
        /// name and connects Ignite lightweight (thin) client to an Ignite node.
        /// <para />
        /// Thin client connects to an existing Ignite node with a socket and does not start JVM in process.
        /// </summary>
        /// <returns>Ignite client instance.</returns>
        public static IIgniteClient StartClient()
        {
            // ReSharper disable once IntroduceOptionalParameters.Global
            return StartClient(ClientConfigurationSectionName);
        }

        /// <summary>
        /// Reads <see cref="IgniteClientConfiguration" /> from application configuration
        /// <see cref="IgniteClientConfigurationSection" /> with specified name and connects
        /// Ignite lightweight (thin) client to an Ignite node.
        /// <para />
        /// Thin client connects to an existing Ignite node with a socket and does not start JVM in process.
        /// </summary>
        /// <param name="sectionName">Name of the configuration section.</param>
        /// <returns>Ignite client instance.</returns>
        public static IIgniteClient StartClient(string sectionName)
        {
            IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");

            var section = ConfigurationManager.GetSection(sectionName) as IgniteClientConfigurationSection;

            if (section == null)
            {
                throw new ConfigurationErrorsException(string.Format("Could not find {0} with name '{1}'.",
                    typeof(IgniteClientConfigurationSection).Name, sectionName));
            }

            if (section.IgniteClientConfiguration == null)
            {
                throw new ConfigurationErrorsException(
                    string.Format("{0} with name '{1}' is defined in <configSections>, " +
                                  "but not present in configuration.",
                        typeof(IgniteClientConfigurationSection).Name, sectionName));
            }

            return StartClient(section.IgniteClientConfiguration);
        }

        /// <summary>
        /// Reads <see cref="IgniteConfiguration" /> from application configuration
        /// <see cref="IgniteConfigurationSection" /> with specified name and starts Ignite.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <param name="configPath">Path to the configuration file.</param>
        /// <returns>Started Ignite.</returns>
        public static IIgniteClient StartClient(string sectionName, string configPath)
        {
            var section = GetConfigurationSection<IgniteClientConfigurationSection>(sectionName, configPath);

            if (section.IgniteClientConfiguration == null)
            {
                throw new ConfigurationErrorsException(
                    string.Format("{0} with name '{1}' in file '{2}' is defined in <configSections>, " +
                                  "but not present in configuration.",
                        typeof(IgniteClientConfigurationSection).Name, sectionName, configPath));
            }

            return StartClient(section.IgniteClientConfiguration);
        }

        /// <summary>
        /// Handles the DomainUnload event of the CurrentDomain control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
        {
            // If we don't stop Ignite.NET on domain unload,
            // we end up with broken instances in Java (invalid callbacks, etc).
            // IIS, in particular, is known to unload and reload domains within the same process.
            StopAll(true);
        }

        /// <summary>
        /// Grid key. Workaround for non-null key requirement in Dictionary.
        /// </summary>
        private class NodeKey
        {
            /** */
            private readonly string _name;

            /// <summary>
            /// Initializes a new instance of the <see cref="NodeKey"/> class.
            /// </summary>
            /// <param name="name">The name.</param>
            internal NodeKey(string name)
            {
                _name = name;
            }

            /** <inheritdoc /> */
            public override bool Equals(object obj)
            {
                var other = obj as NodeKey;

                return other != null && Equals(_name, other._name);
            }

            /** <inheritdoc /> */
            [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "Not available on .NET FW")]
            public override int GetHashCode()
            {
                return _name == null ? 0 : _name.GetHashCode();
            }
        }

        /// <summary>
        /// Value object to pass data between .NET methods during startup bypassing Java.
        /// </summary>
        private class Startup
        {
            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="cfg">Configuration.</param>
            /// <param name="cbs"></param>
            internal Startup(IgniteConfiguration cfg, UnmanagedCallbacks cbs)
            {
                Configuration = cfg;
                Callbacks = cbs;
            }
            /// <summary>
            /// Configuration.
            /// </summary>
            internal IgniteConfiguration Configuration { get; private set; }

            /// <summary>
            /// Gets unmanaged callbacks.
            /// </summary>
            internal UnmanagedCallbacks Callbacks { get; private set; }

            /// <summary>
            /// Lifecycle handlers.
            /// </summary>
            internal IList<LifecycleHandlerHolder> LifecycleHandlers { get; set; }

            /// <summary>
            /// Node name.
            /// </summary>
            internal string Name { get; set; }

            /// <summary>
            /// Marshaller.
            /// </summary>
            internal Marshaller Marshaller { get; set; }

            /// <summary>
            /// Start error.
            /// </summary>
            internal Exception Error { get; set; }

            /// <summary>
            /// Gets or sets the ignite.
            /// </summary>
            internal Ignite Ignite { get; set; }
        }

        /// <summary>
        /// Internal handler for event notification.
        /// </summary>
        private class InternalLifecycleHandler : ILifecycleHandler
        {
            /** */
            #pragma warning disable 649   // unused field
            [InstanceResource] private readonly IIgnite _ignite;

            /** <inheritdoc /> */
            public void OnLifecycleEvent(LifecycleEventType evt)
            {
                if (evt == LifecycleEventType.BeforeNodeStop && _ignite != null)
                    ((Ignite) _ignite).BeforeNodeStop();
            }
        }
    }
}
