using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

using C4IT.Logging;
using C4IT.XML;
using C4IT.FASD.Base;
using C4IT.DataHistoryProvider;

using static C4IT.Logging.cLogManager;

namespace F4SD_Cockpit_ConfigLoader
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                InitializeComponent();
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }

        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                WaitingImage.Visibility = Visibility.Collapsed;
                textBoxConfigPath.Text = App.ConfigFilesFolder;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private void buttonSelectConfigPath_Click(object sender, RoutedEventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                var openFileDlg = new System.Windows.Forms.OpenFileDialog();
                openFileDlg.FileName = textBoxConfigPath.Text;
                openFileDlg.ValidateNames = false;
                openFileDlg.CheckFileExists = false;
                openFileDlg.CheckPathExists = true;
                openFileDlg.FileName = "select a folder.";
                var result = openFileDlg.ShowDialog();
                if (result is System.Windows.Forms.DialogResult.OK)
                {
                    var _path = openFileDlg.FileName;
                    _path = System.IO.Path.GetDirectoryName(_path);
                    if (System.IO.Directory.Exists(_path))
                        textBoxConfigPath.Text = _path;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }

        }

        private void buttonLoadConfigFiles_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(textBoxConfigPath.Text))
                return;

            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                rtbProtocol.Document.Blocks.Clear();

                var _path = textBoxConfigPath.Text;
                if (System.IO.Directory.Exists(_path))
                {
                    App.SaveConfigPath(_path);
                    AddProtocolText($"Loading configuration files from folder '{_path}'...", Colors.Blue);

                    LoadConfiguration(_path);

                }
                else
                {
                    AddProtocolText($"The path '{_path}' could not be found!", Colors.Red);
                    rtbProtocol.AppendText("");
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private void AddProtocolText(string _text, Color _color)
        {
            try
            {
                var paragraph = new Paragraph();
                var run = new Run(_text)
                {
                    Foreground = new SolidColorBrush(_color)
                };
                paragraph.Inlines.Add(run);
                rtbProtocol.Document.Blocks.Add(paragraph);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void AddProtocol(List<cXmlParserNodeMessage> _parsingMessages)
        {
            foreach (var _msg in _parsingMessages)
            {
                var _strMsg = cXmlParser.GetMessageString(_msg);
                var _col = Colors.Black;
                switch (_msg.Level)
                {
                    case LogLevels.Info:
                        _col = Colors.Black;
                        break;
                    case LogLevels.Warning:
                        _col = Colors.DarkOrange;
                        break;
                    case LogLevels.Error:
                        _col = Colors.Red;
                        break;
                    case LogLevels.Fatal:
                        _col = Colors.Purple;
                        break;
                    case LogLevels.Debug:
                        _col = Colors.DarkGray;
                        break;
                }
                AddProtocolText("    " + _strMsg, _col);
            }
        }

        private void AddProtocolResult(cFasdBaseConfig _config, List<cXmlParserNodeMessage> _parsingMessages, string FileName)
        {
            AddProtocol(_parsingMessages);
            if (_config?.IsValid is true)
            {
                if (_parsingMessages?.Count >= 1)
                    AddProtocolText($"  Configuration file '{cDataHistoryConfigClusters.constFileNameF4sdConfig}' is valid but has some annotations!", Colors.DarkOrange);
                else
                    AddProtocolText($"  Configuration file '{cDataHistoryConfigClusters.constFileNameF4sdConfig}' is valid.", Colors.DarkGreen);
            }
            else
                AddProtocolText($"  Configuration file '{cDataHistoryConfigClusters.constFileNameF4sdConfig}' has non trivial errors and is invalid!", Colors.Red);

            rtbProtocol.AppendText("");
        }

        private async void LoadConfiguration(string configPath)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            var _currentCursor = Cursor; 
            try
            {
                Cursor = System.Windows.Input.Cursors.Wait;
                WaitingImage.Visibility = Visibility.Visible;
                buttonLoadConfigFiles.IsEnabled = false;
                buttonSelectConfigPath.IsEnabled = false;

                List<cXmlParserNodeMessage> _parsingMessages = null;

                // load and validate the data clusters configuration file
                var _cfgClusters = new cDataHistoryConfigClusters();
                AddProtocolText($"  Loading and parsing configuration file '{_cfgClusters._fileNameConfig}'", Colors.Black);

                await Task.Run(() =>
                {
                    _cfgClusters.LoadFromFile(out _parsingMessages, Folder: configPath);
                });
                AddProtocolResult(_cfgClusters, _parsingMessages, _cfgClusters._fileNameConfig);

                // load and validate the client configuration files
                var _Configs = new Dictionary<enumFasdConfigurationType, cFasdBaseConfig>();
                var _lst = Enum.GetValues(typeof(enumFasdConfigurationType)).Cast<enumFasdConfigurationType>();
                foreach (var _entry in _lst)
                {
                    if (_entry != enumFasdConfigurationType.unknown)
                    {
                        var _cfg = cFasdBaseConfig.CreateConfigByType(_entry);
                        if (_cfg != null)
                        {
                            AddProtocolText($"  Loading and parsing configuration file '{_cfg._fileNameConfig}'", Colors.Black);
                            await Task.Run(() =>
                            {
                                _cfg.LoadFromFile(out _parsingMessages, Folder: configPath);
                            });
                            AddProtocolResult(_cfg, _parsingMessages, _cfg._fileNameConfig);
                        }
                    }

                }

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                WaitingImage.Visibility = Visibility.Collapsed;
                buttonLoadConfigFiles.IsEnabled = true;
                buttonSelectConfigPath.IsEnabled = true;
                Cursor = _currentCursor;
                if (CM != null) LogMethodEnd(CM);
            }
        }
    }
}
