"""Theme intended to be used on a white background.

There exists already a Pygments theme called 'friendly';
I thought that using the French translation 'amical' for the name of
theme would be appropriate.
"""

from pygments.style import Style
from pygments.token import (
    Keyword,
    Name,
    Comment,
    String,
    Error,
    Text,
    Number,
    Operator,
    Generic,
    Whitespace,
    Punctuation,
    Other,
    Literal,
)


colours = {
    "yellow": "#F0E68C",
    "orange": "#CC4400",
    "red": "#DD0000",
    "white": "#FFFFFF",
    "brown": "#783114",
    "blue": "#266290",
    "blue2": "#0011AA",
    "purple": "#8b008b",
    "gray": "#808080",
    "green": "#005500",
    "mauve": "#9370DB",
    "black": "#101010",
}

my_style = {
    "builtins": colours["green"],
    "code": colours["blue2"],
    "comments": colours["gray"],
    "keywords": colours["green"],
    "numbers": colours["black"],
    "operators": colours["brown"],
    "string": colours["purple"],
    "text": colours["black"],
    "TrueFalseNone": colours["blue"],
    "Exception": colours["red"],
    "diagnostics": "#FF00FF",  # Magenta; when trying to figure out a category
}


# Since we use Rich's pretty(), we try to ensure that the colours
# are consistent.  pretty() highlight objects based on their repr name
# with the following choices:

rich_style = {
    "markdown.code": my_style["code"],
    "repr.tag_name": my_style["code"],  # for consistency with Python
    "markdown.h1": my_style["diagnostics"],
    # Exception message; location header H2
    "markdown.h2": my_style["Exception"],
    "markdown.h3": colours["mauve"],  # likely cause
    "markdown.h4": colours["orange"],  # warning header
    "markdown.link": f"underline {my_style['keywords']}",
    "repr.url": my_style["keywords"],
    "repr.number": my_style["numbers"],
    # The next three are identical for pygments, so we keep them identical
    "repr.bool_false": my_style["TrueFalseNone"],
    "repr.bool_true": my_style["TrueFalseNone"],
    "repr.none": my_style["TrueFalseNone"],
    #
    "repr.str": my_style["string"],
    "repr.error": my_style["Exception"],
    "repr.indent": my_style["comments"],
    "repr.attrib_name": my_style["builtins"],
    "repr.attrib_value": my_style["code"],
    "repr.attrib_equal": my_style["operators"],
    "repr.call": my_style["code"],
}

my_style.update(**rich_style)
BACKGROUND = colours["white"]


class AmicalStyle(Style):

    background_color = BACKGROUND
    default_style = "#363636"

    styles = {
        Text: my_style["text"],  # class:  ''
        Whitespace: "",  # class: 'w'
        Error: my_style["Exception"],  # class: 'err'
        Other: my_style["string"],  # class 'x'
        #
        Comment: my_style["comments"],  # class: 'c'
        Comment.Multiline: my_style["comments"],  # class: 'cm'
        Comment.Preproc: my_style["comments"],  # class: 'cp'
        Comment.Single: my_style["comments"],  # class: 'c1'
        Comment.Special: my_style["comments"],  # class: 'cs'
        #
        Generic: my_style["text"],  # class: 'g'
        Generic.Deleted: my_style["Exception"],  # class: 'gd'
        Generic.Emph: my_style["text"],  # class: 'ge'
        Generic.Error: my_style["Exception"],  # class: 'gr'
        Generic.Heading: my_style["text"],  # class: 'gh'
        Generic.Inserted: my_style["text"],  # class: 'gi'
        Generic.Output: my_style["text"],  # class: 'go'
        Generic.Prompt: my_style["keywords"],  # class: 'gp'
        Generic.Strong: my_style["text"],  # class: 'gs'
        Generic.Subheading: my_style["text"],  # class: 'gu'
        Generic.Traceback: my_style["Exception"],  # class: 'gt'
        #
        Keyword: my_style["keywords"],  # class: 'k'
        Keyword.Constant: my_style["TrueFalseNone"],  # class: 'kc'
        Keyword.Declaration: my_style["keywords"],  # class: 'kd'
        Keyword.Namespace: my_style["keywords"],  # class: 'kn'
        Keyword.Pseudo: my_style["keywords"],  # class: 'kp'
        Keyword.Reserved: my_style["keywords"],  # class: 'kr'
        Keyword.Type: my_style["keywords"],  # class: 'kt'
        #
        Literal: my_style["text"],  # class: 'l'
        Literal.Date: my_style["text"],  # class: 'ld'
        #
        Name: my_style["code"],  # class: 'n'
        Name.Attribute: my_style["code"],  # class: 'na'
        # The following is for file path in tracebacks and Python builtins.
        Name.Builtin: my_style["builtins"],  # class: 'nb'
        Name.Builtin.Pseudo: my_style["builtins"],  # class: 'bp'
        Name.Class: my_style["code"],  # class: 'nc'
        Name.Constant: my_style["code"],  # class: 'no'
        Name.Decorator: my_style["code"],  # class: 'nd'
        Name.Entity: my_style["code"],  # class: 'ni'
        Name.Exception: my_style["Exception"],  # class: 'ne'
        Name.Function: my_style["code"],  # class: 'nf'
        Name.Property: my_style["code"],  # class: 'py'
        Name.Label: my_style["code"],  # class: 'nl'
        Name.Namespace: my_style["code"],  # class: 'nn'
        Name.Other: my_style["diagnostics"],  # class: 'nx'
        Name.Tag: my_style["code"],  # class: 'nt' - like a keyword
        Name.Variable: my_style["text"],  # class: 'nv'
        Name.Variable.Class: my_style["code"],  # class: 'vc'
        Name.Variable.Global: my_style["code"],  # class: 'vg'
        Name.Variable.Instance: my_style["text"],  # class: 'vi'
        #
        Number: my_style["numbers"],  # class: 'm'
        Number.Float: my_style["numbers"],  # class: 'mf'
        Number.Hex: my_style["numbers"],  # class: 'mh'
        Number.Integer: my_style["numbers"],  # class: 'mi'
        Number.Integer.Long: my_style["numbers"],  # class: 'il'
        Number.Oct: my_style["numbers"],  # class: 'mo'
        #
        Operator: my_style["operators"],  # class: 'o'
        Operator.Word: my_style["keywords"],  # class: 'ow'
        #
        Punctuation: my_style["operators"],  # class: 'p'
        #
        String: my_style["string"],  # class: 's'
        String.Backtick: my_style["string"],  # class: 'sb'
        String.Char: my_style["string"],  # class: 'sc'
        String.Doc: my_style["string"],  # class: 'sd'
        String.Double: my_style["string"],  # class: 's2'
        String.Escape: my_style["string"],  # class: 'se'
        String.Heredoc: my_style["string"],  # class: 'sh'
        String.Interpol: my_style["string"],  # class: 'si'
        String.Other: my_style["string"],  # class: 'sx'
        String.Regex: my_style["string"],  # class: 'sr'
        String.Single: my_style["string"],  # class: 's1'
        String.Symbol: my_style["string"],  # class: 'ss'
    }
