package org.jabref.logic.integrity;

import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.strings.StringUtil;

import org.jspecify.annotations.Nullable;

public class YearChecker implements ValueChecker {

    private static final Predicate<String> CONTAINS_FOUR_DIGIT = Pattern.compile("([^0-9]|^)[0-9]{4}([^0-9]|$)").asPredicate();
    private static final Predicate<String> ENDS_WITH_FOUR_DIGIT = Pattern.compile("[0-9]{4}$").asPredicate();
    private static final String PUNCTUATION_MARKS = "[(){},.;!?<>%&$]";

    /// Checks, if the number String contains a four digit year and ends with it.
    /// Official bibtex spec:
    /// Generally it should consist of four numerals, such as 1984, although the standard styles
    /// can handle any year whose last four nonpunctuation characters are numerals, such as ‘(about 1984)’.
    /// Source: http://ftp.fernuni-hagen.de/ftp-dir/pub/mirrors/www.ctan.org/biblio/bibtex/base/btxdoc.pdf
    @Override
    public Optional<String> checkValue(@Nullable String value) {
        if (StringUtil.isBlank(value)) {
            return Optional.empty();
        }

        if (!CONTAINS_FOUR_DIGIT.test(value.trim())) {
            return Optional.of(Localization.lang("should contain a four digit number"));
        }

        if (!ENDS_WITH_FOUR_DIGIT.test(value.replaceAll(PUNCTUATION_MARKS, ""))) {
            return Optional.of(Localization.lang("last four nonpunctuation characters should be numerals"));
        }

        return Optional.empty();
    }

    public static boolean isValueCorrectlyFormatted(String value) {
        if (StringUtil.isBlank(value)) {
            return false;
        }

        if (!CONTAINS_FOUR_DIGIT.test(value.trim())) {
            return false;
        }

        return ENDS_WITH_FOUR_DIGIT.test(value.replaceAll(PUNCTUATION_MARKS, ""));
    }
}
