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

import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

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

    public static final Pattern NUMBER_WITH_DOT = Pattern.compile("^\\s*([1-9]{1,4})\\.\\s+");
    public static final Pattern NUMBER_IN_PARENTHESES = Pattern.compile("^\\s*\\(([1-9]{1,4})\\)\\s+");

    enum Format {
        NUMBER_WITH_DOT,
        NUMBER_IN_PARENTHESES
    }

    Format format;
    @Getter
    Word word;
    @Getter
    int page;
    int representation;


    public static Optional<ListIdentifier> parse(TextPageBlock textPageBlock, int page) {

        return parse(textPageBlock.getWords().subList(0, Math.min(5, textPageBlock.getWords().size())), page);
    }


    public static Optional<ListIdentifier> parse(List<Word> sequences, int page) {

        StringBuilder sb = new StringBuilder();
        for (Word sequence : sequences) {
            sb.append(sequence.toString());
            sb.append(" ");
        }
        sb.replace(sb.length() - 1, sb.length(), "");
        String text = sb.toString();

        Matcher numberMatcher = NUMBER_WITH_DOT.matcher(text);

        if (numberMatcher.find()) {
            Optional<Integer> representation = parseInteger(numberMatcher.group(1));
            if (representation.isPresent()) {
                return Optional.of(new ListIdentifier(Format.NUMBER_WITH_DOT, sequences.get(0), page, representation.get()));
            }
        }

        Matcher parenthesisMatcher = NUMBER_IN_PARENTHESES.matcher(text);
        if (parenthesisMatcher.find()) {
            Optional<Integer> representation = parseInteger(parenthesisMatcher.group(1));
            if (representation.isPresent()) {
                return Optional.of(new ListIdentifier(Format.NUMBER_IN_PARENTHESES, sequences.get(0), page, representation.get()));
            }
        }
        return Optional.empty();
    }


    private static Optional<Integer> parseInteger(String text) {

        try {
            return Optional.of(Integer.parseInt(text));
        } catch (NumberFormatException e) {
            return Optional.empty();
        }
    }


    public static boolean isInOrder(List<ListIdentifier> listIdentifiers) {

        if (listIdentifiers.size() <= 1) {
            return true;
        }

        for (int i = 1; i < listIdentifiers.size(); i++) {
            ListIdentifier current = listIdentifiers.get(i);
            ListIdentifier previous = listIdentifiers.get(i - 1);
            if (current.format != previous.format) {
                return false;
            }
            if (current.representation <= previous.representation) {
                return false;
            }
            if (!current.word.intersectsXDirAdj(previous.word, 2)) {
                return false;
            }
            if (current.page == previous.page && !current.word.isBelowDirAdj(previous.word)) {
                return false;
            }
            if (current.page < previous.page) {
                return false;
            }
        }
        return true;
    }

}
