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

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;

@AllArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class SectionIdentifier {

    static Pattern numericalIdentifierPattern = Pattern.compile("^[\\s]?(\\d+)[\\s.,;]?(\\d+)?[\\s.,;]?(\\d+)?[\\s.,;]?(\\d+)?");

    private enum Format {
        EMPTY,
        NUMERICAL,
        DOCUMENT
    }

    Format format;
    String identifierString;
    List<Integer> identifiers;
    boolean asChild;


    public static SectionIdentifier fromSearchText(String headline) {

        if (headline == null || headline.isEmpty() || headline.isBlank()) {
            return SectionIdentifier.empty();
        }

        Matcher numericalIdentifierMatcher = numericalIdentifierPattern.matcher(headline);
        if (numericalIdentifierMatcher.find()) {
            return buildNumericalSectionIdentifier(headline, numericalIdentifierMatcher);
        }
        // more formats here
        return SectionIdentifier.empty();
    }


    public static SectionIdentifier asChildOf(SectionIdentifier sectionIdentifier) {

        return new SectionIdentifier(sectionIdentifier.format, sectionIdentifier.toString(), sectionIdentifier.identifiers, true);
    }


    public static SectionIdentifier document() {

        return new SectionIdentifier(Format.DOCUMENT, "document", Collections.emptyList(), false);
    }


    public static SectionIdentifier empty() {

        return new SectionIdentifier(Format.EMPTY, "empty", Collections.emptyList(), false);
    }


    private static SectionIdentifier buildNumericalSectionIdentifier(String headline, Matcher numericalIdentifierMatcher) {

        String identifierString = headline.substring(numericalIdentifierMatcher.start(), numericalIdentifierMatcher.end());
        List<Integer> identifiers = new LinkedList<>();
        for (int i = 1; i <= 4; i++) {
            String numericalIdentifier = numericalIdentifierMatcher.group(i);
            if (numericalIdentifier == null || numericalIdentifier.equals("0") || numericalIdentifier.isEmpty() || numericalIdentifier.isBlank()) {
                break;
            }
            identifiers.add(Integer.parseInt(numericalIdentifier.trim()));
        }
        return new SectionIdentifier(Format.NUMERICAL, identifierString, identifiers.stream().toList(), false);
    }


    /**
     * Determines if the current section is the parent of the given section.
     *
     * @param sectionIdentifier The section identifier to compare against.
     * @return true if the current section is the parent of the given section, false otherwise.
     */
    public boolean isParentOf(SectionIdentifier sectionIdentifier) {

        if (this.format.equals(Format.EMPTY)) {
            return false;
        }
        if (this.format.equals(Format.DOCUMENT)) {
            return true;
        }
        if (!this.format.equals(sectionIdentifier.format)) {
            return false;
        }
        if (this.identifiers.size() >= sectionIdentifier.identifiers.size() && !(this.identifiers.size() == sectionIdentifier.identifiers.size() && sectionIdentifier.asChild)) {
            return false;
        }
        for (int i = 0; i < this.identifiers.size(); i++) {
            if (!this.identifiers.get(i).equals(sectionIdentifier.identifiers.get(i))) {
                return false;
            }
        }
        return true;
    }


    public boolean isChildOf(SectionIdentifier sectionIdentifier) {

        if (this.format.equals(Format.DOCUMENT) || this.format.equals(Format.EMPTY)) {
            return false;
        }
        return sectionIdentifier.isParentOf(this);
    }


    @Override
    public String toString() {

        return identifierString;
    }

}
