package com.knecon.fforesight.service.viewerdoc.service;

import java.util.Set;

import com.knecon.fforesight.service.viewerdoc.model.MarkedContentStack;
import com.pdftron.pdf.Element;
import com.pdftron.pdf.ElementBuilder;
import com.pdftron.pdf.ElementReader;
import com.pdftron.pdf.ElementWriter;
import com.pdftron.pdf.Page;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.SneakyThrows;
import lombok.experimental.FieldDefaults;

@Builder
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class PageContentCleaner {

    ElementWriter writer;
    ElementReader reader;
    ElementBuilder elementBuilder;
    Set<String> markedContentToRemove;

    @Builder.Default
    MarkedContentStack markedContentStack = new MarkedContentStack();


    @SneakyThrows
    public void removeMarkedContent(Page page) {

        begin(page);
        copyElementsExceptMarkedContentToRemove();
        end();
    }


    @SneakyThrows
    private void begin(Page page) {

        writer.begin(page, ElementWriter.e_replacement, false, true, page.getResourceDict());
        reader.begin(page);
    }


    @SneakyThrows
    private void end() {

        writer.end();
        reader.end();
    }


    @SneakyThrows
    private void copyElementsExceptMarkedContentToRemove() {

        for (Element element = reader.next(); element != null; element = reader.next()) {
            switch (element.getType()) {
                case Element.e_marked_content_begin -> {
                    markedContentStack.enterMarkedContent(element.getMCTag().getName());
                    if (markedContentStack.currentMarkedContentContainsNone(markedContentToRemove)) {
                        writer.writeElement(element);
                    }
                }
                case Element.e_marked_content_end -> {
                    if (markedContentStack.currentMarkedContentContainsNone(markedContentToRemove)) {
                        writer.writeElement(element);
                    }
                    markedContentStack.leaveMarkedContent();
                }
                default -> {
                    if (markedContentStack.currentMarkedContentContainsNone(markedContentToRemove)) {
                        writer.writeElement(element);
                    }
                }
            }

        }

    }

}
