using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using System.Linq;

namespace AyaNova.Util
{

    /// <summary>
    /// Contains config values from bootup
    /// </summary>
    internal static class ServerBootConfig
    {

        //AUTOID's

        //Get the highest id number issued previously and start the auto-id at that level
        internal static AutoId WIDGET_SERIAL { get; set; }


        //Diagnostic static values used during development, may not be related to config at all, this is just a convenient class to put them in
#if (DEBUG)
        internal static List<string> LocaleKeysRequested { get; set; }

#endif


        //CONTENTROOTPATH
        internal static string AYANOVA_CONTENT_ROOT_PATH { get; set; } //Note: set in startup.cs, not in program.cs as it requires startup IHostingEnvironment


        //LANGUAGE / LOCALE
        internal static string AYANOVA_DEFAULT_LANGUAGE { get; set; }
        internal static long AYANOVA_DEFAULT_LANGUAGE_ID { get; set; } //internal setting set at boot by LocaleBiz::ValidateLocales

        //API
        internal static string AYANOVA_JWT_SECRET { get; set; }
        internal static string AYANOVA_USE_URLS { get; set; }

        //DATABASE
        internal static string AYANOVA_DB_CONNECTION { get; set; }
        internal static bool AYANOVA_PERMANENTLY_ERASE_DATABASE { get; set; }

        //FILE FOLDERS
        internal static string AYANOVA_FOLDER_USER_FILES { get; set; }
        internal static string AYANOVA_FOLDER_BACKUP_FILES { get; set; }

        //LOGGING
        internal static string AYANOVA_LOG_PATH { get; set; }
        internal static string AYANOVA_LOG_LEVEL { get; set; }
        internal static bool AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG { get; set; }



        //METRICS
        internal static bool AYANOVA_METRICS_USE_INFLUXDB { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_BASEURL { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_DBNAME { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_CONSISTENCY { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_USERNAME { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_PASSWORD { get; set; }
        internal static string AYANOVA_METRICS_INFLUXDB_RETENSION_POLICY { get; set; }
        internal static bool AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS { get; set; }

        /// <summary>
        /// Populate the config from the configuration found at boot
        /// called by program.cs
        /// </summary>
        /// <param name="config"></param>
        internal static void SetConfiguration(IConfigurationRoot config)
        {

#if (DEBUG)
            LocaleKeysRequested = new List<string>();
#endif

            bool? bTemp = null;

            #region SERVER BASICS

            //LANGUAGE
            //LocaleBiz will validate this later at boot pfc and ensure a sane default is set (English)
            AYANOVA_DEFAULT_LANGUAGE = config.GetValue<string>("AYANOVA_DEFAULT_LANGUAGE");
            AYANOVA_DEFAULT_LANGUAGE = string.IsNullOrWhiteSpace(AYANOVA_DEFAULT_LANGUAGE) ? "en" : AYANOVA_DEFAULT_LANGUAGE;
            string lowLocale = AYANOVA_DEFAULT_LANGUAGE.ToLowerInvariant();
            switch (lowLocale)
            {
                case "en":
                case "english":
                    AYANOVA_DEFAULT_LANGUAGE = "en";
                    break;
                case "de":
                case "deutsch":
                case "german":
                    AYANOVA_DEFAULT_LANGUAGE = "de";
                    break;
                case "es":
                case "español":
                case "spanish":
                    AYANOVA_DEFAULT_LANGUAGE = "es";
                    break;
                case "fr":
                case "français":
                case "french":
                    AYANOVA_DEFAULT_LANGUAGE = "fr";
                    break;
                default:
                    AYANOVA_DEFAULT_LANGUAGE = "en";
                    break;
            }




            //LOGLEVEL
            AYANOVA_LOG_LEVEL = config.GetValue<string>("AYANOVA_LOG_LEVEL");
            AYANOVA_LOG_LEVEL = string.IsNullOrWhiteSpace(AYANOVA_LOG_LEVEL) ? "Info" : AYANOVA_LOG_LEVEL;

            //LOGGING DIAGNOSTIC LOG
            bTemp = config.GetValue<bool?>("AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG");
            AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG = (null == bTemp) ? false : (bool)bTemp;

            //PORT / API
            AYANOVA_USE_URLS = config.GetValue<string>("AYANOVA_USE_URLS");
            AYANOVA_USE_URLS = string.IsNullOrWhiteSpace(AYANOVA_USE_URLS) ? "http://*:7575" : AYANOVA_USE_URLS;

            AYANOVA_JWT_SECRET = config.GetValue<string>("AYANOVA_JWT_SECRET");

            //DB
            AYANOVA_DB_CONNECTION = config.GetValue<string>("AYANOVA_DB_CONNECTION");
            bTemp = config.GetValue<bool?>("AYANOVA_PERMANENTLY_ERASE_DATABASE");
            AYANOVA_PERMANENTLY_ERASE_DATABASE = (null == bTemp) ? false : (bool)bTemp;


            //FOLDERS
            //Log folder
            AYANOVA_LOG_PATH = config.GetValue<string>("AYANOVA_LOG_PATH");

            if (AYANOVA_LOG_PATH == null)
            {
                //DEFAULT LOG PATH
                var currentDir = Directory.GetCurrentDirectory();
                AYANOVA_LOG_PATH = Path.Combine(currentDir, "logs");
            }
            else
            {
                AYANOVA_LOG_PATH = Path.Combine(AYANOVA_LOG_PATH, "logs");
            }

            //(note, startup.cs ensures these folders exist via FileUtil because we need IHostingEnvironment)
            //UserFiles
            AYANOVA_FOLDER_USER_FILES = config.GetValue<string>("AYANOVA_FOLDER_USER_FILES");

            //BackupFiles
            AYANOVA_FOLDER_BACKUP_FILES = config.GetValue<string>("AYANOVA_FOLDER_BACKUP_FILES");
            #endregion server BASICS

            #region METRICS
            //InfluxDB
            bTemp = config.GetValue<bool?>("AYANOVA_METRICS_USE_INFLUXDB");
            AYANOVA_METRICS_USE_INFLUXDB = (null == bTemp) ? false : (bool)bTemp;

            AYANOVA_METRICS_INFLUXDB_BASEURL = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_BASEURL");
            AYANOVA_METRICS_INFLUXDB_BASEURL = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_BASEURL) ? "http://127.0.0.1:8086" : AYANOVA_METRICS_INFLUXDB_BASEURL;

            AYANOVA_METRICS_INFLUXDB_DBNAME = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_DBNAME");
            AYANOVA_METRICS_INFLUXDB_DBNAME = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_DBNAME) ? "AyaNova" : AYANOVA_METRICS_INFLUXDB_DBNAME;

            AYANOVA_METRICS_INFLUXDB_CONSISTENCY = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_CONSISTENCY");
            //No default value, if it's null or empty or whitespace then it won't be set

            AYANOVA_METRICS_INFLUXDB_USERNAME = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_USERNAME");
            AYANOVA_METRICS_INFLUXDB_USERNAME = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_USERNAME) ? "root" : AYANOVA_METRICS_INFLUXDB_USERNAME;

            AYANOVA_METRICS_INFLUXDB_PASSWORD = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_PASSWORD");
            AYANOVA_METRICS_INFLUXDB_PASSWORD = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_PASSWORD) ? "root" : AYANOVA_METRICS_INFLUXDB_PASSWORD;

            AYANOVA_METRICS_INFLUXDB_RETENSION_POLICY = config.GetValue<string>("AYANOVA_METRICS_INFLUXDB_RETENSION_POLICY");
            //No default value, if it's null or empty or whitespace then it won't be set

            bTemp = config.GetValue<bool?>("AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS");
            AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS = (null == bTemp) ? true : (bool)bTemp;
            #endregion

        }


        //Fetch first url from list of urls (used by generator)
        internal static string FirstOfAyaNovaUseUrls
        {
            get
            {
                if (string.IsNullOrWhiteSpace(AYANOVA_USE_URLS))
                { return null; }

                if (!AYANOVA_USE_URLS.Contains(";"))
                {
                    return AYANOVA_USE_URLS.Replace("*", "localhost");
                }
                var s = AYANOVA_USE_URLS.Split(';');
                return s[0].Replace("*", "localhost");

            }
        }


        //Get the auto-id most recent values at boot time
        internal static void SetMostRecentAutoIdValuesFromDatabase(AyaNova.Models.AyContext ct)
        {
            //WIDGET SERIALS
            if (WIDGET_SERIAL == null)
            {
                //query for most recently used serial number
                //(note, can't query for highest serial as it can and likely will reset or be changed manually from time to time
                // so the algorithm is to keep the most recent sequence going on startup of the server)
                var MostRecentWidget = ct.Widget.AsNoTracking().OrderByDescending(x => x.Id).FirstOrDefault();
                uint MaxWidgetId = 0;
                if (MostRecentWidget != null)
                    MaxWidgetId = MostRecentWidget.Serial;
                WIDGET_SERIAL = new AutoId(MaxWidgetId);

            }

            //OTHER SERIALS HERE IN FUTURE...
        }



    }//eoc


}//eons