'''
Names for the standard and extended color set.
Extended set is similar to `vim wiki <http://vim.wikia.com/wiki/Xterm256_color_names_for_console_Vim>`_, `colored <https://pypi.python.org/pypi/colored>`_, etc. Colors based on `wikipedia <https://en.wikipedia.org/wiki/ANSI_escape_code#Colors>`_.

You can access the index of the colors with names.index(name). You can access the
rgb values with ``r=int(html[n][1:3],16)``, etc.
'''

from __future__ import division, print_function

color_names = '''\
black
red
green
yellow
blue
magenta
cyan
light_gray
dark_gray
light_red
light_green
light_yellow
light_blue
light_magenta
light_cyan
white
grey_0
navy_blue
dark_blue
blue_3
blue_3a
blue_1
dark_green
deep_sky_blue_4
deep_sky_blue_4a
deep_sky_blue_4b
dodger_blue_3
dodger_blue_2
green_4
spring_green_4
turquoise_4
deep_sky_blue_3
deep_sky_blue_3a
dodger_blue_1
green_3
spring_green_3
dark_cyan
light_sea_green
deep_sky_blue_2
deep_sky_blue_1
green_3a
spring_green_3a
spring_green_2
cyan_3
dark_turquoise
turquoise_2
green_1
spring_green_2a
spring_green_1
medium_spring_green
cyan_2
cyan_1
dark_red
deep_pink_4
purple_4
purple_4a
purple_3
blue_violet
orange_4
grey_37
medium_purple_4
slate_blue_3
slate_blue_3a
royal_blue_1
chartreuse_4
dark_sea_green_4
pale_turquoise_4
steel_blue
steel_blue_3
cornflower_blue
chartreuse_3
dark_sea_green_4a
cadet_blue
cadet_blue_a
sky_blue_3
steel_blue_1
chartreuse_3a
pale_green_3
sea_green_3
aquamarine_3
medium_turquoise
steel_blue_1a
chartreuse_2a
sea_green_2
sea_green_1
sea_green_1a
aquamarine_1
dark_slate_gray_2
dark_red_a
deep_pink_4a
dark_magenta
dark_magenta_a
dark_violet
purple
orange_4a
light_pink_4
plum_4
medium_purple_3
medium_purple_3a
slate_blue_1
yellow_4
wheat_4
grey_53
light_slate_grey
medium_purple
light_slate_blue
yellow_4_a
dark_olive_green_3
dark_sea_green
light_sky_blue_3
light_sky_blue_3a
sky_blue_2
chartreuse_2
dark_olive_green_3a
pale_green_3a
dark_sea_green_3
dark_slate_gray_3
sky_blue_1
chartreuse_1
light_green_a
light_green_b
pale_green_1
aquamarine_1a
dark_slate_gray_1
red_3
deep_pink_4b
medium_violet_red
magenta_3
dark_violet_a
purple_a
dark_orange_3
indian_red
hot_pink_3
medium_orchid_3
medium_orchid
medium_purple_2
dark_goldenrod
light_salmon_3
rosy_brown
grey_63
medium_purple_2a
medium_purple_1
gold_3
dark_khaki
navajo_white_3
grey_69
light_steel_blue_3
light_steel_blue
yellow_3
dark_olive_green_3b
dark_sea_green_3a
dark_sea_green_2
light_cyan_3
light_sky_blue_1
green_yellow
dark_olive_green_2
pale_green_1a
dark_sea_green_2a
dark_sea_green_1
pale_turquoise_1
red_3a
deep_pink_3
deep_pink_3a
magenta_3a
magenta_3b
magenta_2
dark_orange_3a
indian_red_a
hot_pink_3a
hot_pink_2
orchid
medium_orchid_1
orange_3
light_salmon_3a
light_pink_3
pink_3
plum_3
violet
gold_3a
light_goldenrod_3
tan
misty_rose_3
thistle_3
plum_2
yellow_3a
khaki_3
light_goldenrod_2
light_yellow_3
grey_84
light_steel_blue_1
yellow_2
dark_olive_green_1
dark_olive_green_1a
dark_sea_green_1a
honeydew_2
light_cyan_1
red_1
deep_pink_2
deep_pink_1
deep_pink_1a
magenta_2a
magenta_1
orange_red_1
indian_red_1
indian_red_1a
hot_pink
hot_pink_a
medium_orchid_1a
dark_orange
salmon_1
light_coral
pale_violet_red_1
orchid_2
orchid_1
orange_1
sandy_brown
light_salmon_1
light_pink_1
pink_1
plum_1
gold_1
light_goldenrod_2a
light_goldenrod_2b
navajo_white_1
misty_rose_1
thistle_1
yellow_1
light_goldenrod_1
khaki_1
wheat_1
cornsilk_1
grey_10_0
grey_3
grey_7
grey_11
grey_15
grey_19
grey_23
grey_27
grey_30
grey_35
grey_39
grey_42
grey_46
grey_50
grey_54
grey_58
grey_62
grey_66
grey_70
grey_74
grey_78
grey_82
grey_85
grey_89
grey_93'''.split()

_greys = (3.4, 7.4, 11, 15, 19, 23, 26.7, 30.49, 34.6, 38.6, 42.4, 46.4, 50, 54, 58, 62, 66, 69.8, 73.8, 77.7, 81.6, 85.3, 89.3, 93)
_grey_vals = [int(x/100.0*16*16) for x in _greys]

_grey_html = ['#' + format(x,'02x')*3 for x in _grey_vals]

_normals =  [int(x,16) for x in '0 5f 87 af d7 ff'.split()]
_normal_html = ['#' + format(_normals[n//36],'02x') + format(_normals[n//6%6],'02x') + format(_normals[n%6],'02x') for n in range(16-16,232-16)]

_base_pattern = [(n//4,n//2%2,n%2) for n in range(8)]
_base_html = (['#{2:02x}{1:02x}{0:02x}'.format(x[0]*192,x[1]*192,x[2]*192) for x in  _base_pattern]
        + ['#808080']
        + ['#{2:02x}{1:02x}{0:02x}'.format(x[0]*255,x[1]*255,x[2]*255) for x in _base_pattern][1:])
color_html = _base_html + _normal_html + _grey_html

color_codes_simple = list(range(8)) + list(range(60,68))
"""Simple colors, remember that reset is #9, second half is non as common."""


# Attributes
attributes_ansi = dict(
    bold=1,
    dim=2,
    italics=3,
    underline=4,
    reverse=7,
    hidden=8,
    strikeout=9,
    )

# Stylesheet
default_styles = dict(
    warn="fg red",
    title="fg cyan underline bold",
    fatal="fg red bold",
    highlight="bg yellow",
    info="fg blue",
    success="fg green",
    )


#Functions to be used for color name operations

class FindNearest(object):
    """This is a class for finding the nearest color given rgb values.
    Different find methods are available."""
    def __init__(self, r, g, b):
        self.r = r
        self.b = b
        self.g = g

    def only_basic(self):
        """This will only return the first 8 colors!
        Breaks the colorspace into cubes, returns color"""
        midlevel = 0x40 # Since bright is not included

        # The colors are organised so that it is a
        # 3D cube, black at 0,0,0, white at 1,1,1
        # Compressed to linear_integers r,g,b
        # [[[0,1],[2,3]],[[4,5],[6,7]]]
        # r*1 + g*2 + b*4
        return (self.r>=midlevel)*1 + (self.g>=midlevel)*2 + (self.b>=midlevel)*4

    def all_slow(self, color_slice=slice(None, None, None)):
        """This is a slow way to find the nearest color."""
        distances = [self._distance_to_color(color) for color in color_html[color_slice]]
        return  min(range(len(distances)), key=distances.__getitem__)

    def _distance_to_color(self, color):
        """This computes the distance to a color, should be minimized."""
        rgb = (int(color[1:3],16), int(color[3:5],16), int(color[5:7],16))
        return (self.r-rgb[0])**2 + (self.g-rgb[1])**2 + (self.b-rgb[2])**2

    def _distance_to_color_number(self, n):
        color = color_html[n]
        return self._distance_to_color(color)

    def only_colorblock(self):
        """This finds the nearest color based on block system, only works
        for 17-232 color values."""
        rint = min(range(len(_normals)), key=[abs(x-self.r) for x in _normals].__getitem__)
        bint = min(range(len(_normals)), key=[abs(x-self.b) for x in _normals].__getitem__)
        gint = min(range(len(_normals)), key=[abs(x-self.g) for x in _normals].__getitem__)
        return (16 + 36 * rint + 6 * gint + bint)

    def only_simple(self):
        """Finds the simple color-block color."""
        return self.all_slow(slice(0,16,None))

    def only_grey(self):
        """Finds the greyscale color."""
        rawval = (self.r + self.b + self.g) / 3
        n = min(range(len(_grey_vals)), key=[abs(x-rawval) for x in _grey_vals].__getitem__)
        return n+232

    def all_fast(self):
        """Runs roughly 8 times faster than the slow version."""
        colors = [self.only_simple(), self.only_colorblock(), self.only_grey()]
        distances = [self._distance_to_color_number(n) for n in colors]
        return  colors[min(range(len(distances)), key=distances.__getitem__)]

def from_html(color):
    """Convert html hex code to rgb."""
    if len(color) != 7 or color[0] != '#':
        raise ValueError("Invalid length of html code")
    return (int(color[1:3],16), int(color[3:5],16), int(color[5:7],16))

def to_html(r, g, b):
    """Convert rgb to html hex code."""
    return "#{0:02x}{1:02x}{2:02x}".format(r, g, b)

