import unicodedata
import re


def normalize(s):
    """
    Normalizes a string.

    This function does the following, in order:

    - Calls :func:`unicodedata.normalize("NFC", ...) \
      <unicodedata.normalize>`.
    - Normalizes line endings.
    - Expands horizontal tabs with a width of four columns.
    - Expands vertical tabs with a height of one row, and emulates
      carriage return.
    - Emulates backspace and delete.

    Parameters
    ----------
    s: :class:`str`
        The string to normalize.

    Returns
    -------
    :class:`str`
        The normalized string.

    Examples
    --------

    .. code:: python3

        >>> normalize("\\u0061\\u0301")  # \u0061\u0301
        "\\u00E1"

        >>> normalize("cool text\\vtext")
        "cool text\\r\\n         text"

        >>> normalize("text text\\rcool")
        "cool text"
    """

    s = unicodedata.normalize("NFC", s)

    s = s.replace("\r\n", "\n")
    s = s.replace("\f", "\n")

    s = s.expandtabs(4)

    if "\r" in s or "\v" in s:
        s = re.sub(r"\r|\v", "\f\\g<0>", s)

        lines = s.split("\n")
        for (i, line) in enumerate(lines):
            if "\f" in line:
                parts = line.split("\f")

                line = ""
                column = 0

                for part in parts:
                    if not part:
                        continue

                    code, part = part[0], part[1:]

                    if code == "\r":
                        try:
                            line, current_line = line.rsplit("\n", 1)
                            line += "\n"
                        except (ValueError) as e:
                            line, current_line = "", line

                        remaining = ""
                        for c in reversed(current_line):
                            if len(current_line) - (len(remaining) + len(part)) < len(c):
                                break

                            remaining = c + remaining

                        line += part + remaining
                        column = len(part)
                    elif code == "\v":
                        line += "\n" + " " * column + part
                        column += len(part)
                    else:
                        line += code + part
                        column = len(code + part)

                lines[i] = line

        s = "\n".join(lines)

    while "\b" in s or "\u007F" in s:
        s = re.sub(r".?((?:\u0008|\u007F)*)\u0008|\u007F((?:\u0008|\u007F)*).?", r"\1\2", s)

    s = s.replace("\n", "\r\n")

    return s