using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml.Linq;
using Saxon.Api;
using System.Diagnostics;
using System.Xml;
using System.Xml.Schema;
using System.Threading;



namespace CDAValidator
{
    public class CDALetterValidator 
    {
        private String FileName;
        public static XDocument resultDocument { get; set; }
        public static String FilePath { get; set; }
        public List<string> SchemaErrors { get; set; }
        public List<string> SchemaWarnings { get; set; }


        public CDALetterValidator(String fileName)
        {
            FileName = fileName;
            FilePath = Directory.GetCurrentDirectory();
            SchemaErrors = new List<string>();            
            SchemaWarnings = new List<string>();
        }

        internal void validateAgainstSchematron()
        {

            resultDocument = ValidateXmlFile(FileName, Path.Combine(FilePath, "elga-cdabgd.sch"));
        }

        internal void validateAgainstSchema()
        {
           

            string xmlFileName = Path.Combine(FilePath, FileName);
            string xmlSchemaUri = Path.Combine(FilePath, "ELGASCHEMA/elgaschema.xsd");
           
            // XmlReaderSettings erzeugen und den Validier-Typ festlegen
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;

            // Schema ohne Ziel-Namensraum hinzufügen
            settings.Schemas.Add(null, xmlSchemaUri);

            // Dem ValidationEventHandler-Ereignis eine anonyme Methode zuweisen,
            // die die Auswertung der Fehler und Warnungen übernimmt
           
            settings.ValidationEventHandler += (sender, e) =>
            {
                // Info zum Ort des Fehlers ermitteln
                string locationInfo = null;
                if (e.Exception != null)
                {
                    locationInfo = "Zeile " + e.Exception.LineNumber +
                      ", Zeichen " + e.Exception.LinePosition + ": ";
                }

                // e.Severity definiert den Schweregrad. XmlSeverityType.Error
                // steht für Fehler, XmlSeverityType.Warning für Warnungen. 
                // Warnungen werden typischerweise generiert, wenn es kein DTD oder
                // XML-Schema gibt, um ein bestimmtes Element oder Attribut zu validieren.
                if (e.Severity == XmlSeverityType.Error)
                {
                    SchemaErrors.Add(locationInfo + e.Message);
                }
                else
                {
                    SchemaWarnings.Add(locationInfo + e.Message);
                }
            };

            // Einen XmlValidatingReader erzeugen, um das XML-Dokument in ein 
            // XElement zu lesen
            XElement rootElement;
            using (XmlReader xmlReader = XmlReader.Create(xmlFileName,
               settings))
            {
                rootElement = XElement.Load(xmlReader);
            }

        }



        private static XDocument ValidateXmlFile(string xmlFileName, string schematronSchemaFileName)
        {
           string schemaFileNameStage3 = Path.Combine(FilePath, "Test-Transformed-Stage3.xsd");
           string resultFileName = Path.Combine(FilePath, "Result.xml");
           Transformator.TransformXmlDocument(xmlFileName, schemaFileNameStage3, resultFileName);
           return XDocument.Load(resultFileName);
        
        }


        private void logError(String error)
        {
            Logging.eventLog(error, EventLogEntryType.Error);
            Logging.writeLog(error.ToString());
        }




        internal bool isWellFormed()
        {
            //XML Dokument auf Wohlgeformtheit prüfen
            using (XmlReader xr = XmlReader.Create(Path.Combine(FilePath, FileName)))
            {
                try
                {
                    while (xr.Read()) { }
                    logInformation("CDA Dokument ist wohlgeformt");
                    return true;
                }
                catch (Exception ex)
                {
                    logError("CDA Dokument ist nicht wohlgeformt: " + ex.Message);
                    return false;
                }
            }
        }

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


    }
}
