//
//    Copyright (C) 2018 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 Microsoft.Win32;
using System.Linq;
using static Hiperscan.Common.I18n.CatalogLocale;
using System.Collections.Generic;

namespace Hiperscan.Common.RegistryManagement
{
    public class MSRegistry
    {
        public static DateTime NO_DATE = DateTime.MinValue;

        private const string FULL_VERION_KEY = "FullVersion";
        private const string INSTALL_PATH_KEY = "InstallPath";
        private const string INSTALL_DATE_KEY = "InstallDate";
        private const string LOCALE_KEY = "Locale";
        private const string EXECUTING_FILE = "ExecutingFile";

        private const string CORRECTION_TOOL = "CorrectionTool";
        private const string PDF_INFO = "PdfInfo";
        private const string QS_OPEN = "QuickStepOS";
        private const string QS_CLOSE = "QuickStepCS";
        private const string IDENT_MODULE = "IdentModule";
        private const string QUANTIFIER_MODULE = "QuantifierModule";

        public static MSRegistry Create()
        {
            lock(MSRegistry.Sync)
            {
                if (MSRegistry.Instance == null)
                {
                    MSRegistry.Instance = new MSRegistry();
                    MSRegistry.Instance.GetIdentExenstionEntries();
                }

                return MSRegistry.Instance;
            }
        }

        private MSRegistry()
        {
           try
            {
                string key_path = String.Format(@"Software\Hiperscan");
                this.HiperScanRegistryKey = Registry.LocalMachine.OpenSubKey(key_path);
               
            }
                catch (Exception)
            {
                this.HiperScanRegistryKey = null;
            }
        }

        private HSRegistryEntry GetHsRegistryEntry(string name)
        {
            HSRegistryEntry entry = new HSRegistryEntry();

            try
            {
                if (this.HasHiperScanRegistryKey == false)
                    return entry;

                RegistryKey key = this.HiperScanRegistryKey.OpenSubKey(name);
                if (key == null)
                    return entry;
                                  
                entry.FullVersion = this.GetStringValue(key, MSRegistry.FULL_VERION_KEY);
                entry.InstallPath = this.GetStringValue(key, MSRegistry.INSTALL_PATH_KEY);
                entry.InstallDate = this.GetDateValue(key, MSRegistry.INSTALL_DATE_KEY);
                entry.Locale = this.GetLocaleValue(key, MSRegistry.LOCALE_KEY);
                entry.ExecutingFile = this.GetStringValue(key, MSRegistry.EXECUTING_FILE);
                entry.HasRegistryEntry = true;
            }
            catch(Exception)
            {
                entry.HasRegistryEntry = false;
            }

            return entry;
        }

        private void GetIdentExenstionEntries()
        {
            foreach(string sub_key in this.HiperScanRegistryKey.GetSubKeyNames())
            {
                HSRegistryEntry entry = this.GetHsRegistryEntry(sub_key);
                if (entry.HasRegistryEntry == false)
                    continue;

                string path = (entry.InstallPath ?? String.Empty).TrimEnd(new char[] { '\\' });
                if (path.EndsWith(DefaultNames.IdentServer.EXTENSION_NAME, StringComparison.InvariantCulture))
                    this.IdentExtensionEntries.Add(entry);
            }
        }

        private LocaleType GetLocaleValue(RegistryKey key, string name)
        {
            try
            {
                string value = (string)key.GetValue(name);
                return (LocaleType)Enum.Parse(typeof(LocaleType), value);
            }
            catch(Exception)
            {
                return LocaleType.Unknown;
            }
        }

        private DateTime GetDateValue(RegistryKey key, string name)
        {
            try
            {
                string value = (string)key.GetValue(name);
                return DateTime.Parse(value);
            }
            catch (Exception)
            {
                return MSRegistry.NO_DATE;
            }
        }

        private string GetStringValue(RegistryKey key, string name)
        {
            try
            {
                return (string)key.GetValue(name) ?? String.Empty;
            }
            catch (Exception)
            {
                return String.Empty;
            }
        }

        private HSRegistryEntry quickstep_open = null;
        public HSRegistryEntry QuickStepOpen
        {
            get
            {
                if (this.quickstep_open == null)
                    this.quickstep_open = this.GetHsRegistryEntry(MSRegistry.QS_OPEN);

                return this.quickstep_open;
            }
        }

        private HSRegistryEntry quickstep_close = null;
        public HSRegistryEntry QuickStepClose
        {
            get
            {
                if (this.quickstep_close == null)
                    this.quickstep_close = this.GetHsRegistryEntry(MSRegistry.QS_CLOSE);

                return this.quickstep_close;
            }
        }

        private HSRegistryEntry ident_module = null;
        public HSRegistryEntry IdentModule
        {
            get
            {
                if (this.ident_module == null)
                    this.ident_module = this.GetHsRegistryEntry(MSRegistry.IDENT_MODULE);

                return this.ident_module;
            }
        }

        private HSRegistryEntry quantifier_module = null;
        public HSRegistryEntry QuantifierModule
        {
            get
            {
                if (this.quantifier_module == null)
                    this.quantifier_module = this.GetHsRegistryEntry(MSRegistry.QUANTIFIER_MODULE);

                return this.quantifier_module;
            }
        }

        private HSRegistryEntry pdf_info = null;
        public HSRegistryEntry PdfInfo
        {
            get
            {
                if (this.pdf_info == null)
                    this.pdf_info = this.GetHsRegistryEntry(MSRegistry.PDF_INFO);

                return this.pdf_info;
            }
        }

        private HSRegistryEntry correction_tool = null;
        public HSRegistryEntry CorrectionTool
        {
            get
            {
                if (this.correction_tool == null)
                    this.correction_tool = this.GetHsRegistryEntry(MSRegistry.CORRECTION_TOOL);

                return this.correction_tool;
            }
        }

        private bool HasHiperScanRegistryKey
        {
            get
            {
                return this.HiperScanRegistryKey != null;
            }
        }

        public IReadOnlyCollection<HSRegistryEntry> IdentExtensions
        {
            get
            {
                return this.IdentExtensionEntries.AsReadOnly();
            }
        }

        private RegistryKey HiperScanRegistryKey { get; set; }
        private static MSRegistry Instance { get; set; } = null;
        private static object Sync { get; set; } = new object();
        private List<HSRegistryEntry> IdentExtensionEntries { get; set; } = new List<HSRegistryEntry>();
    }
}
