using iText.Html2pdf;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace WK5.Core.Drucken
{
    /// <summary>
    /// Stellt die Basis einer Implementierung für eine neue Druckvorlage dar.
    /// </summary>
    public abstract class PrintBase
    {
        /*
         * Es gibt in keiner Implementierung einen public Konstruktor, da Daten nicht asynchron im Konstruktor geladen werden können.
         * Daher verwenden die Implementierungen ein Pattern über eine asynchrone statische Funktion
         * public static async Task<T> CreateAsync(xxx)
         * 
         * T = Typ der Implemtierung. Beispiel: PrintAngebot
         * In dieser Funktion wird ein private Konstruktor aufgerufen und es werden alle Daten soweit initialisiert, sodass 
         * über Print(); das PDF generiert werden kann.
         */


        /// <summary>
        /// Ruft den Basispfad für alle DruckTemplate Dateien ab.
        /// <para>
        /// Dieser Wert sollte nicht verändert werden!
        /// </para>
        /// </summary>
        public const string LAYOUT_PATH = "Drucken\\DruckTemplates";

        /// <summary>
        /// Ruft den Dateinamen des ausgewählten Layouts ab.
        /// <para>
        /// Beispiel: Angebot.html
        /// </para>
        /// </summary>
        protected string _layoutFile = String.Empty;
        /// <summary>
        /// Ruft den HTML-Inhalt des Drucklayouts ab.
        /// <para>
        /// Wird in <see cref="InitializeAsync"/> mit den Daten des <see cref="_layoutFile"/> gefüllt und doie Platzhalter werden hier in <see cref="SetTemplateVariables"/> ersetzt.
        /// </para>
        /// </summary>
        protected string _template = String.Empty;

        protected PrintBase()
        {

        }

        /// <summary>
        /// Generiert das Dokument als PDF und gibt das entsprechende Byte Array zurück.
        /// </summary>
        /// <returns>Gibt ein Byte Array zurück welches das PDF Dokument enthält.</returns>
        public byte[] GetBytes()
        {
            byte[] byteArray = Encoding.UTF8.GetBytes(_template);
            MemoryStream stream = new MemoryStream(byteArray);
            ConverterProperties converterProperties = new ConverterProperties()
                .SetBaseUri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LAYOUT_PATH));

            MemoryStream output = new MemoryStream();

            HtmlConverter.ConvertToPdf(stream, output, converterProperties);

            return output.ToArray();
        }

        /// <summary>
        /// Generiert das Dokument als PDF an dem angegeben Speicherort.
        /// </summary>
        /// <param name="speicherpfad">Der Pfad in dem das Dokument gespeichert werden soll, ohne Dateinamen.</param>
        /// <returns>Gibt den vollständigen Dateinamen zur generierten PDF zurück.</returns>
        public abstract string Print(string speicherpfad);               
        /// <summary>
        /// Legt Anzeigeregeln für die Generierung des PDFs fest.
        /// </summary>
        protected abstract void SetRegeln();
        /// <summary>
        /// Überschreibt die Platzhalter-Variabeln des Layouts mit dem entsprechenden Inhalt.
        /// </summary>
        /// <returns></returns>
        protected abstract Task<string> SetTemplateVariables();
        /// <summary>
        /// Kann verwendet werden, um noch zusätzliche Daten abzufragen
        /// </summary>
        /// <returns></returns>
        protected abstract Task InitializeAsync();
        /// <summary>
        /// Initialisiert die Printvorlage, sodass die Methode <see cref="Print(string)"/> aufgerufen werden kann.
        /// </summary>
        /// <returns></returns>
        protected abstract Task InitializeAsync(FbController2 fbController);
        /// <summary>
        /// Generiert die Style Section, die alle Klassen ausblendet, die durch <see cref="SetRegeln"/> festgelegt worden sind.
        /// </summary>
        /// <returns></returns>
        protected abstract string GenerateDisplayCss();
    }
}
