//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2026 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

const { PDFNet } = require('@pdftron/pdfnet-node');
const PDFTronLicense = require('../LicenseKey/LicenseKey');

((exports) => {
	'use strict';

	exports.runDocumentCreationTest = async () => {
		// Iterate over all text runs of the document and make every second run
		// bold with smaller font size.
		const modifyContentTree = async (node) => {
			let bold = false;
		
			const itr = await node.getContentNodeIterator();
			while (await itr.hasNext()) {
				const el = await itr.current();
				itr.next();
		
				const text_run = await el.asTextRun();
				if (text_run !== null) {
					if (bold) {
						const styledElement = await text_run.getTextStyledElement();
						styledElement.setBold(true);
						styledElement.setFontSize(await styledElement.getFontSize() * 0.8);
					}
					bold = !bold;
					continue;
				}
		
				const content_node = await el.asContentNode();
				if (content_node !== null) {
					await modifyContentTree(content_node);
					continue;
				}
			}
		};

		const main = async () => {

			const outputPath = '../TestFiles/Output/';
			try {
				const para_text = 
				"Lorem ipsum dolor " +
				"sit amet, consectetur adipisicing elit, sed " +
				"do eiusmod tempor incididunt ut labore " +
				"et dolore magna aliqua. Ut enim ad " +
				"minim veniam, quis nostrud exercitation " +
				"ullamco laboris nisi ut aliquip ex ea " +
				"commodo consequat. Duis aute irure " +
				"dolor in reprehenderit in voluptate velit " +
				"esse cillum dolore eu fugiat nulla pariatur. " +
				"Excepteur sint occaecat cupidatat " +
				"non proident, sunt in culpa qui officia " +
				"deserunt mollit anim id est laborum.";

				const flowdoc = await PDFNet.FlowDocument.create();
				const para = await flowdoc.addParagraph();
				const st_para = await para.getTextStyledElement();

				st_para.setFontSize(24);
				st_para.setTextColor(255, 0, 0);
				para.addText('Start \tRed \tText\n');

				para.addTabStop(150);
				para.addTabStop(250);
				st_para.setTextColor(0, 0, 255);
				para.addText('Start \tBlue \tText\n');

				let last_run = await para.addText('Start Green Text\n');

				let start = true;
				const para_itr = await para.getContentNodeIterator();
				while (await para_itr.hasNext()) {
					const el = await para_itr.current();
					const run = await el.asTextRun();
					if (run !== null) {
						(await run.getTextStyledElement()).setFontSize(12);
						if (start) {
							// Restore red color.
							start = false;
							run.setText(await run.getText() + '(restored \tred \tcolor)\n');
							(await run.getTextStyledElement()).setTextColor(255, 0, 0);
						}
					}
					await para_itr.next();
				}

				const st_last = await last_run.getTextStyledElement();
				st_last.setTextColor(0, 255, 0);
				st_last.setItalic(true);
				st_last.setFontSize(18);

				(await para.getTextStyledElement()).setBold(true);
				para.setBorder(0.2, 0, 127, 0);
				st_last.setBold(false);

				await flowdoc.addParagraphWithText('Simple list creation process. All elements are added in their natural order\n\n');

				const list = await flowdoc.addList();
				list.setNumberFormat(PDFNet.List.NumberFormat.e_upper_letter, ".", false);
				list.setStartIndex(4);

				const item = await list.addItem(); // creates "D."
				item.addParagraphWithText('item 0[0]');
				const px = await item.addParagraphWithText('item 0[1]');
				const xx_para = await px.getTextStyledElement();
				xx_para.setTextColor(255, 99, 71);
				px.addText(' Some More Text!');

				const item2 = await list.addItem(); // creates "E."
				const item2List = await item2.addList();
				item2List.setStartIndex(0);
				item2List.setNumberFormat(PDFNet.List.NumberFormat.e_decimal, '', true);
				(await item2List.addItem()).addParagraphWithText('item 1[0].0');
				const pp = await (await item2List.addItem()).addParagraphWithText('item 1[0].1');
				const sx_para = await pp.getTextStyledElement();
				sx_para.setTextColor(0, 0, 255);
				pp.addText(' Some More Text');
				(await item2List.addItem()).addParagraphWithText('item 1[0].2');
				const item2List1 = await (await item2List.addItem()).addList();
				item2List1.setStartIndex(7);
				item2List1.setNumberFormat(PDFNet.List.NumberFormat.e_upper_roman, ')', true);
				(await item2List1.addItem()).addParagraphWithText('item 1[0].3.0');
				(await item2List1.addItem()).addParagraphWithText('item 1[0].3.1');

				const extraItem = await item2List1.addItem();
				extraItem.addParagraphWithText('item 1[0].3.2[0]');
				extraItem.addParagraphWithText('item 1[0].3.2[1]');
				let fourth = await extraItem.addList();
				fourth.setNumberFormat(PDFNet.List.NumberFormat.e_decimal, '', true);
				(await fourth.addItem()).addParagraphWithText('Fourth Level');

				fourth = await (await item2List1.addItem()).addList();
				fourth.setNumberFormat(PDFNet.List.NumberFormat.e_lower_letter, '', true);
				(await fourth.addItem()).addParagraphWithText('Fourth Level (again)');

				item2.addParagraphWithText('item 1[1]');
				const item2List2 = await item2.addList();
				item2List2.setStartIndex(10);
				item2List2.setNumberFormat(PDFNet.List.NumberFormat.e_lower_roman, ".", false);
				(await item2List2.addItem()).addParagraphWithText('item 1[2].0');
				(await item2List2.addItem()).addParagraphWithText('item 1[2].1');
				(await item2List2.addItem()).addParagraphWithText('item 1[2].2');

				const item3 = await list.addItem(); // creates "F."
				item3.addParagraphWithText('item 2');

				const item4 = await list.addItem(); // creates "G."
				item4.addParagraphWithText('item 3');

				const item5 = await list.addItem(); // creates "H."
				item5.addParagraphWithText('item 4');

				const body_itr = await (await flowdoc.getBody()).getContentNodeIterator();
				while (await body_itr.hasNext()) {
					const el = await body_itr.current();

					const list = await el.asList();
					if (list !== null && (await list.getIndentationLevel()) === 1) {
						const p = await (await list.addItem()).addParagraphWithText('Item added during iteration');
						const ps = await p.getTextStyledElement();
						ps.setTextColor(0, 127, 0);
					}

					const list_item = await el.asListItem();
					if (list_item !== null && (await list_item.getIndentationLevel()) === 2) {
						const p = await list_item.addParagraphWithText('* Paragraph added during iteration');
						const ps = await p.getTextStyledElement();
						ps.setTextColor(0, 0, 255);
					}
					await body_itr.next();
				}

				flowdoc.addParagraphWithText('\f'); // page break

				flowdoc.addParagraphWithText(
					'Nonlinear list creation flow. Items are added randomly.' +
					' List body separated by a paragraph, does not belong to the list\n\n'
				);

				const list2 = await flowdoc.addList();
				list2.setNumberFormat(PDFNet.List.NumberFormat.e_upper_letter, ".", false);
				list2.setStartIndex(4);

				const item6 = await list2.addItem(); // creates "D."
				item6.addParagraphWithText('item 0[0]');
				const px2 = await item6.addParagraphWithText('item 0[1]');
				const xx_para2 = await px2.getTextStyledElement();
				xx_para2.setTextColor(255, 99, 71);
				px2.addText(' Some More Text!');
				item6.addParagraphWithText('item 0[2]');
				const px3 = await item6.addParagraphWithText('item 0[3]');
				item6.addParagraphWithText('item 0[4]');
				const xx_para3 = await px3.getTextStyledElement();
				xx_para3.setTextColor(255, 99, 71);

				const item7 = await list2.addItem(); // creates "E."
				const item7List = await item7.addList();
				item7List.setStartIndex(0);
				item7List.setNumberFormat(PDFNet.List.NumberFormat.e_decimal, '', true);
				(await item7List.addItem()).addParagraphWithText('item 1[0].0');
				const pp2 = await (await item7List.addItem()).addParagraphWithText('item 1[0].1');
				const sx_para2 = await pp2.getTextStyledElement();
				sx_para2.setTextColor(0, 0, 255);
				pp2.addText(' Some More Text');

				const item8 = await list2.addItem(); // creates "F."
				item8.addParagraphWithText('item 2');

				(await item7List.addItem()).addParagraphWithText('item 1[0].2');

				item7.addParagraphWithText('item 1[1]');
				const item7List2 = await item7.addList();
				item7List2.setStartIndex(10);
				item7List2.setNumberFormat(PDFNet.List.NumberFormat.e_lower_roman, ".", false);
				(await item7List2.addItem()).addParagraphWithText('item 1[2].0');
				(await item7List2.addItem()).addParagraphWithText('item 1[2].1');
				(await item7List2.addItem()).addParagraphWithText('item 1[2].2');

				const item9 = await list2.addItem(); // creates "G."
				item9.addParagraphWithText('item 3');

				const item7List1 = await (await item7List.addItem()).addList();
				item7List1.setStartIndex(7);
				item7List1.setNumberFormat(PDFNet.List.NumberFormat.e_upper_roman, ')', true);
				(await item7List1.addItem()).addParagraphWithText('item 1[0].3.0');

				flowdoc.addParagraphWithText(
					'---------------------------------- splitting paragraph ----------------------------------'
				);

				item7List1.continueList();

				(await item7List1.addItem()).addParagraphWithText('item 1[0].3.1 (continued)');
				const extraItem2 = await item7List1.addItem();
				extraItem2.addParagraphWithText('item 1[0].3.2[0]');
				extraItem2.addParagraphWithText('item 1[0].3.2[1]');
				let fourth2 = await extraItem2.addList();
				fourth2.setNumberFormat(PDFNet.List.NumberFormat.e_decimal, '', true);
				(await fourth2.addItem()).addParagraphWithText('FOURTH LEVEL');

				const item10 = await list2.addItem(); // creates "H."
				item10.addParagraphWithText('item 4 (continued)');

				flowdoc.addParagraphWithText(' ');

				flowdoc.setDefaultMargins(72.0, 72.0, 144.0, 228.0);
				flowdoc.setDefaultPageSize(650, 750);
				flowdoc.addParagraphWithText(para_text);

				const clr1 = [50, 50, 199];
				const clr2 = [30, 199, 30];

				for (let i = 0; i < 50; i++) {
					const para = await flowdoc.addParagraph();
					const style = await para.getTextStyledElement();
					const point_size = (17 * i * i * i) % 13 + 5;
					if (i % 2 === 0) {
						style.setItalic(true);
						style.setTextColor(clr1[0], clr1[1], clr1[2]);
						style.setBackgroundColor(200, 200, 200);
						para.setSpaceBefore(20);
						para.setStartIndent(20);
						para.setJustificationMode(PDFNet.Paragraph.TextJustification.e_text_justify_left);
					} else {
						style.setTextColor(clr2[0], clr2[1], clr2[2]);
						para.setSpaceBefore(50);
						para.setEndIndent(20);
						para.setJustificationMode(PDFNet.Paragraph.TextJustification.e_text_justify_right);
					}

					para.addText(para_text);
					para.addText(' ' + para_text);
					style.setFontSize(point_size);
				}

				// Table creation
				const new_table = await flowdoc.addTable();
				new_table.setDefaultColumnWidth(100);
				new_table.setDefaultRowHeight(15);

				for (let i = 0; i < 4; i++) {
					const row = await new_table.addTableRow();
					row.setRowHeight(await new_table.getDefaultRowHeight() + i * 5);
					for (let j = 0; j < 5; j++) {
						const cell = await row.addTableCell();
						cell.setBorder(0.5, 255, 0, 0);

						if (i === 3) {
							if (j % 2 !== 0) {
								cell.setVerticalAlignment(
									PDFNet.TableCell.AlignmentVertical.e_alignment_center);
							} else {
								cell.setVerticalAlignment(
									PDFNet.TableCell.AlignmentVertical.e_alignment_bottom);
							}
						}

						if (i === 3 && j === 4) {
							const para_title = await cell.addParagraphWithText('Table title');
							para_title.setJustificationMode(
								PDFNet.Paragraph.TextJustification.e_text_justify_center);

							const nested_table = await cell.addTable();
							nested_table.setDefaultColumnWidth(33);
							nested_table.setDefaultRowHeight(5);
							nested_table.setBorder(0.5, 0, 0, 0);

							for (let nested_row_index = 0; nested_row_index < 3; nested_row_index++) {
								const nested_row = await nested_table.addTableRow();
								for (let nested_column_index = 0; nested_column_index < 3; nested_column_index++) {
									const para_str = `${nested_row_index}/${nested_column_index}`;
									const nested_cell = await nested_row.addTableCell();
									nested_cell.setBackgroundColor(200, 200, 255);
									nested_cell.setBorder(0.1, 0, 255, 0);

									const new_para = await nested_cell.addParagraphWithText(para_str);
									new_para.setJustificationMode(
										PDFNet.Paragraph.TextJustification.e_text_justify_right);
								}
							}
						} else if (i === 2 && j === 2) {
							const new_para = await cell.addParagraphWithText(`Cell ${j} x ${i}\n`);
							new_para.addText('to be bold text 1\n');
							new_para.addText('still normal text\n');
							new_para.addText('to be bold text 2');
							cell.addParagraphWithText('Second Paragraph');
						} else {
							cell.addParagraphWithText(`Cell ${j} x ${i}`);
						}
					}
				}

				// Walk the content tree and modify some text runs.
				await modifyContentTree(await flowdoc.getBody());

				// Merge cells
				const merged_cell = await (await new_table.getTableCell(2, 0)).mergeCellsRight(1);
				merged_cell.setHorizontalAlignment(PDFNet.TableCell.AlignmentHorizontal.e_alignment_middle);

				(await (await new_table.getTableCell(0, 0)).mergeCellsDown(1)).setVerticalAlignment(
					PDFNet.TableCell.AlignmentVertical.e_alignment_center
				);

				// Walk over the table and change the first cell in each row.
				let row_idx = 0;
				const clr_row1 = [175, 240, 240];
				const clr_row2 = [250, 250, 175];

				const table_itr = await new_table.getContentNodeIterator();
				while (await table_itr.hasNext()) {
					const row = await (await table_itr.current()).asTableRow();
					if (row !== null) {
						const row_itr = await row.getContentNodeIterator();
						while (await row_itr.hasNext()) {
							const cell = await (await row_itr.current()).asTableCell();
							if (cell !== null) {
								if (row_idx % 2 !== 0) {
									cell.setBackgroundColor(clr_row1[0], clr_row1[1], clr_row1[2]);
								} else {
									cell.setBackgroundColor(clr_row2[0], clr_row2[1], clr_row2[2]);
								}

								const cell_itr = await cell.getContentNodeIterator();
								while (await cell_itr.hasNext()) {
									const element = await cell_itr.current();
									const para = await element.asParagraph();
									if (para !== null) {
										const st = await para.getTextStyledElement();
										st.setTextColor(255, 0, 0);
										st.setFontSize(12);
									} else {
										const nested_table = await element.asTable();
										if (nested_table !== null) {
											const nested_cell = await nested_table.getTableCell(1, 1);
											nested_cell.setBackgroundColor(255, 127, 127);
										}
									}
									await cell_itr.next();
								}
							}
							await row_itr.next();
						}
					}

					row_idx += 1;
					await table_itr.next();
				}

				const my_pdf = await flowdoc.paginateToPDF();
				my_pdf.save(outputPath + "created_doc.pdf", PDFNet.SDFDoc.SaveOptions.e_linearized);
				console.log('Done.');
			} catch (err) {
			  console.log(err);
			}
		};

		PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function (error) {
			console.log('Error: ' + JSON.stringify(error));
		}).then(function () { return PDFNet.shutdown(); });
	};
	exports.runDocumentCreationTest();
})(exports);
// eslint-disable-next-line spaced-comment
//# sourceURL=DocumentCreationTest.js
