import re
from easyansi.common import field_validations as _validator


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."""

    # Source of CSI format: https://en.wikipedia.org/wiki/ANSI_escape_code
    #   CSI Starting Sequence = Esc + [
    #   CSI Parameter Bytes: 0–9 : ; < = > ?
    #   CSI Intermediate Bytes: [space] ! " # $ % & ' ( ) * + , - . /
    #   CSI Final Byte: A-Z a-z @ [ \ ] ^ _ ` { | } ~

    _validator.check_if_string(text, "Text to strip ANSI codes from")
    csi_regex = r'(\x1B\[)[0-?]*[ -\/]*[@-~]'
    csi_pattern = re.compile(csi_regex)  # compile csi regex pattern
    csi_less_text = csi_pattern.sub('', text)  # replace regex matches with empty string
    return csi_less_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))
