package com.knecon.fforesight.service.layoutparser.processor.services;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.springframework.core.io.ClassPathResource;

import com.knecon.fforesight.service.layoutparser.processor.model.PageContents;
import com.knecon.fforesight.service.layoutparser.processor.model.text.TextPositionSequence;
import com.knecon.fforesight.service.layoutparser.processor.services.parsing.PDFLinesTextStripper;
import com.knecon.fforesight.service.layoutparser.processor.utils.RectangleTransformations;

import lombok.experimental.UtilityClass;

@UtilityClass
public class PageContentExtractor {

    public List<PageContents> getSortedPageContents(String filename) throws IOException {

        List<PageContents> textPositionSequencesPerPage = new LinkedList<>();
        ClassPathResource pdfResource = new ClassPathResource(filename);

        try (PDDocument pdDocument = Loader.loadPDF(pdfResource.getFile())) {

            for (int pageNumber = 1; pageNumber < pdDocument.getNumberOfPages() + 1; pageNumber++) {

                PDFLinesTextStripper stripper = new PDFLinesTextStripper();
                PDPage pdPage = pdDocument.getPage(pageNumber - 1);
                stripper.setPageNumber(pageNumber);
                stripper.setSortByPosition(true);
                stripper.setStartPage(pageNumber);
                stripper.setEndPage(pageNumber);
                stripper.setPdpage(pdPage);
                stripper.getText(pdDocument);

                Map<Float, List<TextPositionSequence>> sortedTextPositionSequencesPerDir = stripper.getTextPositionSequences()
                        .stream()
                        .collect(Collectors.groupingBy(textPositionSequence -> textPositionSequence.getDir().getDegrees()));

                var sortedTextPositionSequences = sortByDirAccordingToPageRotation(sortedTextPositionSequencesPerDir, pdPage.getRotation());

                textPositionSequencesPerPage.add(new PageContents(sortedTextPositionSequences,
                        RectangleTransformations.toRectangle2D(pdPage.getCropBox()),
                        RectangleTransformations.toRectangle2D(pdPage.getMediaBox()),
                        stripper.getRulings()));
            }
        }
    
        return textPositionSequencesPerPage;
    }


    public List<TextPositionSequence> sortByDirAccordingToPageRotation(Map<Float, List<TextPositionSequence>> sortedTextPositionSequencesPerDir, int rotation) {

        LinkedList<Float> sortedKeys = new LinkedList<>(sortedTextPositionSequencesPerDir.keySet().stream().sorted().toList());

        for (int i = 0; i < sortedKeys.size(); i++) {
            if (sortedKeys.get(i) < rotation) {
                Float keyToSwap = sortedKeys.remove(i);
                sortedKeys.addLast(keyToSwap);
            }
        }
        return sortedKeys.stream().map(sortedTextPositionSequencesPerDir::get).flatMap(Collection::stream).toList();
    }

}
