/*
 * Copyright (C) 2011 Brian Grinstead All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
export class Spectrum extends UI.VBox {
  /**
   * @param {?ColorPicker.ContrastInfo=} contrastInfo
   */
  constructor(contrastInfo) {
    /**
     * @param {!Element} parentElement
     */
    function appendSwitcherIcon(parentElement) {
      const icon = parentElement.createSVGChild('svg');
      icon.setAttribute('height', 16);
      icon.setAttribute('width', 16);
      const path = icon.createSVGChild('path');
      path.setAttribute('d', 'M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z');
      return icon;
    }

    super(true);
    this.registerRequiredCSS('color_picker/spectrum.css');
    this.contentElement.tabIndex = 0;
    this.setDefaultFocusedElement(this.contentElement);

    this._colorElement = this.contentElement.createChild('div', 'spectrum-color');
    this._colorDragElement = this._colorElement.createChild('div', 'spectrum-sat fill')
                                 .createChild('div', 'spectrum-val fill')
                                 .createChild('div', 'spectrum-dragger');
    this._dragX = 0;
    this._dragY = 0;

    const toolsContainer = this.contentElement.createChild('div', 'spectrum-tools');
    const toolbar = new UI.Toolbar('spectrum-eye-dropper', toolsContainer);
    this._colorPickerButton = new UI.ToolbarToggle(Common.UIString('Toggle color picker'), 'largeicon-eyedropper');
    this._colorPickerButton.setToggled(true);
    this._colorPickerButton.addEventListener(
        UI.ToolbarButton.Events.Click, this._toggleColorPicker.bind(this, undefined));
    toolbar.appendToolbarItem(this._colorPickerButton);

    this._swatch = new Swatch(toolsContainer);

    this._hueElement = toolsContainer.createChild('div', 'spectrum-hue');
    this._hueElement.tabIndex = 0;
    this._hueElement.addEventListener('keydown', this._onSliderKeydown.bind(this, positionHue.bind(this)));
    UI.ARIAUtils.setAccessibleName(this._hueElement, ls`Change hue`);
    UI.ARIAUtils.markAsSlider(this._hueElement, 0, 360);
    this._hueSlider = this._hueElement.createChild('div', 'spectrum-slider');
    this._alphaElement = toolsContainer.createChild('div', 'spectrum-alpha');
    this._alphaElement.tabIndex = 0;
    this._alphaElement.addEventListener('keydown', this._onSliderKeydown.bind(this, positionAlpha.bind(this)));
    UI.ARIAUtils.setAccessibleName(this._alphaElement, ls`Change alpha`);
    UI.ARIAUtils.markAsSlider(this._alphaElement, 0, 1);
    this._alphaElementBackground = this._alphaElement.createChild('div', 'spectrum-alpha-background');
    this._alphaSlider = this._alphaElement.createChild('div', 'spectrum-slider');

    // RGBA/HSLA display.
    this._displayContainer = toolsContainer.createChild('div', 'spectrum-text source-code');
    this._textValues = [];
    for (let i = 0; i < 4; ++i) {
      const inputValue = UI.createInput('spectrum-text-value');
      this._displayContainer.appendChild(inputValue);
      inputValue.maxLength = 4;
      this._textValues.push(inputValue);
      inputValue.addEventListener('keydown', this._inputChanged.bind(this), false);
      inputValue.addEventListener('input', this._inputChanged.bind(this), false);
      inputValue.addEventListener('mousewheel', this._inputChanged.bind(this), false);
    }

    this._textLabels = this._displayContainer.createChild('div', 'spectrum-text-label');

    // HEX display.
    this._hexContainer = toolsContainer.createChild('div', 'spectrum-text spectrum-text-hex source-code');
    this._hexValue = UI.createInput('spectrum-text-value');
    this._hexContainer.appendChild(this._hexValue);
    this._hexValue.maxLength = 9;
    this._hexValue.addEventListener('keydown', this._inputChanged.bind(this), false);
    this._hexValue.addEventListener('input', this._inputChanged.bind(this), false);
    this._hexValue.addEventListener('mousewheel', this._inputChanged.bind(this), false);

    const label = this._hexContainer.createChild('div', 'spectrum-text-label');
    label.textContent = ls`HEX`;
    UI.ARIAUtils.setAccessibleName(this._hexValue, label.textContent);

    const displaySwitcher = toolsContainer.createChild('div', 'spectrum-display-switcher spectrum-switcher');
    appendSwitcherIcon(displaySwitcher);
    displaySwitcher.tabIndex = 0;
    self.onInvokeElement(displaySwitcher, event => {
      this._formatViewSwitch();
      event.consume(true);
    });
    UI.ARIAUtils.setAccessibleName(displaySwitcher, ls`Change color format`);
    UI.ARIAUtils.markAsButton(displaySwitcher);

    UI.installDragHandle(
        this._hueElement, dragStart.bind(this, positionHue.bind(this)), positionHue.bind(this), null, 'pointer',
        'default');
    UI.installDragHandle(
        this._alphaElement, dragStart.bind(this, positionAlpha.bind(this)), positionAlpha.bind(this), null, 'pointer',
        'default');
    UI.installDragHandle(
        this._colorElement, dragStart.bind(this, positionColor.bind(this)), positionColor.bind(this), null, 'pointer',
        'default');

    // Color contrast business.
    if (contrastInfo) {
      this._contrastInfo = contrastInfo;
      this._contrastOverlay = new ColorPicker.ContrastOverlay(this._contrastInfo, this._colorElement);
      this._contrastDetails = new ColorPicker.ContrastDetails(
          this._contrastInfo, this.contentElement, this._toggleColorPicker.bind(this),
          this._contrastPanelExpanded.bind(this));

      this._contrastDetailsBackgroundColorPickedToggledBound =
          this._contrastDetailsBackgroundColorPickedToggled.bind(this);
    }

    this.element.classList.add('flex-none');
    /** @type {!Map.<string, !ColorPicker.Spectrum.Palette>} */
    this._palettes = new Map();
    this._palettePanel = this.contentElement.createChild('div', 'palette-panel');
    this._palettePanelShowing = false;
    this._paletteSectionContainer = this.contentElement.createChild('div', 'spectrum-palette-container');
    this._paletteContainer = this._paletteSectionContainer.createChild('div', 'spectrum-palette');
    this._paletteContainer.addEventListener('contextmenu', this._showPaletteColorContextMenu.bind(this, -1));
    this._shadesContainer = this.contentElement.createChild('div', 'palette-color-shades hidden');
    UI.installDragHandle(
        this._paletteContainer, this._paletteDragStart.bind(this), this._paletteDrag.bind(this),
        this._paletteDragEnd.bind(this), 'default');
    const paletteSwitcher =
        this._paletteSectionContainer.createChild('div', 'spectrum-palette-switcher spectrum-switcher');
    appendSwitcherIcon(paletteSwitcher);
    UI.ARIAUtils.markAsButton(paletteSwitcher);
    UI.ARIAUtils.setAccessibleName(paletteSwitcher, ls`Preview palettes`);
    paletteSwitcher.tabIndex = 0;
    self.onInvokeElement(paletteSwitcher, event => {
      this._togglePalettePanel(true);
      event.consume(true);
    });

    this._deleteIconToolbar = new UI.Toolbar('delete-color-toolbar');
    this._deleteButton = new UI.ToolbarButton('', 'largeicon-trash-bin');
    this._deleteIconToolbar.appendToolbarItem(this._deleteButton);

    const overlay = this.contentElement.createChild('div', 'spectrum-overlay fill');
    overlay.addEventListener('click', this._togglePalettePanel.bind(this, false));

    this._addColorToolbar = new UI.Toolbar('add-color-toolbar');
    const addColorButton = new UI.ToolbarButton(Common.UIString('Add to palette'), 'largeicon-add');
    addColorButton.addEventListener(UI.ToolbarButton.Events.Click, this._onAddColorMousedown.bind(this));
    addColorButton.element.addEventListener('keydown', this._onAddColorKeydown.bind(this));
    this._addColorToolbar.appendToolbarItem(addColorButton);

    this._colorPickedBound = this._colorPicked.bind(this);

    this._loadPalettes();
    new PaletteGenerator(palette => {
      if (palette.colors.length) {
        this.addPalette(palette);
      } else if (this._selectedColorPalette.get() === palette.title) {
        this._paletteSelected(MaterialPalette);
      }
    });

    /**
     * @param {function(!Event)} callback
     * @param {!Event} event
     * @return {boolean}
     * @this {ColorPicker.Spectrum}
     */
    function dragStart(callback, event) {
      this._colorOffset = this._colorElement.totalOffset();
      callback(event);
      return true;
    }

    /**
     * @param {!Element} element
     * @param {!Event} event
     * @return {number};
     */
    function getUpdatedSliderPosition(element, event) {
      const elementPosition = element.getBoundingClientRect();
      switch (event.key) {
        case 'ArrowLeft':
        case 'ArrowDown':
          return elementPosition.left - 1;
        case 'ArrowRight':
        case 'ArrowUp':
          return elementPosition.right + 1;
        default:
          return event.x;
      }
    }

    /**
     * @param {!Event} event
     * @this {ColorPicker.Spectrum}
     */
    function positionHue(event) {
      const hsva = this._hsv.slice();
      const sliderPosition = getUpdatedSliderPosition(this._hueSlider, event);
      const hueAlphaLeft = this._hueElement.getBoundingClientRect().left;
      const positionFraction = (sliderPosition - hueAlphaLeft) / this._hueAlphaWidth;
      const newHue = 1 - positionFraction;
      hsva[0] = Number.constrain(newHue, 0, 1);
      this._innerSetColor(hsva, '', undefined /* colorName */, undefined, _ChangeSource.Other);
      const colorValues = this._color().canonicalHSLA();
      UI.ARIAUtils.setValueNow(this._hueElement, colorValues[0]);
    }

    /**
     * @param {!Event} event
     * @this {ColorPicker.Spectrum}
     */
    function positionAlpha(event) {
      const hsva = this._hsv.slice();
      const sliderPosition = getUpdatedSliderPosition(this._alphaSlider, event);
      const hueAlphaLeft = this._hueElement.getBoundingClientRect().left;
      const positionFraction = (sliderPosition - hueAlphaLeft) / this._hueAlphaWidth;
      const newAlpha = Math.round(positionFraction * 100) / 100;
      hsva[3] = Number.constrain(newAlpha, 0, 1);
      this._innerSetColor(hsva, '', undefined /* colorName */, undefined, _ChangeSource.Other);
      const colorValues = this._color().canonicalHSLA();
      UI.ARIAUtils.setValueText(this._alphaElement, colorValues[3]);
    }

    /**
     * @param {!Event} event
     * @this {ColorPicker.Spectrum}
     */
    function positionColor(event) {
      const hsva = this._hsv.slice();
      hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragWidth, 0, 1);
      hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dragHeight, 0, 1);

      this._innerSetColor(hsva, '', undefined /* colorName */, undefined, _ChangeSource.Other);
    }
  }

  _contrastDetailsBackgroundColorPickedToggled({data: enabled}) {
    if (enabled) {
      this._toggleColorPicker(false);
    }
  }

  _contrastPanelExpanded() {
    this._contrastOverlay.setVisible(this._contrastDetails.expanded());
    this._resizeForSelectedPalette(true);
  }

  _updatePalettePanel() {
    this._palettePanel.removeChildren();
    const title = this._palettePanel.createChild('div', 'palette-title');
    title.textContent = Common.UIString('Color Palettes');
    const toolbar = new UI.Toolbar('', this._palettePanel);
    this._closeButton = new UI.ToolbarButton(ls`Return to color picker`, 'largeicon-delete');
    this._closeButton.addEventListener(UI.ToolbarButton.Events.Click, this._togglePalettePanel.bind(this, false));
    this._closeButton.element.addEventListener('keydown', this._onCloseBtnKeydown.bind(this));
    toolbar.appendToolbarItem(this._closeButton);
    for (const palette of this._palettes.values()) {
      this._palettePanel.appendChild(this._createPreviewPaletteElement(palette));
    }
  }

  /**
   * @param {boolean} show
   */
  _togglePalettePanel(show) {
    if (this._palettePanelShowing === show) {
      return;
    }
    if (show) {
      this._updatePalettePanel();
    }
    this._palettePanelShowing = show;
    this.contentElement.classList.toggle('palette-panel-showing', show);
    this._focus();
  }

  /**
   * @param {!Event} event
   */
  _onCloseBtnKeydown(event) {
    if (isEscKey(event) || isEnterOrSpaceKey(event)) {
      this._togglePalettePanel(false);
      event.consume(true);
    }
  }

  /**
   * @param {function(!Event)} sliderNewPosition
   * @param {!Event} event
   */
  _onSliderKeydown(sliderNewPosition, event) {
    switch (event.key) {
      case 'ArrowLeft':
      case 'ArrowRight':
      case 'ArrowDown':
      case 'ArrowUp':
        sliderNewPosition(event);
        event.consume(true);
    }
  }

  /**
   * (Suppress warning about preventScroll)
   * @suppress {checkTypes}
   */
  _focus() {
    if (!this.isShowing()) {
      return;
    }
    if (this._palettePanelShowing) {
      this._closeButton.element.focus({preventScroll: true});
    } else {
      this.contentElement.focus();
    }
  }

  /**
   * @param {string} colorText
   * @param {string=} colorName
   * @param {number=} animationDelay
   * @return {!Element}
   */
  _createPaletteColor(colorText, colorName, animationDelay) {
    const element = createElementWithClass('div', 'spectrum-palette-color');
    element.style.background = String.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
    if (animationDelay) {
      element.animate([{opacity: 0}, {opacity: 1}], {duration: 100, delay: animationDelay, fill: 'backwards'});
    }
    element.title = colorName || colorText;
    return element;
  }

  /**
   * @param {!ColorPicker.Spectrum.Palette} palette
   * @param {boolean} animate
   * @param {!Event=} event
   */
  _showPalette(palette, animate, event) {
    this._resizeForSelectedPalette();
    this._paletteContainer.removeChildren();
    for (let i = 0; i < palette.colors.length; i++) {
      const animationDelay = animate ? i * 100 / palette.colors.length : 0;
      const colorElement = this._createPaletteColor(palette.colors[i], palette.colorNames[i], animationDelay);
      UI.ARIAUtils.markAsButton(colorElement);
      UI.ARIAUtils.setAccessibleName(colorElement, ls`Color ${palette.colors[i]}`);
      colorElement.tabIndex = -1;
      colorElement.addEventListener(
          'mousedown',
          this._paletteColorSelected.bind(this, palette.colors[i], palette.colorNames[i], palette.matchUserFormat));
      colorElement.addEventListener(
          'keydown',
          this._onPaletteColorKeydown.bind(this, palette.colors[i], palette.colorNames[i], palette.matchUserFormat));
      if (palette.mutable) {
        colorElement.__mutable = true;
        colorElement.__color = palette.colors[i];
        colorElement.addEventListener('contextmenu', this._showPaletteColorContextMenu.bind(this, i));
      } else if (palette === MaterialPalette) {
        colorElement.classList.add('has-material-shades');
        let shadow = colorElement.createChild('div', 'spectrum-palette-color spectrum-palette-color-shadow');
        shadow.style.background = palette.colors[i];
        shadow = colorElement.createChild('div', 'spectrum-palette-color spectrum-palette-color-shadow');
        shadow.style.background = palette.colors[i];
        colorElement.title = ls`${palette.colors[i]}. Long-click to show alternate shades.`;
        UI.ARIAUtils.setAccessibleName(colorElement, colorElement.title);
        new UI.LongClickController(colorElement, this._showLightnessShades.bind(this, colorElement, palette.colors[i]));
      }
      this._paletteContainer.appendChild(colorElement);
    }
    if (this._paletteContainer.childNodes.length > 0) {
      this._paletteContainer.childNodes[0].tabIndex = 0;
    }
    this._paletteContainerMutable = palette.mutable;

    if (palette.mutable) {
      this._paletteContainer.appendChild(this._addColorToolbar.element);
      this._paletteContainer.appendChild(this._deleteIconToolbar.element);
    } else {
      this._addColorToolbar.element.remove();
      this._deleteIconToolbar.element.remove();
    }

    this._togglePalettePanel(false);
    this._focus();
  }

  /**
   * @param {!Element} colorElement
   * @param {string} colorText
   * @param {!Event} event
   */
  _showLightnessShades(colorElement, colorText, event) {
    /**
     * @param {!Element} element
     * @this {!ColorPicker.Spectrum}
     */
    function closeLightnessShades(element) {
      this._shadesContainer.classList.add('hidden');
      element.classList.remove('spectrum-shades-shown');
      this._shadesContainer.ownerDocument.removeEventListener('mousedown', this._shadesCloseHandler, true);
      delete this._shadesCloseHandler;
    }

    if (this._shadesCloseHandler) {
      this._shadesCloseHandler();
    }

    this._shadesContainer.classList.remove('hidden');
    this._shadesContainer.removeChildren();
    this._shadesContainer.animate(
        [{transform: 'scaleY(0)', opacity: '0'}, {transform: 'scaleY(1)', opacity: '1'}],
        {duration: 200, easing: 'cubic-bezier(0.4, 0, 0.2, 1)'});
    let shadesTop = this._paletteContainer.offsetTop + colorElement.offsetTop + colorElement.parentElement.offsetTop;
    if (this._contrastDetails) {
      shadesTop += this._contrastDetails.element().offsetHeight;
    }
    this._shadesContainer.style.top = shadesTop + 'px';
    this._shadesContainer.style.left = colorElement.offsetLeft + 'px';
    colorElement.classList.add('spectrum-shades-shown');

    const shades = MaterialPaletteShades[colorText];
    for (let i = shades.length - 1; i >= 0; i--) {
      const shadeElement =
          this._createPaletteColor(shades[i], undefined /* colorName */, i * 200 / shades.length + 100);
      UI.ARIAUtils.markAsButton(shadeElement);
      UI.ARIAUtils.setAccessibleName(shadeElement, ls`Color ${shades[i]}`);
      shadeElement.tabIndex = -1;
      shadeElement.addEventListener('mousedown', this._paletteColorSelected.bind(this, shades[i], shades[i], false));
      shadeElement.addEventListener(
          'keydown', this._onShadeColorKeydown.bind(this, shades[i], shades[i], false, colorElement));
      this._shadesContainer.appendChild(shadeElement);
    }

    if (this._shadesContainer.childNodes.length > 0) {
      this._shadesContainer.childNodes[this._shadesContainer.childNodes.length - 1].focus();
    }
    this._shadesCloseHandler = closeLightnessShades.bind(this, colorElement);
    this._shadesContainer.ownerDocument.addEventListener('mousedown', this._shadesCloseHandler, true);
  }

  /**
   * @param {!Event} e
   * @return {number}
   */
  _slotIndexForEvent(e) {
    const localX = e.pageX - this._paletteContainer.totalOffsetLeft();
    const localY = e.pageY - this._paletteContainer.totalOffsetTop();
    const col = Math.min(localX / _colorChipSize | 0, _itemsPerPaletteRow - 1);
    const row = (localY / _colorChipSize) | 0;
    return Math.min(row * _itemsPerPaletteRow + col, this._customPaletteSetting.get().colors.length - 1);
  }

  /**
   * @param {!Event} e
   * @return {boolean}
   */
  _isDraggingToBin(e) {
    return e.pageX > this._deleteIconToolbar.element.totalOffsetLeft();
  }

  /**
   * @param {!Event} e
   * @return {boolean}
   */
  _paletteDragStart(e) {
    const element = e.deepElementFromPoint();
    if (!element || !element.__mutable) {
      return false;
    }

    const index = this._slotIndexForEvent(e);
    this._dragElement = element;
    this._dragHotSpotX = e.pageX - (index % _itemsPerPaletteRow) * _colorChipSize;
    this._dragHotSpotY = e.pageY - (index / _itemsPerPaletteRow | 0) * _colorChipSize;
    return true;
  }

  /**
   * @param {!Event} e
   */
  _paletteDrag(e) {
    if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._paletteContainer.totalOffsetTop()) {
      return;
    }
    const newIndex = this._slotIndexForEvent(e);
    const offsetX = e.pageX - (newIndex % _itemsPerPaletteRow) * _colorChipSize;
    const offsetY = e.pageY - (newIndex / _itemsPerPaletteRow | 0) * _colorChipSize;

    const isDeleting = this._isDraggingToBin(e);
    this._deleteIconToolbar.element.classList.add('dragging');
    this._deleteIconToolbar.element.classList.toggle('delete-color-toolbar-active', isDeleting);
    const dragElementTransform =
        'translateX(' + (offsetX - this._dragHotSpotX) + 'px) translateY(' + (offsetY - this._dragHotSpotY) + 'px)';
    this._dragElement.style.transform = isDeleting ? dragElementTransform + ' scale(0.8)' : dragElementTransform;
    const children = Array.prototype.slice.call(this._paletteContainer.children);
    const index = children.indexOf(this._dragElement);
    /** @type {!Map.<!Element, {left: number, top: number}>} */
    const swatchOffsets = new Map();
    for (const swatch of children) {
      swatchOffsets.set(swatch, swatch.totalOffset());
    }

    if (index !== newIndex) {
      this._paletteContainer.insertBefore(this._dragElement, children[newIndex > index ? newIndex + 1 : newIndex]);
    }

    for (const swatch of children) {
      if (swatch === this._dragElement) {
        continue;
      }
      const before = swatchOffsets.get(swatch);
      const after = swatch.totalOffset();
      if (before.left !== after.left || before.top !== after.top) {
        swatch.animate(
            [
              {
                transform:
                    'translateX(' + (before.left - after.left) + 'px) translateY(' + (before.top - after.top) + 'px)'
              },
              {transform: 'none'}
            ],
            {duration: 100, easing: 'cubic-bezier(0, 0, 0.2, 1)'});
      }
    }
  }

  /**
   * @param {!Event} e
   */
  _paletteDragEnd(e) {
    if (this._isDraggingToBin(e)) {
      this._dragElement.remove();
    }
    this._dragElement.style.removeProperty('transform');
    const children = this._paletteContainer.children;
    const colors = [];
    for (let i = 0; i < children.length; ++i) {
      if (children[i].__color) {
        colors.push(children[i].__color);
      }
    }
    const palette = this._customPaletteSetting.get();
    palette.colors = colors;
    this._customPaletteSetting.set(palette);
    this._showPalette(this._customPaletteSetting.get(), false);

    this._deleteIconToolbar.element.classList.remove('dragging');
    this._deleteIconToolbar.element.classList.remove('delete-color-toolbar-active');
  }

  _loadPalettes() {
    this._palettes.set(MaterialPalette.title, MaterialPalette);
    /** @type {!ColorPicker.Spectrum.Palette} */
    const defaultCustomPalette = {title: 'Custom', colors: [], colorNames: [], mutable: true};
    this._customPaletteSetting = Common.settings.createSetting('customColorPalette', defaultCustomPalette);
    const customPalette = this._customPaletteSetting.get();
    // Fallback case for custom palettes created pre-m67
    customPalette.colorNames = customPalette.colorNames || [];
    this._palettes.set(customPalette.title, customPalette);

    this._selectedColorPalette = Common.settings.createSetting('selectedColorPalette', GeneratedPaletteTitle);
    const palette = this._palettes.get(this._selectedColorPalette.get());
    if (palette) {
      this._showPalette(palette, true);
    }
  }

  /**
   * @param {!ColorPicker.Spectrum.Palette} palette
   */
  addPalette(palette) {
    this._palettes.set(palette.title, palette);
    if (this._selectedColorPalette.get() === palette.title) {
      this._showPalette(palette, true);
    }
  }

  /**
   * @param {!ColorPicker.Spectrum.Palette} palette
   * @return {!Element}
   */
  _createPreviewPaletteElement(palette) {
    const colorsPerPreviewRow = 5;
    const previewElement = createElementWithClass('div', 'palette-preview');
    UI.ARIAUtils.markAsButton(previewElement);
    previewElement.tabIndex = 0;
    const titleElement = previewElement.createChild('div', 'palette-preview-title');
    titleElement.textContent = palette.title;
    let i;
    for (i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++) {
      previewElement.appendChild(this._createPaletteColor(palette.colors[i], palette.colorNames[i]));
    }
    for (; i < colorsPerPreviewRow; i++) {
      previewElement.createChild('div', 'spectrum-palette-color empty-color');
    }
    self.onInvokeElement(previewElement, event => {
      this._paletteSelected(palette);
      event.consume(true);
    });
    return previewElement;
  }

  /**
   * @param {!ColorPicker.Spectrum.Palette} palette
   */
  _paletteSelected(palette) {
    this._selectedColorPalette.set(palette.title);
    this._showPalette(palette, true);
  }

  /**
   * @param {boolean=} force
   */
  _resizeForSelectedPalette(force) {
    const palette = this._palettes.get(this._selectedColorPalette.get());
    if (!palette) {
      return;
    }
    let numColors = palette.colors.length;
    if (palette === this._customPaletteSetting.get()) {
      numColors++;
    }
    const rowsNeeded = Math.max(1, Math.ceil(numColors / _itemsPerPaletteRow));
    if (this._numPaletteRowsShown === rowsNeeded && !force) {
      return;
    }
    this._numPaletteRowsShown = rowsNeeded;
    const paletteColorHeight = 12;
    const paletteMargin = 12;
    let paletteTop = 236;
    if (this._contrastDetails) {
      if (this._contrastDetails.expanded()) {
        paletteTop += 78;
      } else {
        paletteTop += 36;
      }
    }
    this.element.style.height = (paletteTop + paletteMargin + (paletteColorHeight + paletteMargin) * rowsNeeded) + 'px';
    this.dispatchEventToListeners(Events.SizeChanged);
  }

  /**
   * @param {string} colorText
   * @param {(string|undefined)} colorName
   * @param {boolean} matchUserFormat
   */
  _paletteColorSelected(colorText, colorName, matchUserFormat) {
    const color = Common.Color.parse(colorText);
    if (!color) {
      return;
    }
    this._innerSetColor(
        color.hsva(), colorText, colorName, matchUserFormat ? this._colorFormat : color.format(), _ChangeSource.Other);
  }

  /**
   * @param {string} colorText
   * @param {(string|undefined)} colorName
   * @param {boolean} matchUserFormat
   * @param {!Event} event
   */
  _onPaletteColorKeydown(colorText, colorName, matchUserFormat, event) {
    if (isEnterOrSpaceKey(event)) {
      this._paletteColorSelected(colorText, colorName, matchUserFormat);
      // If this is a long keypress on color palette of type Material then, it needs to handled by _showLightnessShades on same element. So, just stopPropagation instead of consuming it.
      event.stopPropagation();
    } else if (event.key === 'ArrowLeft' && event.target.previousElementSibling) {
      event.target.previousElementSibling.focus();
      event.consume(true);
    } else if (event.key === 'ArrowRight' && event.target.nextElementSibling) {
      event.target.nextElementSibling.focus();
      event.consume(true);
    }
  }

  /**
   * @param {string} colorText
   * @param {(string|undefined)} colorName
   * @param {boolean} matchUserFormat
   * @param {!Element} colorElement
   * @param {!Event} event
   */
  _onShadeColorKeydown(colorText, colorName, matchUserFormat, colorElement, event) {
    if (isEnterOrSpaceKey(event)) {
      this._paletteColorSelected(colorText, colorName, matchUserFormat);
      event.consume(true);
    } else if (isEscKey(event) || event.key === 'Tab') {
      colorElement.focus();
      this._shadesCloseHandler();
      event.consume(true);
    } else if (event.key === 'ArrowUp' && event.target.previousElementSibling) {
      event.target.previousElementSibling.focus();
      event.consume(true);
    } else if (event.key === 'ArrowDown' && event.target.nextElementSibling) {
      event.target.nextElementSibling.focus();
      event.consume(true);
    }
  }

  _onAddColorMousedown() {
    this._addColorToCustomPalette();
  }

  /**
   * @param {!Event} event
   */
  _onAddColorKeydown(event) {
    if (isEnterOrSpaceKey(event)) {
      this._addColorToCustomPalette();
      event.consume(true);
    }
  }

  _addColorToCustomPalette() {
    const palette = this._customPaletteSetting.get();
    palette.colors.push(this.colorString());
    this._customPaletteSetting.set(palette);
    this._showPalette(this._customPaletteSetting.get(), false);
    const colorElements = this._paletteContainer.querySelectorAll('.spectrum-palette-color');
    colorElements[colorElements.length - 1].focus();
  }

  /**
   * @param {number} colorIndex
   * @param {!Event} event
   */
  _showPaletteColorContextMenu(colorIndex, event) {
    if (!this._paletteContainerMutable) {
      return;
    }
    const contextMenu = new UI.ContextMenu(event);
    if (colorIndex !== -1) {
      contextMenu.defaultSection().appendItem(
          Common.UIString('Remove color'), this._deletePaletteColors.bind(this, colorIndex, false));
      contextMenu.defaultSection().appendItem(
          Common.UIString('Remove all to the right'), this._deletePaletteColors.bind(this, colorIndex, true));
    }
    contextMenu.defaultSection().appendItem(
        Common.UIString('Clear palette'), this._deletePaletteColors.bind(this, -1, true));
    contextMenu.show();
  }

  /**
   * @param {number} colorIndex
   * @param {boolean} toRight
   */
  _deletePaletteColors(colorIndex, toRight) {
    const palette = this._customPaletteSetting.get();
    if (toRight) {
      palette.colors.splice(colorIndex + 1, palette.colors.length - colorIndex - 1);
    } else {
      palette.colors.splice(colorIndex, 1);
    }
    this._customPaletteSetting.set(palette);
    this._showPalette(this._customPaletteSetting.get(), false);
  }

  /**
   * @param {!Common.Color} color
   * @param {string} colorFormat
   */
  setColor(color, colorFormat) {
    this._originalFormat = colorFormat;
    this._innerSetColor(color.hsva(), '', undefined /* colorName */, colorFormat, _ChangeSource.Model);
    const colorValues = this._color().canonicalHSLA();
    UI.ARIAUtils.setValueNow(this._hueElement, colorValues[0]);
    UI.ARIAUtils.setValueText(this._alphaElement, colorValues[3]);
  }

  /**
   * @param {!Array<number>|undefined} hsva
   * @param {string|undefined} colorString
   * @param {string|undefined} colorName
   * @param {string|undefined} colorFormat
   * @param {string} changeSource
   */
  _innerSetColor(hsva, colorString, colorName, colorFormat, changeSource) {
    if (hsva !== undefined) {
      this._hsv = hsva;
    }
    this._colorName = colorName;
    if (colorString !== undefined) {
      this._colorString = colorString;
    }
    if (colorFormat !== undefined) {
      const cf = Common.Color.Format;
      console.assert(colorFormat !== cf.Original, 'Spectrum\'s color format cannot be Original');
      if (colorFormat === cf.RGBA) {
        colorFormat = cf.RGB;
      } else if (colorFormat === cf.HSLA) {
        colorFormat = cf.HSL;
      } else if (colorFormat === cf.HEXA) {
        colorFormat = cf.HEX;
      } else if (colorFormat === cf.ShortHEXA) {
        colorFormat = cf.ShortHEX;
      }
      this._colorFormat = colorFormat;
    }

    if (hsva && this._contrastInfo) {
      this._contrastInfo.setColor(Common.Color.fromHSVA(hsva));
    }

    this._updateHelperLocations();
    this._updateUI();

    if (changeSource !== _ChangeSource.Input) {
      this._updateInput();
    }
    if (changeSource !== _ChangeSource.Model) {
      this.dispatchEventToListeners(Events.ColorChanged, this.colorString());
    }
  }

  /**
   * @return {!Common.Color}
   */
  _color() {
    return Common.Color.fromHSVA(this._hsv);
  }

  /**
   * @return {string|undefined}
   */
  colorName() {
    return this._colorName;
  }

  /**
   * @return {string}
   */
  colorString() {
    if (this._colorString) {
      return this._colorString;
    }
    const cf = Common.Color.Format;
    const color = this._color();
    let colorString = color.asString(this._colorFormat);
    if (colorString) {
      return colorString;
    }

    if (this._colorFormat === cf.Nickname) {
      colorString = color.asString(color.hasAlpha() ? cf.HEXA : cf.HEX);
    } else if (this._colorFormat === cf.ShortHEX) {
      colorString = color.asString(color.detectHEXFormat());
    } else if (this._colorFormat === cf.HEX) {
      colorString = color.asString(cf.HEXA);
    } else if (this._colorFormat === cf.HSL) {
      colorString = color.asString(cf.HSLA);
    } else {
      colorString = color.asString(cf.RGBA);
    }

    console.assert(colorString);
    return colorString || '';
  }

  _updateHelperLocations() {
    const h = this._hsv[0];
    const s = this._hsv[1];
    const v = this._hsv[2];
    const alpha = this._hsv[3];

    // Where to show the little circle that displays your current selected color.
    this._dragX = s * this.dragWidth;
    this._dragY = this.dragHeight - (v * this.dragHeight);

    const dragX = Math.max(
        -this._colorDragElementHeight,
        Math.min(this.dragWidth - this._colorDragElementHeight, this._dragX - this._colorDragElementHeight));
    const dragY = Math.max(
        -this._colorDragElementHeight,
        Math.min(this.dragHeight - this._colorDragElementHeight, this._dragY - this._colorDragElementHeight));

    this._colorDragElement.positionAt(dragX, dragY);

    // Where to show the bar that displays your current selected hue.
    const hueSlideX = (1 - h) * this._hueAlphaWidth - this.slideHelperWidth;
    this._hueSlider.style.left = hueSlideX + 'px';
    const alphaSlideX = alpha * this._hueAlphaWidth - this.slideHelperWidth;
    this._alphaSlider.style.left = alphaSlideX + 'px';
  }

  _updateInput() {
    const cf = Common.Color.Format;
    if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || this._colorFormat === cf.Nickname) {
      this._hexContainer.hidden = false;
      this._displayContainer.hidden = true;
      if (this._colorFormat === cf.ShortHEX) {
        this._hexValue.value = this._color().asString(this._color().detectHEXFormat());
      } else {  // Don't use ShortHEX if original was not in that format.
        this._hexValue.value = this._color().asString(this._color().hasAlpha() ? cf.HEXA : cf.HEX);
      }
    } else {
      // RGBA, HSLA display.
      this._hexContainer.hidden = true;
      this._displayContainer.hidden = false;
      const isRgb = this._colorFormat === cf.RGB;
      this._textLabels.textContent = isRgb ? 'RGBA' : 'HSLA';
      const colorValues = isRgb ? this._color().canonicalRGBA() : this._color().canonicalHSLA();
      for (let i = 0; i < 3; ++i) {
        UI.ARIAUtils.setAccessibleName(
            this._textValues[i],
            /** R in RGBA */ ls`${this._textLabels.textContent.charAt(i)} in ${this._textLabels.textContent}`);
        this._textValues[i].value = colorValues[i];
        if (!isRgb && (i === 1 || i === 2)) {
          this._textValues[i].value += '%';
        }
      }
      UI.ARIAUtils.setAccessibleName(
          this._textValues[3],
          /** A in RGBA */ ls`${this._textLabels.textContent.charAt(3)} in ${this._textLabels.textContent}`);
      this._textValues[3].value = Math.round(colorValues[3] * 100) / 100;
    }
  }

  _updateUI() {
    const h = Common.Color.fromHSVA([this._hsv[0], 1, 1, 1]);
    this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(Common.Color.Format.RGB));
    if (this._contrastOverlay) {
      this._contrastOverlay.setDimensions(this.dragWidth, this.dragHeight);
    }

    this._swatch.setColor(this._color(), this.colorString());
    this._colorDragElement.style.backgroundColor =
        /** @type {string} */ (this._color().asString(Common.Color.Format.RGBA));
    const noAlpha = Common.Color.fromHSVA(this._hsv.slice(0, 3).concat(1));
    this._alphaElementBackground.style.backgroundImage =
        String.sprintf('linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.asString(Common.Color.Format.RGB));
  }

  _formatViewSwitch() {
    const cf = Common.Color.Format;
    let format = cf.RGB;
    if (this._colorFormat === cf.RGB) {
      format = cf.HSL;
    } else if (this._colorFormat === cf.HSL) {
      format = (this._originalFormat === cf.ShortHEX || this._originalFormat === cf.ShortHEXA) ? cf.ShortHEX : cf.HEX;
    }
    this._innerSetColor(undefined, '', undefined /* colorName */, format, _ChangeSource.Other);
  }

  /**
   * @param {!Event} event
   */
  _inputChanged(event) {
    /**
     * @param {!Element} element
     * @return {string}
     */
    function elementValue(element) {
      return element.value;
    }

    const inputElement = /** @type {!Element} */ (event.currentTarget);
    const newValue = UI.createReplacementString(inputElement.value, event);
    if (newValue) {
      inputElement.value = newValue;
      inputElement.selectionStart = 0;
      inputElement.selectionEnd = newValue.length;
      event.consume(true);
    }

    const cf = Common.Color.Format;
    let colorString;
    if (this._colorFormat === cf.Nickname || this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
      colorString = this._hexValue.value;
    } else {
      const format = this._colorFormat === cf.RGB ? 'rgba' : 'hsla';
      const values = this._textValues.map(elementValue).join(', ');
      colorString = String.sprintf('%s(%s)', format, values);
    }

    const color = Common.Color.parse(colorString);
    if (!color) {
      return;
    }

    let colorFormat = undefined;
    if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
      colorFormat = color.detectHEXFormat();
    }
    this._innerSetColor(color.hsva(), colorString, undefined /* colorName */, colorFormat, _ChangeSource.Input);
  }

  /**
   * @override
   */
  wasShown() {
    this._hueAlphaWidth = this._hueElement.offsetWidth;
    this.slideHelperWidth = this._hueSlider.offsetWidth / 2;
    this.dragWidth = this._colorElement.offsetWidth;
    this.dragHeight = this._colorElement.offsetHeight;
    this._colorDragElementHeight = this._colorDragElement.offsetHeight / 2;
    this._innerSetColor(undefined, undefined, undefined /* colorName */, undefined, _ChangeSource.Model);
    this._toggleColorPicker(true);

    if (this._contrastDetails) {
      this._contrastDetails.addEventListener(
          ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled,
          this._contrastDetailsBackgroundColorPickedToggledBound);
    }
  }

  /**
   * @override
   */
  willHide() {
    this._toggleColorPicker(false);
    if (this._contrastDetails) {
      this._contrastDetails.removeEventListener(
          ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled,
          this._contrastDetailsBackgroundColorPickedToggledBound);
    }
  }

  /**
   * @param {boolean=} enabled
   * @param {!Common.Event=} event
   */
  _toggleColorPicker(enabled, event) {
    if (enabled === undefined) {
      enabled = !this._colorPickerButton.toggled();
    }
    this._colorPickerButton.setToggled(enabled);

    // This is to make sure that only one picker is open at a time
    // Also have a look at this._contrastDetailsBackgroundColorPickedToggled
    if (this._contrastDetails && enabled && this._contrastDetails.backgroundColorPickerEnabled()) {
      this._contrastDetails.toggleBackgroundColorPicker(false);
    }

    Host.InspectorFrontendHost.setEyeDropperActive(enabled);
    if (enabled) {
      Host.InspectorFrontendHost.events.addEventListener(
          Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
    } else {
      Host.InspectorFrontendHost.events.removeEventListener(
          Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _colorPicked(event) {
    const rgbColor = /** @type {!{r: number, g: number, b: number, a: number}} */ (event.data);
    const rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 100];
    const color = Common.Color.fromRGBA(rgba);
    this._innerSetColor(color.hsva(), '', undefined /* colorName */, undefined, _ChangeSource.Other);
    Host.InspectorFrontendHost.bringToFront();
  }
}

export const _ChangeSource = {
  Input: 'Input',
  Model: 'Model',
  Other: 'Other'
};

/** @enum {symbol} */
export const Events = {
  ColorChanged: Symbol('ColorChanged'),
  SizeChanged: Symbol('SizeChanged')
};

const _colorChipSize = 24;
const _itemsPerPaletteRow = 8;
const GeneratedPaletteTitle = 'Page colors';

export class PaletteGenerator {
  /**
   * @param {function(!ColorPicker.Spectrum.Palette)} callback
   */
  constructor(callback) {
    this._callback = callback;
    /** @type {!Map.<string, number>} */
    this._frequencyMap = new Map();
    const stylesheetPromises = [];
    for (const cssModel of SDK.targetManager.models(SDK.CSSModel)) {
      for (const stylesheet of cssModel.allStyleSheets()) {
        stylesheetPromises.push(this._processStylesheet(stylesheet));
      }
    }
    Promise.all(stylesheetPromises).catchException(null).then(this._finish.bind(this));
  }

  /**
   * @param {string} a
   * @param {string} b
   * @return {number}
   */
  _frequencyComparator(a, b) {
    return this._frequencyMap.get(b) - this._frequencyMap.get(a);
  }

  _finish() {
    /**
     * @param {string} a
     * @param {string} b
     * @return {number}
     */
    function hueComparator(a, b) {
      const hsva = paletteColors.get(a).hsva();
      const hsvb = paletteColors.get(b).hsva();

      // First trim the shades of gray
      if (hsvb[1] < 0.12 && hsva[1] < 0.12) {
        return hsvb[2] * hsvb[3] - hsva[2] * hsva[3];
      }
      if (hsvb[1] < 0.12) {
        return -1;
      }
      if (hsva[1] < 0.12) {
        return 1;
      }

      // Equal hue -> sort by sat
      if (hsvb[0] === hsva[0]) {
        return hsvb[1] * hsvb[3] - hsva[1] * hsva[3];
      }

      return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1;
    }

    let colors = this._frequencyMap.keysArray();
    colors = colors.sort(this._frequencyComparator.bind(this));
    /** @type {!Map.<string, !Common.Color>} */
    const paletteColors = new Map();
    const colorsPerRow = 24;
    while (paletteColors.size < colorsPerRow && colors.length) {
      const colorText = colors.shift();
      const color = Common.Color.parse(colorText);
      if (!color || color.nickname() === 'white' || color.nickname() === 'black') {
        continue;
      }
      paletteColors.set(colorText, color);
    }

    this._callback({
      title: GeneratedPaletteTitle,
      colors: paletteColors.keysArray().sort(hueComparator),
      colorNames: [],
      mutable: false
    });
  }

  /**
   * @param {!SDK.CSSStyleSheetHeader} stylesheet
   * @return {!Promise}
   */
  async _processStylesheet(stylesheet) {
    let text = (await stylesheet.requestContent()).content || '';
    text = text.toLowerCase();
    const regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || [];
    for (const c of regexResult) {
      let frequency = this._frequencyMap.get(c) || 0;
      this._frequencyMap.set(c, ++frequency);
    }
  }
}

export const MaterialPaletteShades = {
  '#F44336':
      ['#FFEBEE', '#FFCDD2', '#EF9A9A', '#E57373', '#EF5350', '#F44336', '#E53935', '#D32F2F', '#C62828', '#B71C1C'],
  '#E91E63':
      ['#FCE4EC', '#F8BBD0', '#F48FB1', '#F06292', '#EC407A', '#E91E63', '#D81B60', '#C2185B', '#AD1457', '#880E4F'],
  '#9C27B0':
      ['#F3E5F5', '#E1BEE7', '#CE93D8', '#BA68C8', '#AB47BC', '#9C27B0', '#8E24AA', '#7B1FA2', '#6A1B9A', '#4A148C'],
  '#673AB7':
      ['#EDE7F6', '#D1C4E9', '#B39DDB', '#9575CD', '#7E57C2', '#673AB7', '#5E35B1', '#512DA8', '#4527A0', '#311B92'],
  '#3F51B5':
      ['#E8EAF6', '#C5CAE9', '#9FA8DA', '#7986CB', '#5C6BC0', '#3F51B5', '#3949AB', '#303F9F', '#283593', '#1A237E'],
  '#2196F3':
      ['#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5', '#2196F3', '#1E88E5', '#1976D2', '#1565C0', '#0D47A1'],
  '#03A9F4':
      ['#E1F5FE', '#B3E5FC', '#81D4FA', '#4FC3F7', '#29B6F6', '#03A9F4', '#039BE5', '#0288D1', '#0277BD', '#01579B'],
  '#00BCD4':
      ['#E0F7FA', '#B2EBF2', '#80DEEA', '#4DD0E1', '#26C6DA', '#00BCD4', '#00ACC1', '#0097A7', '#00838F', '#006064'],
  '#009688':
      ['#E0F2F1', '#B2DFDB', '#80CBC4', '#4DB6AC', '#26A69A', '#009688', '#00897B', '#00796B', '#00695C', '#004D40'],
  '#4CAF50':
      ['#E8F5E9', '#C8E6C9', '#A5D6A7', '#81C784', '#66BB6A', '#4CAF50', '#43A047', '#388E3C', '#2E7D32', '#1B5E20'],
  '#8BC34A':
      ['#F1F8E9', '#DCEDC8', '#C5E1A5', '#AED581', '#9CCC65', '#8BC34A', '#7CB342', '#689F38', '#558B2F', '#33691E'],
  '#CDDC39':
      ['#F9FBE7', '#F0F4C3', '#E6EE9C', '#DCE775', '#D4E157', '#CDDC39', '#C0CA33', '#AFB42B', '#9E9D24', '#827717'],
  '#FFEB3B':
      ['#FFFDE7', '#FFF9C4', '#FFF59D', '#FFF176', '#FFEE58', '#FFEB3B', '#FDD835', '#FBC02D', '#F9A825', '#F57F17'],
  '#FFC107':
      ['#FFF8E1', '#FFECB3', '#FFE082', '#FFD54F', '#FFCA28', '#FFC107', '#FFB300', '#FFA000', '#FF8F00', '#FF6F00'],
  '#FF9800':
      ['#FFF3E0', '#FFE0B2', '#FFCC80', '#FFB74D', '#FFA726', '#FF9800', '#FB8C00', '#F57C00', '#EF6C00', '#E65100'],
  '#FF5722':
      ['#FBE9E7', '#FFCCBC', '#FFAB91', '#FF8A65', '#FF7043', '#FF5722', '#F4511E', '#E64A19', '#D84315', '#BF360C'],
  '#795548':
      ['#EFEBE9', '#D7CCC8', '#BCAAA4', '#A1887F', '#8D6E63', '#795548', '#6D4C41', '#5D4037', '#4E342E', '#3E2723'],
  '#9E9E9E':
      ['#FAFAFA', '#F5F5F5', '#EEEEEE', '#E0E0E0', '#BDBDBD', '#9E9E9E', '#757575', '#616161', '#424242', '#212121'],
  '#607D8B':
      ['#ECEFF1', '#CFD8DC', '#B0BEC5', '#90A4AE', '#78909C', '#607D8B', '#546E7A', '#455A64', '#37474F', '#263238']
};

export const MaterialPalette = {
  title: 'Material',
  mutable: false,
  matchUserFormat: true,
  colors: Object.keys(MaterialPaletteShades),
  colorNames: []
};

export class Swatch {
  /**
   * @param {!Element} parentElement
   */
  constructor(parentElement) {
    /** @type {?string} */
    this._colorString;

    const swatchElement = parentElement.createChild('span', 'swatch');
    this._swatchInnerElement = swatchElement.createChild('span', 'swatch-inner');

    this._swatchOverlayElement = swatchElement.createChild('span', 'swatch-overlay');
    UI.ARIAUtils.markAsButton(this._swatchOverlayElement);
    UI.ARIAUtils.setPressed(this._swatchOverlayElement, false);
    this._swatchOverlayElement.tabIndex = 0;
    self.onInvokeElement(this._swatchOverlayElement, this._onCopyText.bind(this));
    this._swatchOverlayElement.addEventListener('mouseout', this._onCopyIconMouseout.bind(this));
    this._swatchOverlayElement.addEventListener('blur', this._onCopyIconMouseout.bind(this));
    this._swatchCopyIcon = UI.Icon.create('largeicon-copy', 'copy-color-icon');
    this._swatchCopyIcon.title = ls`Copy color to clipboard`;
    this._swatchOverlayElement.appendChild(this._swatchCopyIcon);
    UI.ARIAUtils.setAccessibleName(this._swatchOverlayElement, this._swatchCopyIcon.title);
  }

  /**
   * @param {!Common.Color} color
   * @param {string=} colorString
   */
  setColor(color, colorString) {
    this._swatchInnerElement.style.backgroundColor =
        /** @type {string} */ (color.asString(Common.Color.Format.RGBA));
    // Show border if the swatch is white.
    this._swatchInnerElement.classList.toggle('swatch-inner-white', color.hsla()[2] > 0.9);
    this._colorString = colorString || null;
    if (colorString) {
      this._swatchOverlayElement.hidden = false;
    } else {
      this._swatchOverlayElement.hidden = true;
    }
  }

  /**
   * @param {!Event} event
   */
  _onCopyText(event) {
    this._swatchCopyIcon.setIconType('largeicon-checkmark');
    Host.InspectorFrontendHost.copyText(this._colorString);
    UI.ARIAUtils.setPressed(this._swatchOverlayElement, true);
    event.consume();
  }

  _onCopyIconMouseout() {
    this._swatchCopyIcon.setIconType('largeicon-copy');
    UI.ARIAUtils.setPressed(this._swatchOverlayElement, false);
  }
}

/* Legacy exported object */
self.ColorPicker = self.ColorPicker || {};

/* Legacy exported object */
ColorPicker = ColorPicker || {};

/** @constructor */
ColorPicker.Spectrum = Spectrum;

/** @constructor */
ColorPicker.Spectrum.PaletteGenerator = PaletteGenerator;

ColorPicker.Spectrum._ChangeSource = _ChangeSource;

/** @constructor */
ColorPicker.Spectrum.Swatch = Swatch;

ColorPicker.Spectrum.Events = Events;

/** @typedef {{ title: string, colors: !Array<string>, colorNames: !Array<string>, mutable: boolean }} */
ColorPicker.Spectrum.Palette;
