using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Serialization;
using System.Collections.Specialized;
using System.Xml.Linq;
using System.Windows.Threading;
using System.Diagnostics;
using System.Xml;
using System.Threading;


namespace CDAValidator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        private static FileSystemWatcher watcher;

        private CDALetterValidator validator;
        private bool modusWait;


        public MainWindow()
        {
            InitializeComponent();
            Initialize();
           
        }
        private void Initialize()
        {

            watcher = new FileSystemWatcher(ConfigSettings.Default.FilePath);
            ComboBox.SelectedIndex = 0;

        }

        #region ButtonAction

        private void Start_Click(object sender, RoutedEventArgs e)
        {

            if (!System.IO.File.Exists(ConfigSettings.Default.TransformedName))
            {
                rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Die Datei 'Test-Transformed-Stage3.xsd' existiert nicht!")));
                rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Diese kann unter Einstellungen - Schematron Transformation erstellt werden")));

            }
            else
            {
                //rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Validation wird durchgeführt. Bitte warten....")));
                if (ComboBox.SelectedIndex == 0)
                {
                    modusWait = true;
                }
                else
                {
                    modusWait = false;
                }
                rdbTextBox.Document.Blocks.Clear();
                Initialize();
                Start.IsEnabled = false;
                Stop1.IsEnabled = true;
                Settings.IsEnabled = false;



                if (modusWait)
                {
                    rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Test gestartet - Warte auf Befund....")));
                    Stop.IsEnabled = true;
                    this.UpdateLayout();


                    // Only watch xml files.

                    watcher.Filter = "*.xml";
                    // Add event handlers.          
                    watcher.Created += OnCreated;

                    // Begin watching.
                    watcher.EnableRaisingEvents = true;
                }
                else
                {
                    //System.Windows.Forms.MessageBox.Show("Validation gestartet - Bitte warten....");
                    ComboBox.SelectedIndex = 1;
                    Stop.IsEnabled = true;
                    this.UpdateLayout();
                    System.Windows.Forms.MessageBoxEx.Show("Validation gestartet - Bitte warten...", "Info", 3000);
                    validateFolder();

                }
            }

        }
        private void Settings_Click(object sender, RoutedEventArgs e)
        {
            Settings setWin = new Settings();
            setWin.Show();
        }
        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (ComboBox.SelectedItem == "Auf Befund warten")
            {
                modusWait = true;
            }
            else if (ComboBox.SelectedItem == "Ordner validieren")
            {
                modusWait = false;
            }
        }
        private void Stop1_Click(object sender, RoutedEventArgs e)
        {
            Initialize();
            this.Start.IsEnabled = true;
            Stop1.IsEnabled = false;
            Settings.IsEnabled = true;
            rdbTextBox.Document.Blocks.Clear();
            rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Test gestoppt!") { FontWeight = FontWeights.Bold }));
            rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("\nBitte starten Sie die Anwendung um mit der Validation fortzusetzen oder beenden Sie den Vorgang!")));
        }

        #endregion

        #region PrintResults

        public void writeSchemaResults(String fileName)
        {
            if (validator.SchemaErrors.Count() == 0)
            {
                TextRange rangeOfText2 = new TextRange(rdbTextBox.Document.ContentEnd, rdbTextBox.Document.ContentEnd);
                String text = "\nist nach dem Schema valide\n";
                rangeOfText2.Text = text;
                logInformation(text);
                rangeOfText2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Green);
                rangeOfText2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
            }

            else
            {

                TextRange rangeOfText2 = new TextRange(rdbTextBox.Document.ContentEnd, rdbTextBox.Document.ContentEnd);
                String text = "\nist nach dem Schema nicht valide, weil:";
                rangeOfText2.Text = text;
                logInformation(text);
                rangeOfText2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
                rangeOfText2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);

                foreach (var error in validator.SchemaErrors)
                {

                    rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("*\t" + error)));
                    logInformation(error);
                }
            }
            writeWarnings();
        }

        public void writeSchemaResult(String fileName)
        {
            Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Clear()));
            if (validator.SchemaErrors.Count() == 0)
            {
                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Der Befund --- " + fileName + " ---") { FontWeight = FontWeights.Bold }))));
                String text = "\nist nach dem Schema valide";
                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(text) { FontWeight = FontWeights.Bold, Foreground = Brushes.Green }))));
                logInformation(text);
            }

            else
            {
                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Der Befund --- " + fileName + " ---") { FontWeight = FontWeights.Bold }))));
                String text = "\nist nach dem Schema nicht valide, weil:";

                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(text) { FontWeight = FontWeights.Bold, Foreground = Brushes.Red }))));
                Logging.eventLog(text, EventLogEntryType.Information);
                logInformation(text);

                foreach (var error in validator.SchemaErrors)
                {
                    Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(error)))));
                    logInformation(error);

                }
            }

            writeWarnings();
        }

        private void writeWarnings()
        {
            if (validator.SchemaWarnings.Count > 0)
            {
                foreach (var warning in validator.SchemaWarnings)
                {
                    logInformation(warning);
                }
            }
        }

        private void writeSchematronResults(string fileName)
        {



            int cntError = 0;
            XNamespace ns = "http://purl.oclc.org/dsdl/svrl";
            var Assertions = CDALetterValidator.resultDocument.Root.Elements(ns + "failed-assert");
            String text = "";

            if (Assertions.Count() == 0)
            {
                TextRange rangeOfText2 = new TextRange(rdbTextBox.Document.ContentEnd, rdbTextBox.Document.ContentEnd);
                text = "\nist nach dem Schematron valide\n";
                rangeOfText2.Text = text;
                logInformation(text);
                rangeOfText2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Green);
                rangeOfText2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
            }

            else
            {

                foreach (var Assertion in Assertions)
                {

                    if (cntError < 1)
                    {
                        TextRange rangeOfText2 = new TextRange(rdbTextBox.Document.ContentEnd, rdbTextBox.Document.ContentEnd);
                        text = "\nist nach dem Schematron nicht valide, weil:";
                        rangeOfText2.Text = text;
                        logInformation(text);
                        rangeOfText2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
                        rangeOfText2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                        cntError++;
                    }


                    String t = /*+ Assertion.Attribute("location").Value + ": " +*/
                        Assertion.Element(ns + "text").Value.Trim();
                    rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(t)));
                    logInformation(t);
                }
                rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("\n")));
                cntError = 0;
            }
        }

        private void WriteSchematronResult(string fileName)
        {
            XNamespace ns = "http://purl.oclc.org/dsdl/svrl";
            var Assertions = CDALetterValidator.resultDocument.Root.Elements(ns + "failed-assert");

            String text = null;

            if (Assertions.Count() == 0)
            {
                text = "\nist nach dem Schematron valide\n\n";

                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(text) { FontWeight = FontWeights.Bold, Foreground = Brushes.Green }))));
                logInformation(text);
            }
            else if (Assertions.Count() != 0)
            {
                text = "\nist nach dem Schematron nicht valide, weil:";

                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(text) { FontWeight = FontWeights.Bold, Foreground = Brushes.Red }))));
                Logging.eventLog(text, EventLogEntryType.Information);
                logInformation(text);
                foreach (var Assertion in Assertions)
                {
                    text = /*Assertion.Attribute("location").Value + ": " +*/
                        Assertion.Element(ns + "text").Value.Trim();
                    Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run(text)))));
                    logInformation(text);
                }
            }

            text = "";
            Dispatcher.BeginInvoke(new Action(() => Stop1.IsEnabled = true));
            //Stop1.IsEnabled = false;
        }

        private void logInformation(string text)
        {
            Logging.eventLog(text, EventLogEntryType.Information);
            Logging.writeLog(text);
        }

        #endregion

        #region Folder

        private void validateFolder()
        {
            DirectoryInfo ParentDirectory = new DirectoryInfo(ConfigSettings.Default.FilePath);
            foreach (FileInfo file in ParentDirectory.GetFiles("*.xml"))
            {
                validator = new CDALetterValidator(file.FullName);
                if (validator.isWellFormed())
                {
                    rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Der Befund ---" + file.FullName + " ---") { FontWeight = FontWeights.Bold }));
                    validator.validateAgainstSchema();
                    writeSchemaResults(file.FullName);
                    validator.validateAgainstSchematron();
                    writeSchematronResults(file.FullName);
                }
                else
                {
                    rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Das CDA Dokument ---" + file.FullName + "--- ist nicht wohlgeformt - Somit konnte keine Validierung durchgeführt werden.\n\n") { FontWeight = FontWeights.Bold, Foreground = Brushes.Red }));
                    Start.IsEnabled = true;
                }
            }
        }



        #endregion

        #region Wait
        private void OnCreated(object sender, FileSystemEventArgs e)
        {
            Dispatcher.BeginInvoke(new Action(() => Stop1.IsEnabled = false));
            watcher.Dispose();
            System.Threading.Thread.Sleep(300);
            //System.Windows.Forms.MessageBox.Show(e.FullPath);
            validator = new CDALetterValidator(e.FullPath);

            if (validator.isWellFormed())
            {
                System.Windows.Forms.MessageBoxEx.Show("Validation gestartet - Bitte warten...", "Info", 3000);
                validator.validateAgainstSchema();
                
                writeSchemaResult(e.FullPath);

                //es wird gegen das elga schematron validiert
                validator.validateAgainstSchematron();

                WriteSchematronResult(e.Name);
                Dispatcher.BeginInvoke(new Action(() => Start.IsEnabled = true));
            }
            else
            {
                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Clear()));
                Dispatcher.BeginInvoke(new Action(() => rdbTextBox.Document.Blocks.Add(new Paragraph(new Run("Das CDA Dokument ist nicht wohlgeformt - Somit konnte keine Validierung durchgeführt werden.") { FontWeight = FontWeights.Bold, Foreground = Brushes.Red}))));
                Dispatcher.BeginInvoke(new Action(() => Start.IsEnabled = true));
            }

        }

        #endregion

      

    }
}

