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

namespace CDAValidator
{
    public class Transformator
    {
        /*
         * Sample Code from 
         * Das C# 2010 Codebook
         * Jürgen Bayer
         * http://bookshop.pearson.de/main/main.asp?page=home/bookdetails&productid=174368&tab=download
         */
        public Transformator(String Iso, String Elga)
        {
            string appPath = System.IO.Path.GetDirectoryName(
                 System.Reflection.Assembly.GetEntryAssembly().Location);

            string schemaFileNameStage1 = Path.Combine(appPath, "Test-Transformed-Stage1.xsd");
            string schemaFileNameStage2 = Path.Combine(appPath, "Test-Transformed-Stage2.xsd");
            string schemaFileNameStage3 = Path.Combine(appPath, "Test-Transformed-Stage3.xsd");

            /*
             * Schematrontransformation nach ISO Schematron
             * http://www.schematron.com/
             * 
             * 
             */

            // Phase 1: Zusammensetzen des Schemas aus mehreren Teilen (sofern vorhanden)
            TransformXmlDocument(Elga, Path.Combine(Iso,
                "Schematron\\iso_dsdl_include.xsl"), schemaFileNameStage1);
           
            // Phase 2: Konvertieren abstrakter Muster in reale
            TransformXmlDocument(schemaFileNameStage1, Path.Combine(Iso,
                "Schematron\\iso_abstract_expand.xsl"), schemaFileNameStage2);

            // Phase 3: Kompilieren des Schematron-Schemas in ein XSLT-Skript
            TransformXmlDocument(schemaFileNameStage2, Path.Combine(Iso,
                "Schematron\\iso_svrl_for_xslt2.xsl"), schemaFileNameStage3);
        }

        private static void logError(Exception ex)
        {
            Logging.eventLog(ex);
            Logging.writeLog(ex.ToString());
        }

         public static void TransformXmlDocument(string sourceFileName, string xslFileName, string resultFileName)
        {
#if DEBUG
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
#endif
            Processor processor = null;
            XdmNode input = null;
            XsltTransformer transformer = null;
            try
            {
                // Das Quelldokument laden
                processor = new Processor();
                input = processor.NewDocumentBuilder().Build(new Uri(sourceFileName));
            }
            catch (Exception e)
            {
                logError(e);
            }
            try
            {
                // Einen Transformer für das Stylesheet erzeugen
                var xsltCompiler = processor.NewXsltCompiler();
                transformer = xsltCompiler.Compile(new Uri(xslFileName)).Load();

                // Den Dokument-Knoten als initialen Kontext-Knoten setzen
                transformer.InitialContextNode = input;
            }
            catch (Exception e)
            {
                logError(e);
            }
            
            try
            {
                // Einen Serializer erzeugen, der in die Ergebnisdatei schreibt
                Serializer serializer = new Serializer();
                
                
                using (StreamWriter outputWriter = new StreamWriter(resultFileName))
                {
                    serializer.SetOutputWriter(outputWriter);

                    // Die Quelldatei transformieren und das Ergebnis in das 
                    // Ergebnisdokument serialisieren
                    
                    transformer.Run(serializer);
                    
                }
                
            }
            catch (Exception e)
            {
                logError(e);
            }

#if DEBUG
            stopwatch.Stop();
            Debug.WriteLine("Transformieren von '" + (new FileInfo(sourceFileName)).Name + "': " +
                stopwatch.Elapsed.TotalSeconds.ToString("0.0000") + " Sekunden");
#endif
        }
    }

}


