ProductListTemplate.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Html;

namespace DsPdfWeb.Demos
{
    // This sample shows how to render a report (the list of products
    // from the standard NWind sample database) using a {{mustache}}
    // HTML template.
    //
    // The data query and HTML formatting are similar to those used
    // in the ProductList sample. Unlike that sample though, here
    // we use the HTML template file ProductListTemplate.html
    // loaded from a resource, and bind it to data using {{mustache}}.
    // Changing the template file (preserving the {{mustache}} bindings)
    // can be used to easily customize the look of the report.
    //
    // This sample uses the Stubble.Core package to bind data to the template.
    //
    // Please see notes in comments at the top of HelloWorldHtml
    // sample code for details on adding DsHtml to your projects.
    public class ProductListTemplate
    {
        public void CreatePDF(Stream stream)
        {
            using var ds = new DataSet();
            // Fetch data:
            ds.ReadXml(Path.Combine("Resources", "data", "DsNWind.xml"));

            DataTable dtProds = ds.Tables["Products"];
            DataTable dtSupps = ds.Tables["Suppliers"];

            var products =
                from prod in dtProds.Select()
                join supp in dtSupps.Select()
                on prod["SupplierID"] equals supp["SupplierID"]
                orderby prod["ProductName"]
                select new
                {
                    ProductID = prod["ProductID"],
                    ProductName = prod["ProductName"],
                    Supplier = supp["CompanyName"],
                    QuantityPerUnit = prod["QuantityPerUnit"],
                    UnitPrice = $"{prod["UnitPrice"]:C}"
                };

            // Load the template - HTML file with {{mustache}} data references:
            var template = File.ReadAllText(Path.Combine("Resources", "Misc", "ProductListTemplate.html"));
            // Bind the template to data:
            var builder = new Stubble.Core.Builders.StubbleBuilder();
            var boundTemplate = builder.Build().Render(template, new { Query = products });

            // Create an instance of GcHtmlBrowser that is used to render HTML:
            using var browser = Common.Util.NewHtmlBrowser();
            // Render the bound HTML:
            using var htmlPage = browser.NewPage(boundTemplate);
            // PdfOptions specifies options for HTML to PDF conversion:
            var pdfOptions = new PdfOptions()
            {
                Margins = new PdfMargins(0.2f, 1, 0.2f, 1),
                PreferCSSPageSize = false,
                DisplayHeaderFooter = true,
                HeaderTemplate = "<div style='color:#1a5276; font-size:12px; width:1000px; margin-left:0.2in; margin-right:0.2in'>" +
                    "<span style='float:left;'>Product Price List</span>" +
                    "<span style='float:right'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></span>" +
                    "</div>",
                FooterTemplate = "<div style='color: #1a5276; font-size:12em; width:1000px; margin-left:0.2in; margin-right:0.2in;'>" +
                    "<span>(c) MESCIUS inc. All Rights Reserved.</span>" +
                    "<span style='float:right'>Generated on <span class='date'></span></span></div>"
            };
            // Render the generated HTML to the temporary file:
            var tmp = Path.GetTempFileName();
            htmlPage.SaveAsPdf(tmp, pdfOptions);

            // Copy the created PDF from the temp file to target stream:
            using (var ts = File.OpenRead(tmp))
                ts.CopyTo(stream);
            // Clean up:
            File.Delete(tmp);
            // Done.
        }
    }
}