"""
Utility functions for working with the color names and color value
formats defined by the HTML and CSS specifications for use in
documents on the Web.

See documentation (in docs/ directory of source distribution) for
details of the supported formats, conventions and conversions.

"""
from .config import (
    CSS2,
    CSS2_HEX_TO_NAMES,
    CSS2_NAMES_TO_HEX,
    CSS3,
    CSS3_HEX_TO_NAMES,
    CSS3_NAMES_TO_HEX,
    CSS21,
    CSS21_HEX_TO_NAMES,
    CSS21_NAMES_TO_HEX,
    HTML4,
    HTML4_HEX_TO_NAMES,
    HTML4_NAMES_TO_HEX,
    SPECIFICATION_ERROR_TEMPLATE,
    SUPPORTED_SPECIFICATIONS,
    DistanceFunction,
    IntegerRGB,
    IntTuple,
    PercentRGB,
    PercentTuple,
)
from .normalisation_functions import (
    normalize_hex,
    normalize_integer_triplet,
    normalize_percent_triplet,
)


def _get_closest(rgb_triplet: IntegerRGB, spec: str, f: DistanceFunction) -> str:
    """
    Internal utility for calculating the closest normalised color
    name based on a function f; given an rgb_triplet, returns the
    closest normalised color name.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))

    name = {
        CSS2: CSS2_HEX_TO_NAMES,
        CSS21: CSS21_HEX_TO_NAMES,
        CSS3: CSS3_HEX_TO_NAMES,
        HTML4: HTML4_HEX_TO_NAMES,
    }[spec]
    distances = {}

    for k, v in name.items():
        distances[f(rgb_triplet, hex_to_rgb(k))] = v

    return distances[min(distances.keys())]


# Conversions from color names to various formats.
#################################################################


def name_to_hex(name: str, spec: str = CSS3) -> str:
    """
    Convert a color name to a normalized hexadecimal color value.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    When no color of that name exists in the given specification,
    ``ValueError`` is raised.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
    normalized = name.lower()
    hex_value = {
        CSS2: CSS2_NAMES_TO_HEX,
        CSS21: CSS21_NAMES_TO_HEX,
        CSS3: CSS3_NAMES_TO_HEX,
        HTML4: HTML4_NAMES_TO_HEX,
    }[spec].get(normalized)
    if hex_value is None:
        raise ValueError(
            "'{name}' is not defined as a named color in {spec}".format(
                name=name, spec=spec
            )
        )
    return hex_value


def name_to_rgb(name: str, spec: str = CSS3) -> IntegerRGB:
    """
    Convert a color name to a 3-tuple of integers suitable for use in
    an ``rgb()`` triplet specifying that color.

    """
    return hex_to_rgb(name_to_hex(name, spec=spec))


def name_to_rgb_percent(name: str, spec: str = CSS3) -> PercentRGB:
    """
    Convert a color name to a 3-tuple of percentages suitable for use
    in an ``rgb()`` triplet specifying that color.

    """
    return rgb_to_rgb_percent(name_to_rgb(name, spec=spec))


# Conversions from hexadecimal color values to various formats.
#################################################################


def hex_to_name(hex_value: str, spec: str = CSS3) -> str:
    """
    Convert a hexadecimal color value to its corresponding normalized
    color name, if any such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    When no color name for the value is found in the given
    specification, ``ValueError`` is raised.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
    normalized = normalize_hex(hex_value)
    name = {
        CSS2: CSS2_HEX_TO_NAMES,
        CSS21: CSS21_HEX_TO_NAMES,
        CSS3: CSS3_HEX_TO_NAMES,
        HTML4: HTML4_HEX_TO_NAMES,
    }[spec].get(normalized)
    if name is None:
        raise ValueError("'{}' has no defined color name in {}".format(hex_value, spec))
    return name


def hex_to_name_closest(
    hex_value: str,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a hexadecimal color value to its corresponding normalized
    color name. If no such name exists, return the normalized color
    name corresponding to the closest hex_value, calculated based on
    a function f whose default is squared error (mean has no effect
    in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = hex_to_name(hex_value, spec)
    except ValueError:
        closest = _get_closest(hex_to_rgb(hex_value), spec, f)
    return closest


def hex_to_rgb(hex_value: str) -> IntegerRGB:
    """
    Convert a hexadecimal color value to a 3-tuple of integers
    suitable for use in an ``rgb()`` triplet specifying that color.

    """
    int_value = int(normalize_hex(hex_value)[1:], 16)
    return IntegerRGB(int_value >> 16, int_value >> 8 & 0xFF, int_value & 0xFF)


def hex_to_rgb_percent(hex_value: str) -> PercentRGB:
    """
    Convert a hexadecimal color value to a 3-tuple of percentages
    suitable for use in an ``rgb()`` triplet representing that color.

    """
    return rgb_to_rgb_percent(hex_to_rgb(hex_value))


# Conversions from  integer rgb() triplets to various formats.
#################################################################


def rgb_to_name(rgb_triplet: IntTuple, spec: str = CSS3) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name, if any
    such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    If there is no matching name, ``ValueError`` is raised.

    """
    return hex_to_name(rgb_to_hex(normalize_integer_triplet(rgb_triplet)), spec=spec)


def rgb_to_name_closest(
    rgb_triplet: IntTuple,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name. If no
    such name exists, return the normalized color name corresponding
    to the closest rgb triplet, calculated based on a function f
    whose default is squared error (mean has no effect in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = rgb_to_name(rgb_triplet, spec)
    except ValueError:
        closest = _get_closest(rgb_triplet, spec, f)
    return closest


def rgb_to_hex(rgb_triplet: IntTuple) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to a normalized hexadecimal value for that color.

    """
    return "#{:02x}{:02x}{:02x}".format(*normalize_integer_triplet(rgb_triplet))


def rgb_to_rgb_percent(rgb_triplet: IntTuple) -> PercentRGB:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to a 3-tuple of percentages suitable for use in
    representing that color.

    This function makes some trade-offs in terms of the accuracy of
    the final representation; for some common integer values,
    special-case logic is used to ensure a precise result (e.g.,
    integer 128 will always convert to '50%', integer 32 will always
    convert to '12.5%'), but for all other values a standard Python
    ``float`` is used and rounded to two decimal places, which may
    result in a loss of precision for some values.

    """
    # In order to maintain precision for common values,
    # special-case them.
    specials = {
        255: "100%",
        128: "50%",
        64: "25%",
        32: "12.5%",
        16: "6.25%",
        0: "0%",
    }
    return PercentRGB._make(
        specials.get(d, "{:.02f}%".format(d / 255.0 * 100))
        for d in normalize_integer_triplet(rgb_triplet)
    )


# Conversions from percentage rgb() triplets to various formats.
#################################################################


def rgb_percent_to_name(rgb_percent_triplet: PercentTuple, spec: str = CSS3) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name, if any
    such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    If there is no matching name, ``ValueError`` is raised.

    """
    return rgb_to_name(
        rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet)), spec=spec
    )


def rgb_percent_to_name_closest(
    rgb_percent_triplet: PercentTuple,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name. If no
    such name exists, return the normalized color name corresponding
    to the closest rgb_percent_triplet, calculated based on a function
    f whose default is squared error (mean has no effect in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = rgb_percent_to_name(rgb_percent_triplet, spec)
    except ValueError:
        closest = _get_closest(rgb_percent_to_rgb(rgb_percent_triplet), spec, f)
    return closest


def rgb_percent_to_hex(rgb_percent_triplet: PercentTuple) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to a normalized hexadecimal color value for that
    color.

    """
    return rgb_to_hex(
        rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet))
    )


def _percent_to_integer(percent: str) -> int:
    """
    Internal helper for converting a percentage value to an integer
    between 0 and 255 inclusive.

    """
    return int(round(float(percent.split("%")[0]) / 100 * 255))


def rgb_percent_to_rgb(rgb_percent_triplet: PercentTuple) -> IntegerRGB:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to a 3-tuple of integers suitable for use in
    representing that color.

    Some precision may be lost in this conversion. See the note
    regarding precision for ``rgb_to_rgb_percent()`` for details.

    """
    return IntegerRGB._make(
        map(_percent_to_integer, normalize_percent_triplet(rgb_percent_triplet))
    )

"""
Utility functions for working with the color names and color value
formats defined by the HTML and CSS specifications for use in
documents on the Web.

See documentation (in docs/ directory of source distribution) for
details of the supported formats, conventions and conversions.

"""
from .config import (
    CSS2,
    CSS2_HEX_TO_NAMES,
    CSS2_NAMES_TO_HEX,
    CSS3,
    CSS3_HEX_TO_NAMES,
    CSS3_NAMES_TO_HEX,
    CSS21,
    CSS21_HEX_TO_NAMES,
    CSS21_NAMES_TO_HEX,
    HTML4,
    HTML4_HEX_TO_NAMES,
    HTML4_NAMES_TO_HEX,
    SPECIFICATION_ERROR_TEMPLATE,
    SUPPORTED_SPECIFICATIONS,
    DistanceFunction,
    IntegerRGB,
    IntTuple,
    PercentRGB,
    PercentTuple,
)
from .normalisation_functions import (
    normalize_hex,
    normalize_integer_triplet,
    normalize_percent_triplet,
)


def _get_closest(rgb_triplet: IntegerRGB, spec: str, f: DistanceFunction) -> str:
    """
    Internal utility for calculating the closest normalised color
    name based on a function f; given an rgb_triplet, returns the
    closest normalised color name.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))

    name = {
        CSS2: CSS2_HEX_TO_NAMES,
        CSS21: CSS21_HEX_TO_NAMES,
        CSS3: CSS3_HEX_TO_NAMES,
        HTML4: HTML4_HEX_TO_NAMES,
    }[spec]
    distances = {}

    for k, v in name.items():
        distances[f(rgb_triplet, hex_to_rgb(k))] = v

    return distances[min(distances.keys())]


# Conversions from color names to various formats.
#################################################################


def name_to_hex(name: str, spec: str = CSS3) -> str:
    """
    Convert a color name to a normalized hexadecimal color value.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    When no color of that name exists in the given specification,
    ``ValueError`` is raised.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
    normalized = name.lower()
    hex_value = {
        CSS2: CSS2_NAMES_TO_HEX,
        CSS21: CSS21_NAMES_TO_HEX,
        CSS3: CSS3_NAMES_TO_HEX,
        HTML4: HTML4_NAMES_TO_HEX,
    }[spec].get(normalized)
    if hex_value is None:
        raise ValueError(
            "'{name}' is not defined as a named color in {spec}".format(
                name=name, spec=spec
            )
        )
    return hex_value


def name_to_rgb(name: str, spec: str = CSS3) -> IntegerRGB:
    """
    Convert a color name to a 3-tuple of integers suitable for use in
    an ``rgb()`` triplet specifying that color.

    """
    return hex_to_rgb(name_to_hex(name, spec=spec))


def name_to_rgb_percent(name: str, spec: str = CSS3) -> PercentRGB:
    """
    Convert a color name to a 3-tuple of percentages suitable for use
    in an ``rgb()`` triplet specifying that color.

    """
    return rgb_to_rgb_percent(name_to_rgb(name, spec=spec))


# Conversions from hexadecimal color values to various formats.
#################################################################


def hex_to_name(hex_value: str, spec: str = CSS3) -> str:
    """
    Convert a hexadecimal color value to its corresponding normalized
    color name, if any such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    When no color name for the value is found in the given
    specification, ``ValueError`` is raised.

    """
    if spec not in SUPPORTED_SPECIFICATIONS:
        raise ValueError(SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
    normalized = normalize_hex(hex_value)
    name = {
        CSS2: CSS2_HEX_TO_NAMES,
        CSS21: CSS21_HEX_TO_NAMES,
        CSS3: CSS3_HEX_TO_NAMES,
        HTML4: HTML4_HEX_TO_NAMES,
    }[spec].get(normalized)
    if name is None:
        raise ValueError("'{}' has no defined color name in {}".format(hex_value, spec))
    return name


def hex_to_name_closest(
    hex_value: str,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a hexadecimal color value to its corresponding normalized
    color name. If no such name exists, return the normalized color
    name corresponding to the closest hex_value, calculated based on
    a function f whose default is squared error (mean has no effect
    in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = hex_to_name(hex_value, spec)
    except ValueError:
        closest = _get_closest(hex_to_rgb(hex_value), spec, f)
    return closest


def hex_to_rgb(hex_value: str) -> IntegerRGB:
    """
    Convert a hexadecimal color value to a 3-tuple of integers
    suitable for use in an ``rgb()`` triplet specifying that color.

    """
    int_value = int(normalize_hex(hex_value)[1:], 16)
    return IntegerRGB(int_value >> 16, int_value >> 8 & 0xFF, int_value & 0xFF)


def hex_to_rgb_percent(hex_value: str) -> PercentRGB:
    """
    Convert a hexadecimal color value to a 3-tuple of percentages
    suitable for use in an ``rgb()`` triplet representing that color.

    """
    return rgb_to_rgb_percent(hex_to_rgb(hex_value))


# Conversions from  integer rgb() triplets to various formats.
#################################################################


def rgb_to_name(rgb_triplet: IntTuple, spec: str = CSS3) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name, if any
    such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    If there is no matching name, ``ValueError`` is raised.

    """
    return hex_to_name(rgb_to_hex(normalize_integer_triplet(rgb_triplet)), spec=spec)


def rgb_to_name_closest(
    rgb_triplet: IntTuple,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name. If no
    such name exists, return the normalized color name corresponding
    to the closest rgb triplet, calculated based on a function f
    whose default is squared error (mean has no effect in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = rgb_to_name(rgb_triplet, spec)
    except ValueError:
        closest = _get_closest(rgb_triplet, spec, f)
    return closest


def rgb_to_hex(rgb_triplet: IntTuple) -> str:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to a normalized hexadecimal value for that color.

    """
    return "#{:02x}{:02x}{:02x}".format(*normalize_integer_triplet(rgb_triplet))


def rgb_to_rgb_percent(rgb_triplet: IntTuple) -> PercentRGB:
    """
    Convert a 3-tuple of integers, suitable for use in an ``rgb()``
    color triplet, to a 3-tuple of percentages suitable for use in
    representing that color.

    This function makes some trade-offs in terms of the accuracy of
    the final representation; for some common integer values,
    special-case logic is used to ensure a precise result (e.g.,
    integer 128 will always convert to '50%', integer 32 will always
    convert to '12.5%'), but for all other values a standard Python
    ``float`` is used and rounded to two decimal places, which may
    result in a loss of precision for some values.

    """
    # In order to maintain precision for common values,
    # special-case them.
    specials = {
        255: "100%",
        128: "50%",
        64: "25%",
        32: "12.5%",
        16: "6.25%",
        0: "0%",
    }
    return PercentRGB._make(
        specials.get(d, "{:.02f}%".format(d / 255.0 * 100))
        for d in normalize_integer_triplet(rgb_triplet)
    )


# Conversions from percentage rgb() triplets to various formats.
#################################################################


def rgb_percent_to_name(rgb_percent_triplet: PercentTuple, spec: str = CSS3) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name, if any
    such name exists.

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    If there is no matching name, ``ValueError`` is raised.

    """
    return rgb_to_name(
        rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet)), spec=spec
    )


def rgb_percent_to_name_closest(
    rgb_percent_triplet: PercentTuple,
    spec: str = CSS3,
    f: DistanceFunction = lambda v1, v2: (v1[0] - v2[0]) ** 2
    + (v1[1] - v2[1]) ** 2
    + (v1[2] - v2[2]) ** 2,
) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to its corresponding normalized color name. If no
    such name exists, return the normalized color name corresponding
    to the closest rgb_percent_triplet, calculated based on a function
    f whose default is squared error (mean has no effect in this case).

    The optional keyword argument ``spec`` determines which
    specification's list of color names will be used. The default is
    CSS3.

    """
    try:
        closest = rgb_percent_to_name(rgb_percent_triplet, spec)
    except ValueError:
        closest = _get_closest(rgb_percent_to_rgb(rgb_percent_triplet), spec, f)
    return closest


def rgb_percent_to_hex(rgb_percent_triplet: PercentTuple) -> str:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to a normalized hexadecimal color value for that
    color.

    """
    return rgb_to_hex(
        rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet))
    )


def _percent_to_integer(percent: str) -> int:
    """
    Internal helper for converting a percentage value to an integer
    between 0 and 255 inclusive.

    """
    return int(round(float(percent.split("%")[0]) / 100 * 255))


def rgb_percent_to_rgb(rgb_percent_triplet: PercentTuple) -> IntegerRGB:
    """
    Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
    color triplet, to a 3-tuple of integers suitable for use in
    representing that color.

    Some precision may be lost in this conversion. See the note
    regarding precision for ``rgb_to_rgb_percent()`` for details.

    """
    return IntegerRGB._make(
        map(_percent_to_integer, normalize_percent_triplet(rgb_percent_triplet))
    )

Utility functions for working with the color names and color value formats defined by the HTML and CSS specifications for use in documents on the Web.  See documentation (in docs/ directory of source distribution) for details of the supported formats, conventions and conversions. Internal utility for calculating the closest normalised color     name based on a function f; given an rgb_triplet, returns the     closest normalised color name. # Conversions from color names to various formats. ################################################################# Convert a color name to a normalized hexadecimal color value.      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3.      When no color of that name exists in the given specification,     ``ValueError`` is raised. Convert a color name to a 3-tuple of integers suitable for use in     an ``rgb()`` triplet specifying that color. Convert a color name to a 3-tuple of percentages suitable for use     in an ``rgb()`` triplet specifying that color. # Conversions from hexadecimal color values to various formats. ################################################################# Convert a hexadecimal color value to its corresponding normalized     color name, if any such name exists.      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3.      When no color name for the value is found in the given     specification, ``ValueError`` is raised. Convert a hexadecimal color value to its corresponding normalized     color name. If no such name exists, return the normalized color     name corresponding to the closest hex_value, calculated based on     a function f whose default is squared error (mean has no effect     in this case).      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3. Convert a hexadecimal color value to a 3-tuple of integers     suitable for use in an ``rgb()`` triplet specifying that color. Convert a hexadecimal color value to a 3-tuple of percentages     suitable for use in an ``rgb()`` triplet representing that color. # Conversions from  integer rgb() triplets to various formats. ################################################################# Convert a 3-tuple of integers, suitable for use in an ``rgb()``     color triplet, to its corresponding normalized color name, if any     such name exists.      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3.      If there is no matching name, ``ValueError`` is raised. Convert a 3-tuple of integers, suitable for use in an ``rgb()``     color triplet, to its corresponding normalized color name. If no     such name exists, return the normalized color name corresponding     to the closest rgb triplet, calculated based on a function f     whose default is squared error (mean has no effect in this case).      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3. Convert a 3-tuple of integers, suitable for use in an ``rgb()``     color triplet, to a normalized hexadecimal value for that color. Convert a 3-tuple of integers, suitable for use in an ``rgb()``     color triplet, to a 3-tuple of percentages suitable for use in     representing that color.      This function makes some trade-offs in terms of the accuracy of     the final representation; for some common integer values,     special-case logic is used to ensure a precise result (e.g.,     integer 128 will always convert to '50%', integer 32 will always     convert to '12.5%'), but for all other values a standard Python     ``float`` is used and rounded to two decimal places, which may     result in a loss of precision for some values. # In order to maintain precision for common values, # special-case them. # Conversions from percentage rgb() triplets to various formats. ################################################################# Convert a 3-tuple of percentages, suitable for use in an ``rgb()``     color triplet, to its corresponding normalized color name, if any     such name exists.      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3.      If there is no matching name, ``ValueError`` is raised. Convert a 3-tuple of percentages, suitable for use in an ``rgb()``     color triplet, to its corresponding normalized color name. If no     such name exists, return the normalized color name corresponding     to the closest rgb_percent_triplet, calculated based on a function     f whose default is squared error (mean has no effect in this case).      The optional keyword argument ``spec`` determines which     specification's list of color names will be used. The default is     CSS3. Convert a 3-tuple of percentages, suitable for use in an ``rgb()``     color triplet, to a normalized hexadecimal color value for that     color. Internal helper for converting a percentage value to an integer     between 0 and 255 inclusive. Convert a 3-tuple of percentages, suitable for use in an ``rgb()``     color triplet, to a 3-tuple of integers suitable for use in     representing that color.      Some precision may be lost in this conversion. See the note     regarding precision for ``rgb_to_rgb_percent()`` for details.