/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
package org.apache.poi.hssf.converter;

import static org.apache.poi.hssf.converter.AbstractExcelUtils.buildMergedRangesMap;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getAlign;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getBorderStyle;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getBorderWidth;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getColor;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getMergedRange;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.isEmpty;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.isNotEmpty;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.loadXls;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hwpf.converter.FoDocumentFacade;
import org.apache.poi.hwpf.converter.FontReplacer.Triplet;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Beta;
import org.apache.poi.util.XMLHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 * Converts xls files (97-2007) to XSL FO.
 */
@Beta
public class ExcelToFoConverter extends AbstractExcelConverter {
    private static final float CM_PER_INCH = 2.54f;

    private static final float DPI = 72;

    private static final Logger LOG = LogManager.getLogger(ExcelToFoConverter.class);

    private static final float PAPER_A4_HEIGHT_INCHES = 29.4f / CM_PER_INCH;

    private static final float PAPER_A4_WIDTH_INCHES = 21.0f / CM_PER_INCH;

    /**
     * Usage: ExcelToHtmlConverter infile outfile
     * <p>
     * Where infile is an input .xls file ( Word 97-2007) which will be rendered
     * as XSL FO into outfile
     */
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.err.println("Usage: ExcelToFoConverter <inputFile.xls> <saveTo.xml>");
            return;
        }

        System.out.println("Converting " + args[0]);
        System.out.println("Saving output to " + args[1]);

        Document doc = ExcelToHtmlConverter.process(new File(args[0]));

        DOMSource domSource = new DOMSource(doc);
        StreamResult streamResult = new StreamResult(new File(args[1]));

        // TODO set encoding from a command argument
        Transformer serializer = XMLHelper.newTransformer();
        serializer.transform(domSource, streamResult);
    }

    /**
     * Converts Excel file (97-2007) into XSL FO file.
     *
     * @param xlsFile file to process
     * @return DOM representation of result XSL FO
     */
    public static Document process(File xlsFile) throws Exception {
        try (HSSFWorkbook workbook = loadXls(xlsFile)) {
            ExcelToFoConverter excelToHtmlConverter = new ExcelToFoConverter(
                XMLHelper.newDocumentBuilder().newDocument());
            excelToHtmlConverter.processWorkbook(workbook);
            return excelToHtmlConverter.getDocument();
        }
    }

    private final FoDocumentFacade foDocumentFacade;

    private float pageMarginInches = 0.4f;

    public ExcelToFoConverter(Document document) {
        this.foDocumentFacade = new FoDocumentFacade(document);
    }

    public ExcelToFoConverter(FoDocumentFacade foDocumentFacade) {
        this.foDocumentFacade = foDocumentFacade;
    }

    protected String createPageMaster(float tableWidthIn, String pageMasterName) {
        final float paperHeightIn;
        final float paperWidthIn;
        {
            float requiredWidthIn = tableWidthIn + 2 * getPageMarginInches();

            if (requiredWidthIn < PAPER_A4_WIDTH_INCHES) {
                // portrait orientation
                paperWidthIn = PAPER_A4_WIDTH_INCHES;
                paperHeightIn = PAPER_A4_HEIGHT_INCHES;
            } else {
                // landscape orientation
                paperWidthIn = requiredWidthIn;
                paperHeightIn = paperWidthIn
                    * (PAPER_A4_WIDTH_INCHES / PAPER_A4_HEIGHT_INCHES);
            }
        }

        final float leftMargin = getPageMarginInches();
        final float rightMargin = getPageMarginInches();
        final float topMargin = getPageMarginInches();
        final float bottomMargin = getPageMarginInches();

        Element pageMaster = foDocumentFacade
            .addSimplePageMaster(pageMasterName);
        pageMaster.setAttribute("page-height", paperHeightIn + "in");
        pageMaster.setAttribute("page-width", paperWidthIn + "in");

        Element regionBody = foDocumentFacade.addRegionBody(pageMaster);
        regionBody.setAttribute("margin", topMargin + "in " + rightMargin
            + "in " + bottomMargin + "in " + leftMargin + "in");

        return pageMasterName;
    }

    @Override
    protected Document getDocument() {
        return foDocumentFacade.getDocument();
    }

    public float getPageMarginInches() {
        return pageMarginInches;
    }

    /**
     * Returns {@code false} if cell style by itself (without text, i.e.
     * borders, fill, etc.) worth a mention, {@code true} otherwise
     *
     * @return {@code false} if cell style by itself (without text, i.e.
     * borders, fill, etc.) worth a mention, {@code true} otherwise
     */
    protected boolean isEmptyStyle(CellStyle cellStyle) {
        return cellStyle == null || (
            cellStyle.getFillPattern() == FillPatternType.NO_FILL
                && cellStyle.getBorderTop() == BorderStyle.NONE
                && cellStyle.getBorderRight() == BorderStyle.NONE
                && cellStyle.getBorderBottom() == BorderStyle.NONE
                && cellStyle.getBorderLeft() == BorderStyle.NONE
        );
    }

    protected boolean processCell(HSSFWorkbook workbook, HSSFCell cell,
        Element tableCellElement, int normalWidthPx, int maxSpannedWidthPx,
        float normalHeightPt) {
        final HSSFCellStyle cellStyle = cell.getCellStyle();

        String value;
        switch (cell.getCellType()) {
            case STRING:
                // XXX: enrich
                value = cell.getRichStringCellValue().getString();
                break;
            case FORMULA:
                switch (cell.getCachedFormulaResultType()) {
                    case STRING:
                        HSSFRichTextString str = cell.getRichStringCellValue();
                        if (str != null && str.length() > 0) {
                            value = (str.toString());
                        } else {
                            value = AbstractExcelUtils.EMPTY;
                        }
                        break;
                    case NUMERIC:
                        double nValue = cell.getNumericCellValue();
                        short df = cellStyle.getDataFormat();
                        String dfs = cellStyle.getDataFormatString();
                        value = _formatter.formatRawCellContents(nValue, df, dfs);
                        break;
                    case BOOLEAN:
                        value = Boolean.toString(cell.getBooleanCellValue());
                        break;
                    case ERROR:
                        value = ErrorEval.getText(cell.getErrorCellValue());
                        break;
                    default:
                        LOG.atWarn().log("Unexpected cell cachedFormulaResultType ({})", cell.getCachedFormulaResultType());
                        value = AbstractExcelUtils.EMPTY;
                        break;
                }
                break;
            case BLANK:
                value = AbstractExcelUtils.EMPTY;
                break;
            case NUMERIC:
                value = _formatter.formatCellValue(cell);
                break;
            case BOOLEAN:
                value = Boolean.toString(cell.getBooleanCellValue());
                break;
            case ERROR:
                value = ErrorEval.getText(cell.getErrorCellValue());
                break;
            default:
                LOG.atWarn().log("Unexpected cell type ({})", cell.getCellType());
                return true;
        }

        final boolean noText = isEmpty(value);
        final boolean wrapInDivs = !noText && !cellStyle.getWrapText();

        final boolean emptyStyle = isEmptyStyle(cellStyle);
        if (!emptyStyle && noText) {
            /*
             * if cell style is defined (like borders, etc.) but cell text
             * is empty, add "&nbsp;" to output, so browser won't collapse
             * and ignore cell
             */
            value = "\u00A0";
        }

        if (isOutputLeadingSpacesAsNonBreaking() && value.startsWith(" ")) {
            StringBuilder builder = new StringBuilder();
            for (int c = 0; c < value.length(); c++) {
                if (value.charAt(c) != ' ') {
                    break;
                }
                builder.append('\u00a0');
            }

            if (value.length() != builder.length()) {
                builder.append(value.substring(builder.length()));
            }

            value = builder.toString();
        }

        Text text = foDocumentFacade.createText(value);
        Element block = foDocumentFacade.createBlock();

        if (wrapInDivs) {
            block.setAttribute("absolute-position", "fixed");
            block.setAttribute("left", "0px");
            block.setAttribute("top", "0px");
            block.setAttribute("bottom", "0px");
            block.setAttribute("min-width", normalWidthPx + "px");

            if (maxSpannedWidthPx != Integer.MAX_VALUE) {
                block.setAttribute("max-width", maxSpannedWidthPx + "px");
            }

            block.setAttribute("overflow", "hidden");
            block.setAttribute("height", normalHeightPt + "pt");
            block.setAttribute("keep-together.within-line", "always");
            block.setAttribute("wrap-option", "no-wrap");
        }

        processCellStyle(workbook, cell.getCellStyle(), tableCellElement,
            block);

        block.appendChild(text);
        tableCellElement.appendChild(block);

        return isEmpty(value) && emptyStyle;
    }

    protected void processCellStyle(HSSFWorkbook workbook,
        HSSFCellStyle cellStyle, Element cellTarget, Element blockTarget) {
        blockTarget.setAttribute("white-space-collapse", "false");
        {
            String textAlign = getAlign(cellStyle.getAlignment());
            if (isNotEmpty(textAlign)) {
                blockTarget.setAttribute("text-align", textAlign);
            }
        }

        if (cellStyle.getFillPattern() == FillPatternType.NO_FILL) {
            // no fill
        } else if (cellStyle.getFillPattern() == FillPatternType.SOLID_FOREGROUND) {
            final HSSFColor foregroundColor = cellStyle
                .getFillForegroundColorColor();
            if (foregroundColor != null) {
                cellTarget.setAttribute("background-color",
                    getColor(foregroundColor));
            }
        } else {
            final HSSFColor backgroundColor = cellStyle
                .getFillBackgroundColorColor();
            if (backgroundColor != null) {
                cellTarget.setAttribute("background-color",
                    getColor(backgroundColor));
            }
        }

        processCellStyleBorder(workbook, cellTarget, "top",
            cellStyle.getBorderTop(), cellStyle.getTopBorderColor());
        processCellStyleBorder(workbook, cellTarget, "right",
            cellStyle.getBorderRight(), cellStyle.getRightBorderColor());
        processCellStyleBorder(workbook, cellTarget, "bottom",
            cellStyle.getBorderBottom(), cellStyle.getBottomBorderColor());
        processCellStyleBorder(workbook, cellTarget, "left",
            cellStyle.getBorderLeft(), cellStyle.getLeftBorderColor());

        HSSFFont font = cellStyle.getFont(workbook);
        processCellStyleFont(workbook, blockTarget, font);

    }

    protected void processCellStyleBorder(HSSFWorkbook workbook,
        Element cellTarget, String type, BorderStyle xlsBorder, short borderColor) {
        if (xlsBorder == BorderStyle.NONE) {
            return;
        }

        StringBuilder borderStyle = new StringBuilder();
        borderStyle.append(getBorderWidth(xlsBorder));

        final HSSFColor color = workbook.getCustomPalette().getColor(
            borderColor);
        if (color != null) {
            borderStyle.append(' ');
            borderStyle.append(getColor(color));

            borderStyle.append(' ');
            borderStyle.append(getBorderStyle(xlsBorder));
        }

        cellTarget.setAttribute("border-" + type, borderStyle.toString());
    }

    protected void processCellStyleFont(HSSFWorkbook workbook,
        Element blockTarget, HSSFFont font) {
        Triplet triplet = new Triplet();
        triplet.fontName = font.getFontName();
        triplet.bold = font.getBold();
        triplet.italic = font.getItalic();

        getFontReplacer().update(triplet);
        setBlockProperties(blockTarget, triplet);

        final HSSFColor fontColor = workbook.getCustomPalette().getColor(
            font.getColor());
        if (fontColor != null) {
            blockTarget.setAttribute("color",
                getColor(fontColor));
        }

        if (font.getFontHeightInPoints() != 0) {
            blockTarget.setAttribute("font-size", font.getFontHeightInPoints()
                + "pt");
        }

    }

    protected void processColumnHeaders(HSSFSheet sheet, int maxSheetColumns,
        Element table) {
        Element tableHeader = foDocumentFacade.createTableHeader();
        Element row = foDocumentFacade.createTableRow();

        if (isOutputRowNumbers()) {
            // empty cell at left-top corner
            final Element tableCellElement = foDocumentFacade.createTableCell();
            tableCellElement.appendChild(foDocumentFacade.createBlock());
            row.appendChild(tableCellElement);
        }

        for (int c = 0; c < maxSheetColumns; c++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(c)) {
                continue;
            }

            Element cell = foDocumentFacade.createTableCell();
            Element block = foDocumentFacade.createBlock();
            block.setAttribute("text-align", "center");
            block.setAttribute("font-weight", "bold");

            String text = getColumnName(c);
            block.appendChild(foDocumentFacade.createText(text));

            cell.appendChild(block);
            row.appendChild(cell);
        }

        tableHeader.appendChild(row);
        table.appendChild(tableHeader);
    }

    /**
     * Creates COLGROUP element with width specified for all columns. (Except
     * first if {@link #isOutputRowNumbers()}{@code ==true})
     *
     * @return table width in inches
     */
    protected float processColumnWidths(HSSFSheet sheet, int maxSheetColumns,
        Element table) {
        float tableWidth = 0;

        if (isOutputRowNumbers()) {
            final float columnWidthIn = getDefaultColumnWidth(sheet) / DPI;

            final Element rowNumberColumn = foDocumentFacade
                .createTableColumn();
            rowNumberColumn.setAttribute("column-width", columnWidthIn + "in");
            table.appendChild(rowNumberColumn);

            tableWidth += columnWidthIn;
        }

        for (int c = 0; c < maxSheetColumns; c++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(c)) {
                continue;
            }

            final float columnWidthIn = getColumnWidth(sheet, c) / DPI;

            Element col = foDocumentFacade.createTableColumn();
            col.setAttribute("column-width", columnWidthIn + "in");
            table.appendChild(col);

            tableWidth += columnWidthIn;
        }

        table.setAttribute("width", tableWidth + "in");
        return tableWidth;
    }

    protected void processDocumentInformation(
        SummaryInformation summaryInformation) {
        if (isNotEmpty(summaryInformation.getTitle())) {
            foDocumentFacade.setTitle(summaryInformation.getTitle());
        }

        if (isNotEmpty(summaryInformation.getAuthor())) {
            foDocumentFacade.setCreator(summaryInformation.getAuthor());
        }

        if (isNotEmpty(summaryInformation.getKeywords())) {
            foDocumentFacade.setKeywords(summaryInformation.getKeywords());
        }

        if (isNotEmpty(summaryInformation.getComments())) {
            foDocumentFacade.setDescription(summaryInformation.getComments());
        }
    }

    /**
     * @return maximum 1-base index of column that were rendered, zero if none
     */
    protected int processRow(HSSFWorkbook workbook,
        CellRangeAddress[][] mergedRanges, HSSFRow row,
        Element tableRowElement) {
        final HSSFSheet sheet = row.getSheet();
        final short maxColIx = row.getLastCellNum();
        if (maxColIx <= 0) {
            return 0;
        }

        final List<Element> emptyCells = new ArrayList<>(maxColIx);

        if (isOutputRowNumbers()) {
            Element tableRowNumberCellElement = processRowNumber(row);
            emptyCells.add(tableRowNumberCellElement);
        }

        int maxRenderedColumn = 0;
        for (int colIx = 0; colIx < maxColIx; colIx++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(colIx)) {
                continue;
            }

            CellRangeAddress range = getMergedRange(mergedRanges, row.getRowNum(), colIx);

            if (range != null
                && (range.getFirstColumn() != colIx || range.getFirstRow() != row
                .getRowNum())) {
                continue;
            }

            HSSFCell cell = row.getCell(colIx);

            // spanning using overlapping blocks
            int divWidthPx = 0;
            {
                divWidthPx = getColumnWidth(sheet, colIx);

                boolean hasBreaks = false;
                for (int nextColumnIndex = colIx + 1; nextColumnIndex < maxColIx; nextColumnIndex++) {
                    if (!isOutputHiddenColumns()
                        && sheet.isColumnHidden(nextColumnIndex)) {
                        continue;
                    }

                    if (row.getCell(nextColumnIndex) != null
                        && !isTextEmpty(row.getCell(nextColumnIndex))) {
                        hasBreaks = true;
                        break;
                    }

                    divWidthPx += getColumnWidth(sheet, nextColumnIndex);
                }

                if (!hasBreaks) {
                    divWidthPx = Integer.MAX_VALUE;
                }
            }

            Element tableCellElement = foDocumentFacade.createTableCell();

            if (range != null) {
                if (range.getFirstColumn() != range.getLastColumn()) {
                    tableCellElement.setAttribute(
                        "number-columns-spanned",
                        String.valueOf(range.getLastColumn()
                            - range.getFirstColumn() + 1));
                }
                if (range.getFirstRow() != range.getLastRow()) {
                    tableCellElement.setAttribute(
                        "number-rows-spanned",
                        String.valueOf(range.getLastRow()
                            - range.getFirstRow() + 1));
                }
            }

            boolean emptyCell;
            if (cell != null) {
                emptyCell = processCell(workbook, cell, tableCellElement,
                    getColumnWidth(sheet, colIx), divWidthPx,
                    row.getHeight() / 20f);
            } else {
                tableCellElement.appendChild(foDocumentFacade.createBlock());
                emptyCell = true;
            }

            if (emptyCell) {
                emptyCells.add(tableCellElement);
            } else {
                for (Element emptyCellElement : emptyCells) {
                    tableRowElement.appendChild(emptyCellElement);
                }
                emptyCells.clear();

                tableRowElement.appendChild(tableCellElement);
                maxRenderedColumn = colIx;
            }
        }

        return maxRenderedColumn + 1;
    }

    protected Element processRowNumber(HSSFRow row) {
        Element tableRowNumberCellElement = foDocumentFacade.createTableCell();

        Element block = foDocumentFacade.createBlock();
        block.setAttribute("text-align", "right");
        block.setAttribute("font-weight", "bold");

        Text text = foDocumentFacade.createText(getRowName(row));
        block.appendChild(text);

        tableRowNumberCellElement.appendChild(block);
        return tableRowNumberCellElement;
    }

    protected float processSheet(HSSFWorkbook workbook, HSSFSheet sheet,
        Element flow) {
        final int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
        if (physicalNumberOfRows <= 0) {
            return 0;
        }

        processSheetName(sheet, flow);

        Element table = foDocumentFacade.createTable();
        table.setAttribute("table-layout", "fixed");

        Element tableBody = foDocumentFacade.createTableBody();

        final CellRangeAddress[][] mergedRanges = buildMergedRangesMap(sheet);

        final List<Element> emptyRowElements = new ArrayList<>(
            physicalNumberOfRows);
        int maxSheetColumns = 1;
        for (int r = sheet.getFirstRowNum(); r <= sheet.getLastRowNum(); r++) {
            HSSFRow row = sheet.getRow(r);

            if (row == null) {
                continue;
            }

            if (!isOutputHiddenRows() && row.getZeroHeight()) {
                continue;
            }

            Element tableRowElement = foDocumentFacade.createTableRow();
            tableRowElement.setAttribute("height", row.getHeight() / 20f
                + "pt");

            int maxRowColumnNumber = processRow(workbook, mergedRanges, row,
                tableRowElement);

            if (tableRowElement.getChildNodes().getLength() == 0) {
                Element emptyCellElement = foDocumentFacade.createTableCell();
                emptyCellElement.appendChild(foDocumentFacade.createBlock());
                tableRowElement.appendChild(emptyCellElement);
            }

            if (maxRowColumnNumber == 0) {
                emptyRowElements.add(tableRowElement);
            } else {
                if (!emptyRowElements.isEmpty()) {
                    for (Element emptyRowElement : emptyRowElements) {
                        tableBody.appendChild(emptyRowElement);
                    }
                    emptyRowElements.clear();
                }

                tableBody.appendChild(tableRowElement);
            }
            maxSheetColumns = Math.max(maxSheetColumns, maxRowColumnNumber);
        }

        float tableWidthIn = processColumnWidths(sheet, maxSheetColumns, table);

        if (isOutputColumnHeaders()) {
            processColumnHeaders(sheet, maxSheetColumns, table);
        }

        table.appendChild(tableBody);
        flow.appendChild(table);

        return tableWidthIn;
    }

    /**
     * Process single sheet (as specified by 0-based sheet index)
     *
     * @return {@code true} if result were added to FO document, {@code false}
     * otherwise
     */
    protected boolean processSheet(HSSFWorkbook workbook, int sheetIndex) {
        String pageMasterName = "sheet-" + sheetIndex;

        Element pageSequence = foDocumentFacade
            .createPageSequence(pageMasterName);
        Element flow = foDocumentFacade.addFlowToPageSequence(pageSequence,
            "xsl-region-body");

        HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
        float tableWidthIn = processSheet(workbook, sheet, flow);

        if (tableWidthIn == 0) {
            return false;
        }

        createPageMaster(tableWidthIn, pageMasterName);
        foDocumentFacade.addPageSequence(pageSequence);
        return true;
    }

    protected void processSheetName(HSSFSheet sheet, Element flow) {
        Element titleBlock = foDocumentFacade.createBlock();

        Triplet triplet = new Triplet();
        triplet.bold = true;
        triplet.italic = false;
        triplet.fontName = "Arial";
        getFontReplacer().update(triplet);

        setBlockProperties(titleBlock, triplet);
        titleBlock.setAttribute("font-size", "200%");

        Element titleInline = foDocumentFacade.createInline();
        titleInline.appendChild(foDocumentFacade.createText(sheet
            .getSheetName()));
        titleBlock.appendChild(titleInline);
        flow.appendChild(titleBlock);

        Element titleBlock2 = foDocumentFacade.createBlock();
        Element titleInline2 = foDocumentFacade.createInline();
        titleBlock2.appendChild(titleInline2);
        flow.appendChild(titleBlock2);
    }

    public void processWorkbook(HSSFWorkbook workbook) {
        final SummaryInformation summaryInformation = workbook
            .getSummaryInformation();
        if (summaryInformation != null) {
            processDocumentInformation(summaryInformation);
        }

        for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
            processSheet(workbook, s);
        }
    }

    private void setBlockProperties(Element textBlock, Triplet triplet) {
        if (triplet.bold) {
            textBlock.setAttribute("font-weight", "bold");
        }

        if (triplet.italic) {
            textBlock.setAttribute("font-style", "italic");
        }

        if (isNotEmpty(triplet.fontName)) {
            textBlock.setAttribute("font-family", triplet.fontName);
        }
    }

    public void setPageMarginInches(float pageMarginInches) {
        this.pageMarginInches = pageMarginInches;
    }

}
