/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
/* This work has been released under the CC0 1.0 Universal license!           */
/******************************************************************************/

using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.Threading;

namespace com.muldersoft.slunkcrypt.gui.utils
{
    class ApplicationConfig
    {
        private readonly ConcurrentDictionary<string, int> m_cache = new ConcurrentDictionary<string, int>();

        public bool DisableBusyIndicator
        {
            get
            {
                return ComputeIfAbsent("DisableBusyIndicator", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
            }
        }
 
        public bool KeepIncompleteFiles
        {
            get
            {
                return ComputeIfAbsent("KeepIncompleteFiles", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
            }
        }

        public int ThreadCount
        {
            get
            {
                return ComputeIfAbsent("ThreadCount", (key) => AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0));
            }
        }

        public bool LegacyCompat
        {
            get
            {
                return ComputeIfAbsent("LegacyCompat", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
            }
        }

        // =============================================================================
        // Internal methods
        // =============================================================================

        protected int ComputeIfAbsent(string name, Func<string, int> valueFactory)
        {
            return m_cache.GetOrAdd(name, valueFactory);
        }

        protected bool ComputeIfAbsent(string name, Func<string, bool> valueFactory)
        {
            return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key))));
        }

        // =============================================================================
        // Helper class
        // =============================================================================

        private static class AppConfHelper
        {
            private static readonly Lazy<KeyValueConfigurationCollection> m_settings = new Lazy<KeyValueConfigurationCollection>(InitializeSettings, LazyThreadSafetyMode.ExecutionAndPublication);

            private static volatile object m_syncRoot;

            public static string GetConfigValue(string name)
            {
                KeyValueConfigurationCollection settings = m_settings.Value;
                if (!ReferenceEquals(settings, null))
                {
                    lock (settings.SyncRoot ?? SyncRootInstance)
                    {
                        try
                        {
                            KeyValueConfigurationElement element = settings[name];
                            if (!ReferenceEquals(element, null))
                            {
                                string value = element.Value;
                                return string.IsNullOrWhiteSpace(value) ? string.Empty : value;
                            }
                        }
                        catch { }
                    }
                }
                return string.Empty;
            }

            public static bool? GetConfigValueAsBool(string name)
            {
                string value;
                if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
                {
                    bool result;
                    if (bool.TryParse(value.Trim(), out result))
                    {
                        return result;
                    }
                }
                return null;
            }

            public static int? GetConfigValueAsInt32(string name)
            {
                string value;
                if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
                {
                    int result;
                    if (int.TryParse(value.Trim(), out result))
                    {
                        return result;
                    }
                }
                return null;
            }

            private static KeyValueConfigurationCollection InitializeSettings()
            {
                try
                {
                    Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    return configuration.AppSettings.Settings;
                }
                catch
                {
                    return null;
                }
            }

            private static object SyncRootInstance
            {
                get
                {
                    if (m_syncRoot == null)
                    {
                        Interlocked.CompareExchange<object>(ref m_syncRoot, new object(), null);
                    }
                    return m_syncRoot;
                }
            }
        }
    }
}
