package dev.fyloz.trial.colorrecipesexplorer.utils;

import dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.springframework.core.io.ResourceLoader;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

public class PdfBuilder {

    private PDFont font;
    private PDDocument document = new PDDocument();
    private PDPage page = new PDPage();
    private Collection<PdfLine> lines = new ArrayList<>();
    private boolean duplicated;
    private int fontSize;
    private int fontSizeBold;
    private int lineSpacing;

    public PdfBuilder(ResourceLoader resourceLoader, boolean duplicated, int fontSize) throws IOException {
        this.duplicated = duplicated;
        this.fontSize = fontSize;
        this.fontSizeBold = this.fontSize + 12;
        this.lineSpacing = (int) (this.fontSize * 1.5f);

        document.addPage(page);
        font = PDType0Font.load(document, resourceLoader.getResource(WebsitePaths.FONT_ARIAL_BOLD).getInputStream());
    }

    public PdfBuilder addLine(String text, boolean bold, int marginTop) {
        lines.add(new PdfLine(text, bold, marginTop));

        return this;
    }

    public byte[] build() throws IOException {
        writeContent();

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.save(outputStream);
        document.close();

        return outputStream.toByteArray();
    }

    private void writeContent() throws IOException {
        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        contentStream.beginText();

        int marginTop = 30;
        for (PdfLine line : lines) {
            writeCenteredText(contentStream, line, marginTop);
            marginTop += lineSpacing;
        }

        if (duplicated) {
            marginTop = (int) page.getMediaBox().getHeight() / 2;
            for (PdfLine line : lines) {
                writeCenteredText(contentStream, line, marginTop);
                marginTop += lineSpacing;
            }
        }

        contentStream.endText();
        contentStream.close();
    }

    private void writeCenteredText(PDPageContentStream contentStream, PdfLine line, int marginTop) throws IOException {
        float textWidth = font.getStringWidth(line.getText()) / 1000 * (line.isBold() ? fontSizeBold : fontSize);
        float textHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * (line.isBold() ? fontSizeBold : fontSize);
        float textX = (page.getMediaBox().getWidth() - textWidth) / 2f;
        float textY = (page.getMediaBox().getHeight() - (marginTop + line.getMarginTop()) - textHeight);

        if (line.isBold()) contentStream.setFont(font, fontSizeBold);
        else contentStream.setFont(font, fontSize);

        contentStream.newLineAtOffset(textX, textY);
        contentStream.showText(line.getText());
        contentStream.newLineAtOffset(-textX, -textY);  // Réinitialise la position pour la prochaine ligne
    }

    @Data
    @AllArgsConstructor
    public static class PdfLine {

        private String text;
        private boolean bold;
        private int marginTop;

    }

}
