AiLoremOutlines.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 GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Pdf.AI;
using DsPdfWeb.Demos.Common;
using System.Threading.Tasks;

namespace DsPdfWeb.Demos
{
    // This sample generates a PDF with random content and uses the PDF AI Assistant (DsPdfAI)
    // to analyze the document content and generate an outline tree (bookmarks) based on inferred headings,
    // which is then added to the PDF.
    //
    // See PaginatedText for an example of using TextLayout for generating a multi-page PDF document.
    //
    // To run this sample locally, set your OpenAI credentials
    // using Util.OpenAIToken.

    public class AiLoremOutlines
    {
        public int CreatePDF(Stream stream)
        {
            var doc = GeneratePDF();
            try
            {
                // Use the PDF AI Assistant to analyze the document content and generate outlines:
                var a = new OpenAIDocumentAssistant(Util.OpenAIToken);
                var task = a.BuildOutlines(doc);
                task.Wait();
                // Set the page mode so that a viewer shows the outlines (bookmarks) on PDF open:
                doc.PageMode = PageMode.UseOutlines;
            }
            catch (Exception ex)
            {
                // Make sure you have assigned your OpenAI API key to Util.OpenAIToken:
                Util.CreatePdfError(doc, ex.Message);
            }
            doc.Save(stream);
            return doc.Pages.Count;
        }

        // Generate a PDF with random hierarchical content and return it:
        GcPdfDocument GeneratePDF()
        {
            var doc = new GcPdfDocument();
            var rnd = Util.NewRandom();
            var tl = new TextLayout(72)
            {
                MaxWidth = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = 72,
                FirstLineIndent = 36,
            };
            tl.DefaultFormat.Font = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            var fmtChapter = new TextFormat(tl.DefaultFormat) { FontSize = 18, FontBold = true };
            var fmtSection = new TextFormat(tl.DefaultFormat) { FontSize = 16, FontBold = true };
            var fmtSubSection = new TextFormat(tl.DefaultFormat) { FontSize = 14, FontBold = true };
            var fmtNormal = new TextFormat(tl.DefaultFormat) { FontSize = 12 };
            for (int i = 0; i < rnd.Next(2, 5); i++)
            {
                tl.Append($"Chapter {i + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtChapter);
                tl.AppendParagraphBreak(fmtChapter);
                for (int j = 0; j < rnd.Next(2, 4); j++)
                {
                    tl.Append($"Section {i + 1}.{j + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtSection);
                    tl.AppendParagraphBreak(fmtSection);
                    for (int k = 0; k < rnd.Next(2, 3); k++)
                    {
                        tl.Append($"Sub-section {i + 1}.{j + 1}.{k + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtSubSection);
                        tl.AppendParagraphBreak(fmtSubSection);
                        tl.AppendLine(Util.LoremIpsum(1), fmtNormal);
                    }
                }
            }
            // Split and render TextLayout as shown in the PaginatedText sample:
            var tso = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph = 2,
            };
            tl.PerformLayout(true);
            var tls = new TextLayoutSplitter(tl);
            for (var tlPage = tls.Split(tso); tlPage != null; tlPage = tls.Split(tso))
                doc.NewPage().Graphics.DrawTextLayout(tlPage, PointF.Empty);
            return doc;
        }
    }
}