import re
import string

from ...library import Library
from ..middleware import LibraryMiddleware


class ProtectTitleWithBracket(LibraryMiddleware):
    def __init__(self, allow_inplace_modification: bool = True):
        super().__init__(allow_inplace_modification=allow_inplace_modification)

    # docstr-coverage: inherited
    def transform(self, library: Library) -> Library:
        library = super().transform(library)
        for entry in library.entries:
            if "title" in entry:
                entry["title"] = process_sentence_refined(entry["title"])
        return library

    # docstr-coverage: inherited
    @classmethod
    def metadata_key(cls) -> str:
        return "protect_title_with_bracket"


def wrap_if_internal_capital_with_punctuation(word):
    if not isinstance(word, str) or len(word) <= 1:
        return word

    ll = len(word.lstrip(string.punctuation))
    trailing_punct_l = word[: (len(word) - ll)]

    rr = len(word.rstrip(string.punctuation))
    trailing_punct_r = word[rr:]

    word_stripped = word.strip(string.punctuation)
    rest = word_stripped[1:]

    # {{A -> {{{{A}}
    # MCMC -> {{MCMC}}
    # Carlo}} -> {{Carlo}}}}
    flag = len(word_stripped) <= 1
    flag = flag or (any(c.isupper() for c in rest) and word.count("{") == 0 and word.count("}") == 0)
    flag = flag or word.count("{") != word.count("}")

    if flag:
        return trailing_punct_l + "{{" + word_stripped + "}}" + trailing_punct_r

    return word


def process_sentence_refined(sentence):
    words = sentence.split()
    processed_words = []

    for word in words:
        processed_word = wrap_if_internal_capital_with_punctuation(word)
        processed_word = re.sub(r"\{{2,}", "{{", processed_word)
        processed_word = re.sub(r"\}{2,}", "}}", processed_word)
        processed_words.append(processed_word)

    sentence = " ".join(processed_words)
    sentence = re.sub("}} {{", " ", sentence)
    return sentence
