import re
import unicodedata

def is_accented(word: str):
    """Returns True if the word has an accent (also detects if the word has a grave accent"""
    return unaccentify(word) != word

def is_acute_accented(phrase: str):
    """Returns True if the phrase has an acute accent"""
    return '\u0301' in phrase

def has_only_one_syllable(word: str):
    """Returns True if the word has only one syllable ( == at most one vowel)
    Accepts only one word without spaces"""
    assert " " not in word

    word_lower = word.lower()
    vowels = 0
    for char in word_lower:
        if char in "аоэуыяеёюи":
            vowels += 1
    return vowels <= 1

def has_acute_accent_or_only_one_syllable(word: str):
    """Returns True if the word (probably) has been stressed or does not need to be stressed:
    This is the case if it has an acute accent or only one syllable"""
    return is_acute_accented(word) or has_only_one_syllable(word)

# Unaccentifier written by Roman Susi
# Taken from https://stackoverflow.com/questions/35942129/remove-accent-marks-from-characters-while-preserving-other-diacritics
ACCENT_MAPPING = {
    '́': '',
    '̀': '',
    'а́': 'а',
    'а̀': 'а',
    'е́': 'е',
    'ѐ': 'е',
    'и́': 'и',
    'ѝ': 'и',
    'о́': 'о',
    'о̀': 'о',
    'у́': 'у',
    'у̀': 'у',
    'ы́': 'ы',
    'ы̀': 'ы',
    'э́': 'э',
    'э̀': 'э',
    'ю́': 'ю',
    '̀ю': 'ю',
    'я́́': 'я',
    'я̀': 'я',
}

ACCENT_MAPPING = {unicodedata.normalize(
    'NFKC', i): j for i, j in ACCENT_MAPPING.items()}


def unaccentify(s):
    source = unicodedata.normalize('NFKC', s)
    for old, new in ACCENT_MAPPING.items():
        source = source.replace(old, new)
    return source

def remove_accent_if_only_one_syllable(s: str):
    """Removes the accent from words like что́, which are usually not set in texts.
    Also works with complete texts (splits by space)"""
    if " " in s:
        words = s.split(" ")
        fixed_words = []
        for word in words:
            fixed_words.append(remove_accent_if_only_one_syllable(word))
        return " ".join(fixed_words)

    s_unaccented = unaccentify(s)
    if has_only_one_syllable(s_unaccented):
        return s_unaccented
    else:
        return s

def has_cyrillic_letters(s: str):
    """Returns True if the string has at least one Cyrillic letter"""
    m = re.findall(r'[А-я]+', s)
    return m != []

def convert_ap_accent_to_real(word: str) -> str:
    """This replaces the accents marked with apostrophes with a real acute accent"""
    return word.replace("'", "\u0301")

def remove_apostrophes(word: str) -> str:
    """Removes apostrophes from words like удар'ения"""
    return word.replace("'", "")

def remove_yo(word: str) -> str:
    """This replaces ё with the letter е (also works for upper case)"""
    return word.replace("ё", "е").replace("Ё", "Е")