# Copyright © 2012-2023 jrnl contributors
# License: https://www.gnu.org/licenses/gpl-3.0.html

import re
from string import punctuation
from string import whitespace
from typing import TYPE_CHECKING

import colorama

from jrnl.os_compat import on_windows

if TYPE_CHECKING:
    from jrnl.journals import Entry

if on_windows():
    colorama.init()


def colorize(string: str, color: str, bold: bool = False) -> str:
    """Returns the string colored with colorama.Fore.color. If the color set by
    the user is "NONE" or the color doesn't exist in the colorama.Fore attributes,
    it returns the string without any modification."""
    color_escape = getattr(colorama.Fore, color.upper(), None)
    if not color_escape:
        return string
    elif not bold:
        return color_escape + string + colorama.Fore.RESET
    else:
        return colorama.Style.BRIGHT + color_escape + string + colorama.Style.RESET_ALL


def highlight_tags_with_background_color(
    entry: "Entry", text: str, color: str, is_title: bool = False
) -> str:
    """
    Takes a string and colorizes the tags in it based upon the config value for
    color.tags, while colorizing the rest of the text based on `color`.
    :param entry: Entry object, for access to journal config
    :param text: Text to be colorized
    :param color: Color for non-tag text, passed to colorize()
    :param is_title: Boolean flag indicating if the text is a title or not
    :return: Colorized str
    """

    def colorized_text_generator(fragments):
        """Efficiently generate colorized tags / text from text fragments.
        Taken from @shobrook. Thanks, buddy :)
        :param fragments: List of strings representing parts of entry (tag or word).
        :rtype: List of tuples
        :returns [(colorized_str, original_str)]"""
        for part in fragments:
            if part and part[0] not in config["tagsymbols"]:
                yield colorize(part, color, bold=is_title), part
            elif part:
                yield colorize(part, config["colors"]["tags"], bold=True), part

    config = entry.journal.config
    if config["highlight"]:  # highlight tags
        text_fragments = re.split(entry.tag_regex(config["tagsymbols"]), text)

        # Colorizing tags inside of other blocks of text
        final_text = ""
        previous_piece = ""
        for colorized_piece, piece in colorized_text_generator(text_fragments):
            # If this piece is entirely punctuation or whitespace or the start
            # of a line or the previous piece was a tag or this piece is a tag,
            # then add it to the final text without a leading space.
            if (
                all(char in punctuation + whitespace for char in piece)
                or previous_piece.endswith("\n")
                or (previous_piece and previous_piece[0] in config["tagsymbols"])
                or piece[0] in config["tagsymbols"]
            ):
                final_text += colorized_piece
            else:
                # Otherwise add a leading space and then append the piece.
                final_text += " " + colorized_piece

            previous_piece = piece
        return final_text.lstrip()
    else:
        return text
