/**
 * 颜色辅助模块
 * @module zrender/tool/color
 */
module.exports = function (require) {
  var util = require('../tool/util');

  var _ctx; // Color palette is an array containing the default colors for the chart's
  // series.
  // When all colors are used, new colors are selected from the start again.
  // Defaults to:
  // 默认色板


  var palette = ['#ff9277', ' #dddd00', ' #ffc877', ' #bbe3ff', ' #d5ffbb', '#bbbbff', ' #ddb000', ' #b0dd00', ' #e2bbff', ' #ffbbe3', '#ff7777', ' #ff9900', ' #83dd00', ' #77e3ff', ' #778fff', '#c877ff', ' #ff77ab', ' #ff6600', ' #aa8800', ' #77c7ff', '#ad77ff', ' #ff77ff', ' #dd0083', ' #777700', ' #00aa00', '#0088aa', ' #8400dd', ' #aa0088', ' #dd0000', ' #772e00'];
  var _palette = palette;
  var highlightColor = 'rgba(255,255,0,0.5)';
  var _highlightColor = highlightColor; // 颜色格式

  /*jshint maxlen: 330 */

  var colorRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i;
  var _nameColors = {
    aliceblue: '#f0f8ff',
    antiquewhite: '#faebd7',
    aqua: '#0ff',
    aquamarine: '#7fffd4',
    azure: '#f0ffff',
    beige: '#f5f5dc',
    bisque: '#ffe4c4',
    black: '#000',
    blanchedalmond: '#ffebcd',
    blue: '#00f',
    blueviolet: '#8a2be2',
    brown: '#a52a2a',
    burlywood: '#deb887',
    cadetblue: '#5f9ea0',
    chartreuse: '#7fff00',
    chocolate: '#d2691e',
    coral: '#ff7f50',
    cornflowerblue: '#6495ed',
    cornsilk: '#fff8dc',
    crimson: '#dc143c',
    cyan: '#0ff',
    darkblue: '#00008b',
    darkcyan: '#008b8b',
    darkgoldenrod: '#b8860b',
    darkgray: '#a9a9a9',
    darkgrey: '#a9a9a9',
    darkgreen: '#006400',
    darkkhaki: '#bdb76b',
    darkmagenta: '#8b008b',
    darkolivegreen: '#556b2f',
    darkorange: '#ff8c00',
    darkorchid: '#9932cc',
    darkred: '#8b0000',
    darksalmon: '#e9967a',
    darkseagreen: '#8fbc8f',
    darkslateblue: '#483d8b',
    darkslategray: '#2f4f4f',
    darkslategrey: '#2f4f4f',
    darkturquoise: '#00ced1',
    darkviolet: '#9400d3',
    deeppink: '#ff1493',
    deepskyblue: '#00bfff',
    dimgray: '#696969',
    dimgrey: '#696969',
    dodgerblue: '#1e90ff',
    firebrick: '#b22222',
    floralwhite: '#fffaf0',
    forestgreen: '#228b22',
    fuchsia: '#f0f',
    gainsboro: '#dcdcdc',
    ghostwhite: '#f8f8ff',
    gold: '#ffd700',
    goldenrod: '#daa520',
    gray: '#808080',
    grey: '#808080',
    green: '#008000',
    greenyellow: '#adff2f',
    honeydew: '#f0fff0',
    hotpink: '#ff69b4',
    indianred: '#cd5c5c',
    indigo: '#4b0082',
    ivory: '#fffff0',
    khaki: '#f0e68c',
    lavender: '#e6e6fa',
    lavenderblush: '#fff0f5',
    lawngreen: '#7cfc00',
    lemonchiffon: '#fffacd',
    lightblue: '#add8e6',
    lightcoral: '#f08080',
    lightcyan: '#e0ffff',
    lightgoldenrodyellow: '#fafad2',
    lightgray: '#d3d3d3',
    lightgrey: '#d3d3d3',
    lightgreen: '#90ee90',
    lightpink: '#ffb6c1',
    lightsalmon: '#ffa07a',
    lightseagreen: '#20b2aa',
    lightskyblue: '#87cefa',
    lightslategray: '#789',
    lightslategrey: '#789',
    lightsteelblue: '#b0c4de',
    lightyellow: '#ffffe0',
    lime: '#0f0',
    limegreen: '#32cd32',
    linen: '#faf0e6',
    magenta: '#f0f',
    maroon: '#800000',
    mediumaquamarine: '#66cdaa',
    mediumblue: '#0000cd',
    mediumorchid: '#ba55d3',
    mediumpurple: '#9370d8',
    mediumseagreen: '#3cb371',
    mediumslateblue: '#7b68ee',
    mediumspringgreen: '#00fa9a',
    mediumturquoise: '#48d1cc',
    mediumvioletred: '#c71585',
    midnightblue: '#191970',
    mintcream: '#f5fffa',
    mistyrose: '#ffe4e1',
    moccasin: '#ffe4b5',
    navajowhite: '#ffdead',
    navy: '#000080',
    oldlace: '#fdf5e6',
    olive: '#808000',
    olivedrab: '#6b8e23',
    orange: '#ffa500',
    orangered: '#ff4500',
    orchid: '#da70d6',
    palegoldenrod: '#eee8aa',
    palegreen: '#98fb98',
    paleturquoise: '#afeeee',
    palevioletred: '#d87093',
    papayawhip: '#ffefd5',
    peachpuff: '#ffdab9',
    peru: '#cd853f',
    pink: '#ffc0cb',
    plum: '#dda0dd',
    powderblue: '#b0e0e6',
    purple: '#800080',
    red: '#f00',
    rosybrown: '#bc8f8f',
    royalblue: '#4169e1',
    saddlebrown: '#8b4513',
    salmon: '#fa8072',
    sandybrown: '#f4a460',
    seagreen: '#2e8b57',
    seashell: '#fff5ee',
    sienna: '#a0522d',
    silver: '#c0c0c0',
    skyblue: '#87ceeb',
    slateblue: '#6a5acd',
    slategray: '#708090',
    slategrey: '#708090',
    snow: '#fffafa',
    springgreen: '#00ff7f',
    steelblue: '#4682b4',
    tan: '#d2b48c',
    teal: '#008080',
    thistle: '#d8bfd8',
    tomato: '#ff6347',
    turquoise: '#40e0d0',
    violet: '#ee82ee',
    wheat: '#f5deb3',
    white: '#fff',
    whitesmoke: '#f5f5f5',
    yellow: '#ff0',
    yellowgreen: '#9acd32'
  };
  /**
   * 自定义调色板
   */

  function customPalette(userPalete) {
    palette = userPalete;
  }
  /**
   * 复位默认色板
   */


  function resetPalette() {
    palette = _palette;
  }
  /**
   * 获取色板颜色
   * @memberOf module:zrender/tool/color
   * @param {number} idx 色板位置
   * @param {Array.<string>} [userPalete] 自定义色板
   * @return {string} 颜色
   */


  function getColor(idx, userPalete) {
    idx = idx | 0;
    userPalete = userPalete || palette;
    return userPalete[idx % userPalete.length];
  }
  /**
   * 自定义默认高亮颜色
   */


  function customHighlight(userHighlightColor) {
    highlightColor = userHighlightColor;
  }
  /**
   * 重置默认高亮颜色
   */


  function resetHighlight() {
    _highlightColor = highlightColor;
  }
  /**
   * 获取默认高亮颜色
   */


  function getHighlightColor() {
    return highlightColor;
  }
  /**
   * 径向渐变
   * @memberOf module:zrender/tool/color
   * @param {number} x0 渐变起点
   * @param {number} y0
   * @param {number} r0
   * @param {number} x1 渐变终点
   * @param {number} y1
   * @param {number} r1
   * @param {Array} colorList 颜色列表
   * @return {CanvasGradient}
   */


  function getRadialGradient(x0, y0, r0, x1, y1, r1, colorList) {
    if (!_ctx) {
      _ctx = util.getContext();
    }

    var gradient = _ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);

    for (var i = 0, l = colorList.length; i < l; i++) {
      gradient.addColorStop(colorList[i][0], colorList[i][1]);
    }

    gradient.__nonRecursion = true;
    return gradient;
  }
  /**
   * 线性渐变
   * @param {Object} x0 渐变起点
   * @param {Object} y0
   * @param {Object} x1 渐变终点
   * @param {Object} y1
   * @param {Array} colorList 颜色列表
   */


  function getLinearGradient(x0, y0, x1, y1, colorList) {
    if (!_ctx) {
      _ctx = util.getContext();
    }

    var gradient = _ctx.createLinearGradient(x0, y0, x1, y1);

    for (var i = 0, l = colorList.length; i < l; i++) {
      gradient.addColorStop(colorList[i][0], colorList[i][1]);
    }

    gradient.__nonRecursion = true;
    return gradient;
  }
  /**
   * 获取两种颜色之间渐变颜色数组
   * @param {color} start 起始颜色
   * @param {color} end 结束颜色
   * @param {number} step 渐变级数
   * @return {Array}  颜色数组
   */


  function getStepColors(start, end, step) {
    start = toRGBA(start);
    end = toRGBA(end);
    start = getData(start);
    end = getData(end);
    var colors = [];
    var stepR = (end[0] - start[0]) / step;
    var stepG = (end[1] - start[1]) / step;
    var stepB = (end[2] - start[2]) / step;
    var stepA = (end[3] - start[3]) / step; // 生成颜色集合
    // fix by linfeng 颜色堆积

    for (var i = 0, r = start[0], g = start[1], b = start[2], a = start[3]; i < step; i++) {
      colors[i] = toColor([adjust(Math.floor(r), [0, 255]), adjust(Math.floor(g), [0, 255]), adjust(Math.floor(b), [0, 255]), a.toFixed(4) - 0], 'rgba');
      r += stepR;
      g += stepG;
      b += stepB;
      a += stepA;
    }

    r = end[0];
    g = end[1];
    b = end[2];
    a = end[3];
    colors[i] = toColor([r, g, b, a], 'rgba');
    return colors;
  }
  /**
   * 获取指定级数的渐变颜色数组
   * @memberOf module:zrender/tool/color
   * @param {Array.<string>} colors 颜色组
   * @param {number} [step=20] 渐变级数
   * @return {Array.<string>}  颜色数组
   */


  function getGradientColors(colors, step) {
    var ret = [];
    var len = colors.length;

    if (step === undefined) {
      step = 20;
    }

    if (len === 1) {
      ret = getStepColors(colors[0], colors[0], step);
    } else if (len > 1) {
      for (var i = 0, n = len - 1; i < n; i++) {
        var steps = getStepColors(colors[i], colors[i + 1], step);

        if (i < n - 1) {
          steps.pop();
        }

        ret = ret.concat(steps);
      }
    }

    return ret;
  }
  /**
   * 颜色值数组转为指定格式颜色,例如:<br/>
   * data = [60,20,20,0.1] format = 'rgba'
   * 返回：rgba(60,20,20,0.1)
   * @param {Array} data 颜色值数组
   * @param {string} format 格式,默认rgb
   * @return {string} 颜色
   */


  function toColor(data, format) {
    format = format || 'rgb';

    if (data && (data.length === 3 || data.length === 4)) {
      data = map(data, function (c) {
        return c > 1 ? Math.ceil(c) : c;
      });

      if (format.indexOf('hex') > -1) {
        return '#' + ((1 << 24) + (data[0] << 16) + (data[1] << 8) + +data[2]).toString(16).slice(1);
      } else if (format.indexOf('hs') > -1) {
        var sx = map(data.slice(1, 3), function (c) {
          return c + '%';
        });
        data[1] = sx[0];
        data[2] = sx[1];
      }

      if (format.indexOf('a') > -1) {
        if (data.length === 3) {
          data.push(1);
        }

        data[3] = adjust(data[3], [0, 1]);
        return format + '(' + data.slice(0, 4).join(',') + ')';
      }

      return format + '(' + data.slice(0, 3).join(',') + ')';
    }
  }
  /**
   * 颜色字符串转换为rgba数组
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {Array.<number>} 颜色值数组
   */


  function toArray(color) {
    color = trim(color);

    if (color.indexOf('rgba') < 0) {
      color = toRGBA(color);
    }

    var data = [];
    var i = 0;
    color.replace(/[\d.]+/g, function (n) {
      if (i < 3) {
        n = n | 0;
      } else {
        // Alpha
        n = +n;
      }

      data[i++] = n;
    });
    return data;
  }
  /**
   * 颜色格式转化
   *
   * @param {string} color 颜色值数组
   * @param {string} format 格式,默认rgb
   * @return {string} 颜色
   */


  function convert(color, format) {
    if (!isCalculableColor(color)) {
      return color;
    }

    var data = getData(color);
    var alpha = data[3];

    if (typeof alpha === 'undefined') {
      alpha = 1;
    }

    if (color.indexOf('hsb') > -1) {
      data = _HSV_2_RGB(data);
    } else if (color.indexOf('hsl') > -1) {
      data = _HSL_2_RGB(data);
    }

    if (format.indexOf('hsb') > -1 || format.indexOf('hsv') > -1) {
      data = _RGB_2_HSB(data);
    } else if (format.indexOf('hsl') > -1) {
      data = _RGB_2_HSL(data);
    }

    data[3] = alpha;
    return toColor(data, format);
  }
  /**
   * 转换为rgba格式的颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} rgba颜色，rgba(r,g,b,a)
   */


  function toRGBA(color) {
    return convert(color, 'rgba');
  }
  /**
   * 转换为rgb数字格式的颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} rgb颜色，rgb(0,0,0)格式
   */


  function toRGB(color) {
    return convert(color, 'rgb');
  }
  /**
   * 转换为16进制颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} 16进制颜色，#rrggbb格式
   */


  function toHex(color) {
    return convert(color, 'hex');
  }
  /**
   * 转换为HSV颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSVA颜色，hsva(h,s,v,a)
   */


  function toHSVA(color) {
    return convert(color, 'hsva');
  }
  /**
   * 转换为HSV颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSV颜色，hsv(h,s,v)
   */


  function toHSV(color) {
    return convert(color, 'hsv');
  }
  /**
   * 转换为HSBA颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSBA颜色，hsba(h,s,b,a)
   */


  function toHSBA(color) {
    return convert(color, 'hsba');
  }
  /**
   * 转换为HSB颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSB颜色，hsb(h,s,b)
   */


  function toHSB(color) {
    return convert(color, 'hsb');
  }
  /**
   * 转换为HSLA颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSLA颜色，hsla(h,s,l,a)
   */


  function toHSLA(color) {
    return convert(color, 'hsla');
  }
  /**
   * 转换为HSL颜色
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} HSL颜色，hsl(h,s,l)
   */


  function toHSL(color) {
    return convert(color, 'hsl');
  }
  /**
   * 转换颜色名
   * 
   * @param {string} color 颜色
   * @return {string} 颜色名
   */


  function toName(color) {
    for (var key in _nameColors) {
      if (toHex(_nameColors[key]) === toHex(color)) {
        return key;
      }
    }

    return null;
  }
  /**
   * 移除颜色中多余空格
   * 
   * @param {string} color 颜色
   * @return {string} 无空格颜色
   */


  function trim(color) {
    return String(color).replace(/\s+/g, '');
  }
  /**
   * 颜色规范化
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} 规范化后的颜色
   */


  function normalize(color) {
    // 颜色名
    if (_nameColors[color]) {
      color = _nameColors[color];
    } // 去掉空格


    color = trim(color); // hsv与hsb等价

    color = color.replace(/hsv/i, 'hsb'); // rgb转为rrggbb

    if (/^#[\da-f]{3}$/i.test(color)) {
      color = parseInt(color.slice(1), 16);
      var r = (color & 0xf00) << 8;
      var g = (color & 0xf0) << 4;
      var b = color & 0xf;
      color = '#' + ((1 << 24) + (r << 4) + r + (g << 4) + g + (b << 4) + b).toString(16).slice(1);
    } // 或者使用以下正则替换，不过 chrome 下性能相对差点
    // color = color.replace(/^#([\da-f])([\da-f])([\da-f])$/i, '#$1$1$2$2$3$3');


    return color;
  }
  /**
   * 颜色加深或减淡，当level>0加深，当level<0减淡
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @param {number} level 升降程度,取值区间[-1,1]
   * @return {string} 加深或减淡后颜色值
   */


  function lift(color, level) {
    if (!isCalculableColor(color)) {
      return color;
    }

    var direct = level > 0 ? 1 : -1;

    if (typeof level === 'undefined') {
      level = 0;
    }

    level = Math.abs(level) > 1 ? 1 : Math.abs(level);
    color = toRGB(color);
    var data = getData(color);

    for (var i = 0; i < 3; i++) {
      if (direct === 1) {
        data[i] = data[i] * (1 - level) | 0;
      } else {
        data[i] = (255 - data[i]) * level + data[i] | 0;
      }
    }

    return 'rgb(' + data.join(',') + ')';
  }
  /**
   * 颜色翻转,[255-r,255-g,255-b,1-a]
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @return {string} 翻转颜色
   */


  function reverse(color) {
    if (!isCalculableColor(color)) {
      return color;
    }

    var data = getData(toRGBA(color));
    data = map(data, function (c) {
      return 255 - c;
    });
    return toColor(data, 'rgb');
  }
  /**
   * 简单两种颜色混合
   * @memberOf module:zrender/tool/color
   * @param {string} color1 第一种颜色
   * @param {string} color2 第二种颜色
   * @param {number} weight 混合权重[0-1]
   * @return {string} 结果色,rgb(r,g,b)或rgba(r,g,b,a)
   */


  function mix(color1, color2, weight) {
    if (!isCalculableColor(color1) || !isCalculableColor(color2)) {
      return color1;
    }

    if (typeof weight === 'undefined') {
      weight = 0.5;
    }

    weight = 1 - adjust(weight, [0, 1]);
    var w = weight * 2 - 1;
    var data1 = getData(toRGBA(color1));
    var data2 = getData(toRGBA(color2));
    var d = data1[3] - data2[3];
    var weight1 = ((w * d === -1 ? w : (w + d) / (1 + w * d)) + 1) / 2;
    var weight2 = 1 - weight1;
    var data = [];

    for (var i = 0; i < 3; i++) {
      data[i] = data1[i] * weight1 + data2[i] * weight2;
    }

    var alpha = data1[3] * weight + data2[3] * (1 - weight);
    alpha = Math.max(0, Math.min(1, alpha));

    if (data1[3] === 1 && data2[3] === 1) {
      // 不考虑透明度
      return toColor(data, 'rgb');
    }

    data[3] = alpha;
    return toColor(data, 'rgba');
  }
  /**
   * 随机颜色
   * 
   * @return {string} 颜色值，#rrggbb格式
   */


  function random() {
    return '#' + (Math.random().toString(16) + '0000').slice(2, 8);
  }
  /**
   * 获取颜色值数组,返回值范围： <br/>
   * RGB 范围[0-255] <br/>
   * HSL/HSV/HSB 范围[0-1]<br/>
   * A透明度范围[0-1]
   * 支持格式：
   * #rgb
   * #rrggbb
   * rgb(r,g,b)
   * rgb(r%,g%,b%)
   * rgba(r,g,b,a)
   * hsb(h,s,b) // hsv与hsb等价
   * hsb(h%,s%,b%)
   * hsba(h,s,b,a)
   * hsl(h,s,l)
   * hsl(h%,s%,l%)
   * hsla(h,s,l,a)
   *
   * @param {string} color 颜色
   * @return {Array.<number>} 颜色值数组或null
   */


  function getData(color) {
    color = normalize(color);
    var r = color.match(colorRegExp);

    if (r === null) {
      throw new Error('The color format error'); // 颜色格式错误
    }

    var d;
    var a;
    var data = [];
    var rgb;

    if (r[2]) {
      // #rrggbb
      d = r[2].replace('#', '').split('');
      rgb = [d[0] + d[1], d[2] + d[3], d[4] + d[5]];
      data = map(rgb, function (c) {
        return adjust(parseInt(c, 16), [0, 255]);
      });
    } else if (r[4]) {
      // rgb rgba
      var rgba = r[4].split(',');
      a = rgba[3];
      rgb = rgba.slice(0, 3);
      data = map(rgb, function (c) {
        c = Math.floor(c.indexOf('%') > 0 ? parseInt(c, 0) * 2.55 : c);
        return adjust(c, [0, 255]);
      });

      if (typeof a !== 'undefined') {
        data.push(adjust(parseFloat(a), [0, 1]));
      }
    } else if (r[5] || r[6]) {
      // hsb hsba hsl hsla
      var hsxa = (r[5] || r[6]).split(',');
      var h = parseInt(hsxa[0], 0) / 360;
      var s = hsxa[1];
      var x = hsxa[2];
      a = hsxa[3];
      data = map([s, x], function (c) {
        return adjust(parseFloat(c) / 100, [0, 1]);
      });
      data.unshift(h);

      if (typeof a !== 'undefined') {
        data.push(adjust(parseFloat(a), [0, 1]));
      }
    }

    return data;
  }
  /**
   * 设置颜色透明度
   * @memberOf module:zrender/tool/color
   * @param {string} color 颜色
   * @param {number} a 透明度,区间[0,1]
   * @return {string} rgba颜色值
   */


  function alpha(color, a) {
    if (!isCalculableColor(color)) {
      return color;
    }

    if (a === null) {
      a = 1;
    }

    var data = getData(toRGBA(color));
    data[3] = adjust(Number(a).toFixed(4), [0, 1]);
    return toColor(data, 'rgba');
  } // 数组映射


  function map(array, fun) {
    if (typeof fun !== 'function') {
      throw new TypeError();
    }

    var len = array ? array.length : 0;

    for (var i = 0; i < len; i++) {
      array[i] = fun(array[i]);
    }

    return array;
  } // 调整值区间


  function adjust(value, region) {
    // < to <= & > to >=
    // modify by linzhifeng 2014-05-25 because -0 == 0
    if (value <= region[0]) {
      value = region[0];
    } else if (value >= region[1]) {
      value = region[1];
    }

    return value;
  }

  function isCalculableColor(color) {
    return color instanceof Array || typeof color === 'string';
  } // 参见 http:// www.easyrgb.com/index.php?X=MATH


  function _HSV_2_RGB(data) {
    var H = data[0];
    var S = data[1];
    var V = data[2]; // HSV from 0 to 1

    var R;
    var G;
    var B;

    if (S === 0) {
      R = V * 255;
      G = V * 255;
      B = V * 255;
    } else {
      var h = H * 6;

      if (h === 6) {
        h = 0;
      }

      var i = h | 0;
      var v1 = V * (1 - S);
      var v2 = V * (1 - S * (h - i));
      var v3 = V * (1 - S * (1 - (h - i)));
      var r = 0;
      var g = 0;
      var b = 0;

      if (i === 0) {
        r = V;
        g = v3;
        b = v1;
      } else if (i === 1) {
        r = v2;
        g = V;
        b = v1;
      } else if (i === 2) {
        r = v1;
        g = V;
        b = v3;
      } else if (i === 3) {
        r = v1;
        g = v2;
        b = V;
      } else if (i === 4) {
        r = v3;
        g = v1;
        b = V;
      } else {
        r = V;
        g = v1;
        b = v2;
      } // RGB results from 0 to 255


      R = r * 255;
      G = g * 255;
      B = b * 255;
    }

    return [R, G, B];
  }

  function _HSL_2_RGB(data) {
    var H = data[0];
    var S = data[1];
    var L = data[2]; // HSL from 0 to 1

    var R;
    var G;
    var B;

    if (S === 0) {
      R = L * 255;
      G = L * 255;
      B = L * 255;
    } else {
      var v2;

      if (L < 0.5) {
        v2 = L * (1 + S);
      } else {
        v2 = L + S - S * L;
      }

      var v1 = 2 * L - v2;
      R = 255 * _HUE_2_RGB(v1, v2, H + 1 / 3);
      G = 255 * _HUE_2_RGB(v1, v2, H);
      B = 255 * _HUE_2_RGB(v1, v2, H - 1 / 3);
    }

    return [R, G, B];
  }

  function _HUE_2_RGB(v1, v2, vH) {
    if (vH < 0) {
      vH += 1;
    }

    if (vH > 1) {
      vH -= 1;
    }

    if (6 * vH < 1) {
      return v1 + (v2 - v1) * 6 * vH;
    }

    if (2 * vH < 1) {
      return v2;
    }

    if (3 * vH < 2) {
      return v1 + (v2 - v1) * (2 / 3 - vH) * 6;
    }

    return v1;
  }

  function _RGB_2_HSB(data) {
    // RGB from 0 to 255
    var R = data[0] / 255;
    var G = data[1] / 255;
    var B = data[2] / 255;
    var vMin = Math.min(R, G, B); // Min. value of RGB

    var vMax = Math.max(R, G, B); // Max. value of RGB

    var delta = vMax - vMin; // Delta RGB value

    var V = vMax;
    var H;
    var S; // HSV results from 0 to 1

    if (delta === 0) {
      H = 0;
      S = 0;
    } else {
      S = delta / vMax;
      var deltaR = ((vMax - R) / 6 + delta / 2) / delta;
      var deltaG = ((vMax - G) / 6 + delta / 2) / delta;
      var deltaB = ((vMax - B) / 6 + delta / 2) / delta;

      if (R === vMax) {
        H = deltaB - deltaG;
      } else if (G === vMax) {
        H = 1 / 3 + deltaR - deltaB;
      } else if (B === vMax) {
        H = 2 / 3 + deltaG - deltaR;
      }

      if (H < 0) {
        H += 1;
      }

      if (H > 1) {
        H -= 1;
      }
    }

    H = H * 360;
    S = S * 100;
    V = V * 100;
    return [H, S, V];
  }

  function _RGB_2_HSL(data) {
    // RGB from 0 to 255
    var R = data[0] / 255;
    var G = data[1] / 255;
    var B = data[2] / 255;
    var vMin = Math.min(R, G, B); // Min. value of RGB

    var vMax = Math.max(R, G, B); // Max. value of RGB

    var delta = vMax - vMin; // Delta RGB value

    var L = (vMax + vMin) / 2;
    var H;
    var S; // HSL results from 0 to 1

    if (delta === 0) {
      H = 0;
      S = 0;
    } else {
      if (L < 0.5) {
        S = delta / (vMax + vMin);
      } else {
        S = delta / (2 - vMax - vMin);
      }

      var deltaR = ((vMax - R) / 6 + delta / 2) / delta;
      var deltaG = ((vMax - G) / 6 + delta / 2) / delta;
      var deltaB = ((vMax - B) / 6 + delta / 2) / delta;

      if (R === vMax) {
        H = deltaB - deltaG;
      } else if (G === vMax) {
        H = 1 / 3 + deltaR - deltaB;
      } else if (B === vMax) {
        H = 2 / 3 + deltaG - deltaR;
      }

      if (H < 0) {
        H += 1;
      }

      if (H > 1) {
        H -= 1;
      }
    }

    H = H * 360;
    S = S * 100;
    L = L * 100;
    return [H, S, L];
  }

  return {
    customPalette: customPalette,
    resetPalette: resetPalette,
    getColor: getColor,
    getHighlightColor: getHighlightColor,
    customHighlight: customHighlight,
    resetHighlight: resetHighlight,
    getRadialGradient: getRadialGradient,
    getLinearGradient: getLinearGradient,
    getGradientColors: getGradientColors,
    getStepColors: getStepColors,
    reverse: reverse,
    mix: mix,
    lift: lift,
    trim: trim,
    random: random,
    toRGB: toRGB,
    toRGBA: toRGBA,
    toHex: toHex,
    toHSL: toHSL,
    toHSLA: toHSLA,
    toHSB: toHSB,
    toHSBA: toHSBA,
    toHSV: toHSV,
    toHSVA: toHSVA,
    toName: toName,
    toColor: toColor,
    toArray: toArray,
    alpha: alpha,
    getData: getData
  };
}(require);