from easyansi.common import field_validations as _validator
from easyansi.common import regex_patterns as _regex_patterns


def prnt(text: str) -> None:
    """This is a wrapper around print which forces a buffer flush and does not output a newline.

    Parameters:
        text: The text to print."""
    print(text, flush=True, end='')


def prntln(text: str = '') -> None:
    """This is a wrapper around print which forces a buffer flush and does output a newline.

    Parameters:
        text: The text to print."""
    print(text, flush=True)


def strip_ansi_codes(text: str) -> str:
    """Given a text string, remove all ANSI sequences and return the plain text.

    This is only guaranteed to remove ANSI codes generated by Easy ANSI, though the following should also work:
    * Any ANSI CSI sequence.

    Parameters:
        text: The text to strip ANSI codes out of."""

    # Order of these checks is important
    _validator.check_if_string(text, "Text to strip ANSI codes from")
    stripped_text = text
    stripped_text = _regex_patterns.ALL_CSI_PATTERN.sub('', stripped_text)  # replace regex matches with empty string
    # OSC Title Code
    osc_title_match = _regex_patterns.OSC_TITLE_PATTERN.match(stripped_text)
    if osc_title_match is not None:
        stripped_text = osc_title_match.group(1) + osc_title_match.group(3) + osc_title_match.group(5)
    # A Lone BELL Code
    stripped_text = _regex_patterns.BELL_PATTERN.sub('', stripped_text)
    return stripped_text


def text_len(text: str) -> int:
    """Given a text string, return the length of the text without the ANSI characters.

    Parameters:
        text: The text to calculate the length from."""
    return len(strip_ansi_codes(text))
