//******************************************************************************//
// Settings.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY  METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//

// Ignore Spelling: Taskbar

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Windows.Media;
using System.Windows;
using NLog;
using Raytheon.Common;
using Raytheon.LogDashboard.ViewModel;
using System.Linq;

namespace Raytheon.LogDashboard.Model
{
    [Serializable]
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public sealed class Settings
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        private static Settings instance;
        private readonly string settingsPath;
        private static LogDashViewModelLocator locatorInstance => (Application.Current.Resources["LogDashLocator"] as LogDashViewModelLocator);

        public bool AutoStartInStartup { get; set; } = false;
        public bool MinimizeToTray { get; set; } = false;
        public bool OnlyOneAppInstance { get; set; } = false;
        public bool IsEnabledMaxMessageBufferSize { get; set; } = false;
        public int MaxMessageBufferSize { get; set; } = 1000000;
        public int DeletedMessagesCount { get; set; } = 100000;
        public string DataFormat { get; set; } = "MM/dd/yyyy HH:mm:ss.fff";
        public string FontColor { get; set; } = "#FFFFFFFF";

        private static List<ColorTheme> BuildListOfThemes()
        {
            List<KeyValuePair<string, Color>> colors = typeof(Colors)
                .GetProperties()
                .Where(prop => typeof(Color).IsAssignableFrom(prop.PropertyType))
                .Select(prop => new KeyValuePair<string, Color>(prop.Name, (Color)prop.GetValue(null)))
                .ToList();

            List<ColorTheme> themes = new List<ColorTheme>();

            foreach(var color in colors)
            {
                themes.Add(new ColorTheme { Color = new SolidColorBrush(color.Value), Name = color.Key, ThemeColorString = color.Value.ToString() });
            }

            return themes;
        }
        public static List<ColorTheme> ColorThemes { get; } = BuildListOfThemes();

        public static List<string> Themes { get; } = new List<string> { "BaseLight", "BaseDark" };

        public ColorTheme CurrentColorTheme { get; set; } 

        public string CurrentTheme { get; set; }

        public List<Receiver> Receivers { get; set; } = new List<Receiver>();
        public List<IgnoredIPAddr> IgnoredIPs { get; set; } = new List<IgnoredIPAddr>();

        /// <summary>
        /// show column with source
        /// </summary>
        public bool IsShowSourceColumn { get; set; } = false;

        /// <summary>
        /// show thread column
        /// </summary>
        public bool IsShowThreadColumn { get; set; } = true;

        /// <summary>
        /// show progress in the taskbar
        /// </summary>
        public bool IsShowTaskbarProgress { get; set; } = true;

        /// <summary>
        /// highlight message with receiver color
        /// </summary>
        public bool ShowMessageHighlightByReceiverColor { get; set; } = false;

        /// <summary>
        /// separate logs by port number
        /// </summary>
        public bool IsSeparateIPLoggersByPort { get; set; } = false;

        public bool IsAutoSave { get; set; }

        public bool IsErrorLogger { get; set; }

        public string AutoSaveLocation { get; set; }

        public long AutoSaveMaxSize { get; set; }

        /// <summary>
        /// indicates if LogDashboard is embedded in another application
        /// </summary>
        public bool EmbeddedMode { get; set; }

        private Settings(string path)
        {
            settingsPath = !string.IsNullOrEmpty(path)
                ? path
                : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LogDashboard", "LogDashboard.xml");
        }

        public static Settings Instance => instance ?? SetInstance("");

        public static Settings SetInstance(string path) => instance ?? (instance = new Settings(path));

        /// <summary>
        /// using theme
        /// </summary>
        public void ApplyTheme()
        {
            try
            {
                Application.Current.Resources.MergedDictionaries[2] = new ResourceDictionary { Source = CurrentColorTheme.ThemeUri };
            }
            catch(Exception e)
            {
                logger.Warn(e, $"An error occurred while ApplyTheme. SelectedTheme - {CurrentColorTheme.Name}");
            }
        }

        /// <summary>
        /// save settings
        /// </summary>
        /// <returns></returns>
        public bool Save()
        {
            try
            {
                ConfigurationFile configurationFile = new ConfigurationFile(settingsPath);

                List<ReceiverSetting> receiverSettings = new List<ReceiverSetting>();
                foreach(Receiver receiver in Instance.Receivers)
                {
                    receiverSettings.Add(new ReceiverSetting(receiver));
                }

                configurationFile.WriteValue("Base", "AutoStartInStartup", Instance.AutoStartInStartup);
                configurationFile.WriteValue("Base", "MinimizeToTray", Instance.MinimizeToTray);
                configurationFile.WriteValue("CurrentThemes", "CurrentColorTheme", Instance.CurrentColorTheme);
                configurationFile.WriteValue("CurrentThemes", "CurrentTheme", Instance.CurrentTheme);
                configurationFile.WriteValue("Base", "DataFormat", Instance.DataFormat);
                configurationFile.WriteList("IgnoredIP", "IgnoredIP", Instance.IgnoredIPs);
                configurationFile.WriteList("ReceiverList", "Receiver", receiverSettings);
                configurationFile.WriteValue("Base", "FontColor", Instance.FontColor);
                configurationFile.WriteValue("Base", "OnlyOneAppInstance", Instance.OnlyOneAppInstance);
                configurationFile.WriteValue("Base", "IsEnabledMaxMessageBufferSize", Instance.IsEnabledMaxMessageBufferSize);
                configurationFile.WriteValue("Base", "MaxMessageBufferSize", Instance.MaxMessageBufferSize);
                configurationFile.WriteValue("Base", "DeletedMessagesCount", Instance.DeletedMessagesCount);
                configurationFile.WriteValue("Base", "IsShowSourceColumn", Instance.IsShowSourceColumn);
                configurationFile.WriteValue("Base", "IsShowThreadColumn", Instance.IsShowThreadColumn);
                configurationFile.WriteValue("Base", "IsShowTaskbarProgress", Instance.IsShowTaskbarProgress);
                configurationFile.WriteValue("Base", "ShowMessageHighlightByReceiverColor", Instance.ShowMessageHighlightByReceiverColor);
                configurationFile.WriteValue("Base", "IsSeparateIPLoggersByPort", Instance.IsSeparateIPLoggersByPort);
                configurationFile.WriteValue("Base", "EmbeddedMode", Instance.EmbeddedMode);
                configurationFile.WriteValue("Base", "IsAutoSave", Instance.IsAutoSave);
                configurationFile.WriteValue("Base", "IsErrorLogger", Instance.IsErrorLogger);
                configurationFile.WriteValue("Base", "AutoSaveLocation", Instance.AutoSaveLocation ?? "");

                return true;
            }
            catch(Exception e)
            {
                logger.Warn(e, "An error occurred while Save settings.");
                return false;
            }
        }

        public void Load()
        {
            IConfigurationFile configurationFile = new ConfigurationFile(settingsPath);
            Instance.AutoStartInStartup = configurationFile.ReadValue("Base", "AutoStartInStartup", true);
            Instance.MinimizeToTray = configurationFile.ReadValue("Base", "MinimizeToTray", false);

            Instance.CurrentColorTheme = configurationFile.ReadValue("CurrentThemes", "CurrentColorTheme", new ColorTheme { Color = new SolidColorBrush(), Name = "DodgerBlue", ThemeColorString = "#FF1E90FF" });
            
            Instance.CurrentTheme = configurationFile.ReadValue("CurrentThemes", "CurrentTheme", "BaseLight");

            Instance.DataFormat = configurationFile.ReadValue("Base", "DataFormat", "MM/dd/yyyy HH:mm:ss.fff");
            Instance.IgnoredIPs = configurationFile.ReadList("IgnoredIP", "IgnoredIP", new List<IgnoredIPAddr>());
            var receiverSettins = configurationFile.ReadList("ReceiverList", "Receiver", new List<ReceiverSetting>
            {
                new ReceiverSetting { Name = "UDP", ReceiverType = ReceiverType.UDP, Port = 7777, IsActive = true, ColorString = "#00FFFFFF", IsPortVisible = true, Encoding = "UTF-8" }
            });

            foreach(ReceiverSetting receiverSetting in receiverSettins)
            {
                Instance.Receivers.Add(new Receiver(receiverSetting));
            }

            Instance.FontColor = configurationFile.ReadValue("Base", "FontColor", "#FF1E90FF");
            Instance.OnlyOneAppInstance = configurationFile.ReadValue("Base", "OnlyOneAppInstance", true);
            Instance.IsEnabledMaxMessageBufferSize = configurationFile.ReadValue("Base", "IsEnabledMaxMessageBufferSize", false);
            Instance.MaxMessageBufferSize = configurationFile.ReadValue("Base", "MaxMessageBufferSize", 1000000);
            Instance.DeletedMessagesCount = configurationFile.ReadValue("Base", "DeletedMessagesCount", 100000);
            Instance.IsShowSourceColumn = configurationFile.ReadValue("Base", "IsShowSourceColumn", true);
            Instance.IsShowThreadColumn = configurationFile.ReadValue("Base", "IsShowThreadColumn", true);
            Instance.IsShowTaskbarProgress = configurationFile.ReadValue("Base", "IsShowTaskbarProgress", true);
            Instance.ShowMessageHighlightByReceiverColor = configurationFile.ReadValue("Base", "ShowMessageHighlightByReceiverColor", true);
            Instance.IsSeparateIPLoggersByPort = configurationFile.ReadValue("Base", "IsSeparateIPLoggersByPort", true);
            Instance.EmbeddedMode = configurationFile.ReadValue("Base", "EmbeddedMode", false);
            Instance.IsAutoSave = configurationFile.ReadValue("Base", "IsAutoSave", false);
            Instance.IsErrorLogger = configurationFile.ReadValue("Base", "IsErrorLogger", false);
            Instance.AutoSaveLocation = configurationFile.ReadValue("Base", "AutoSaveLocation", "");
            Instance.AutoSaveMaxSize = configurationFile.ReadValue<long>("Base", "AutoSaveMaxSize", 10 * 1048576); // 10 MG
        }
    }
}
