import math
import warnings


def get_normalized_color(start_color, end_color, start_no, end_no, value):
    """
    Gets a color relative to a numbers position in a range. (Heatmap)
    :param start_color: First color in RGB e.g. #43F3FC
    :param end_color: Last color in range
    :param start_no: Start of range
    :param end_no: End of range
    :param value: value within range
    :return: normalized RGB value in the form #RRGGBB
    """
    a_r, a_g, a_b = int(start_color[1:3], 16), int(
        start_color[3:5], 16), int(start_color[5:], 16)
    b_r, b_g, b_b = int(end_color[1:3], 16), int(
        end_color[3:5], 16), int(end_color[5:], 16)

    # There's some subtle difference in type when truncated.
    value = float(value)
    if end_no - start_no == 0:
        return "#FFFFFF"
    percentage = (value - start_no) / (end_no - start_no)

    r_diff = b_r - a_r
    g_diff = b_g - a_g
    b_diff = b_b - a_b

    adjusted_r = r_diff * percentage + a_r
    adjusted_g = g_diff * percentage + a_g
    adjusted_b = b_diff * percentage + a_b

    invalid_values = [float('NaN'), float('Inf')]
    if math.isnan(adjusted_r) or math.isnan(
            adjusted_b) or math.isnan(adjusted_g):
        warnings.warn("Non-Finite value detected", RuntimeWarning)
        return "#%X%X%X" % (122, 122, 122)

    return "#%X%X%X" % (int(adjusted_r), int(adjusted_g), int(adjusted_b))