/*
 * Copyright (C) 2007 Apple Inc.  All rights reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * 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.
 */
import {ColorSwatchPopoverIcon, ShadowSwatchPopoverHelper} from './ColorSwatchPopoverIcon.js';
import {linkifyDeferredNodeReference} from './DOMLinkifier.js';
import {ElementsSidebarPane} from './ElementsSidebarPane.js';
import {StylePropertyHighlighter} from './StylePropertyHighlighter.js';
import {StylePropertyTreeElement} from './StylePropertyTreeElement.js';

export class StylesSidebarPane extends ElementsSidebarPane {
  constructor() {
    super(true /* delegatesFocus */);
    this.setMinimumSize(96, 26);
    this.registerRequiredCSS('elements/stylesSidebarPane.css');

    Common.moduleSetting('colorFormat').addChangeListener(this.update.bind(this));
    Common.moduleSetting('textEditorIndent').addChangeListener(this.update.bind(this));

    /** @type {?UI.Widget} */
    this._currentToolbarPane = null;
    /** @type {?UI.Widget} */
    this._animatedToolbarPane = null;
    /** @type {?UI.Widget} */
    this._pendingWidget = null;
    /** @type {?UI.ToolbarToggle} */
    this._pendingWidgetToggle = null;
    this._toolbarPaneElement = this._createStylesSidebarToolbar();

    this._noMatchesElement = this.contentElement.createChild('div', 'gray-info-message hidden');
    this._noMatchesElement.textContent = ls`No matching selector or style`;

    this._sectionsContainer = this.contentElement.createChild('div');
    UI.ARIAUtils.markAsTree(this._sectionsContainer);
    this._sectionsContainer.addEventListener('keydown', this._sectionsContainerKeyDown.bind(this), false);
    this._sectionsContainer.addEventListener('focusin', this._sectionsContainerFocusChanged.bind(this), false);
    this._sectionsContainer.addEventListener('focusout', this._sectionsContainerFocusChanged.bind(this), false);

    this._swatchPopoverHelper = new InlineEditor.SwatchPopoverHelper();
    this._linkifier = new Components.Linkifier(_maxLinkLength, /* useLinkDecorator */ true);
    /** @type {?StylePropertyHighlighter} */
    this._decorator = null;
    this._userOperation = false;
    this._isEditingStyle = false;
    /** @type {?RegExp} */
    this._filterRegex = null;
    this._isActivePropertyHighlighted = false;

    this.contentElement.classList.add('styles-pane');

    /** @type {!Array<!SectionBlock>} */
    this._sectionBlocks = [];
    this._needsForceUpdate = false;
    StylesSidebarPane._instance = this;
    UI.context.addFlavorChangeListener(SDK.DOMNode, this.forceUpdate, this);
    this.contentElement.addEventListener('copy', this._clipboardCopy.bind(this));
    this._resizeThrottler = new Common.Throttler(100);
  }

  /**
   * @return {!InlineEditor.SwatchPopoverHelper}
   */
  swatchPopoverHelper() {
    return this._swatchPopoverHelper;
  }

  /**
   * @param {boolean} userOperation
   */
  setUserOperation(userOperation) {
    this._userOperation = userOperation;
  }

  /**
   * @param {!SDK.CSSProperty} property
   * @return {!Element}
   */
  static createExclamationMark(property) {
    const exclamationElement = createElement('span', 'dt-icon-label');
    exclamationElement.className = 'exclamation-mark';
    if (!StylesSidebarPane.ignoreErrorsForProperty(property)) {
      exclamationElement.type = 'smallicon-warning';
    }
    exclamationElement.title = SDK.cssMetadata().isCSSPropertyName(property.name) ?
        Common.UIString('Invalid property value') :
        Common.UIString('Unknown property name');
    return exclamationElement;
  }

  /**
   * @param {!SDK.CSSProperty} property
   * @return {boolean}
   */
  static ignoreErrorsForProperty(property) {
    /**
     * @param {string} string
     */
    function hasUnknownVendorPrefix(string) {
      return !string.startsWith('-webkit-') && /^[-_][\w\d]+-\w/.test(string);
    }

    const name = property.name.toLowerCase();

    // IE hack.
    if (name.charAt(0) === '_') {
      return true;
    }

    // IE has a different format for this.
    if (name === 'filter') {
      return true;
    }

    // Common IE-specific property prefix.
    if (name.startsWith('scrollbar-')) {
      return true;
    }
    if (hasUnknownVendorPrefix(name)) {
      return true;
    }

    const value = property.value.toLowerCase();

    // IE hack.
    if (value.endsWith('\\9')) {
      return true;
    }
    if (hasUnknownVendorPrefix(value)) {
      return true;
    }

    return false;
  }

  /**
   * @param {string} placeholder
   * @param {!Element} container
   * @param {function(?RegExp)} filterCallback
   * @return {!Element}
   */
  static createPropertyFilterElement(placeholder, container, filterCallback) {
    const input = createElementWithClass('input');
    input.placeholder = placeholder;

    function searchHandler() {
      const regex = input.value ? new RegExp(input.value.escapeForRegExp(), 'i') : null;
      filterCallback(regex);
    }
    input.addEventListener('input', searchHandler, false);

    /**
     * @param {!Event} event
     */
    function keydownHandler(event) {
      if (event.key !== 'Escape' || !input.value) {
        return;
      }
      event.consume(true);
      input.value = '';
      searchHandler();
    }
    input.addEventListener('keydown', keydownHandler, false);

    input.setFilterValue = setFilterValue;

    /**
     * @param {string} value
     */
    function setFilterValue(value) {
      input.value = value;
      input.focus();
      searchHandler();
    }

    return input;
  }

  /**
   * @param {!SDK.CSSProperty} cssProperty
   */
  revealProperty(cssProperty) {
    this._decorator = new StylePropertyHighlighter(this, cssProperty);
    this._decorator.perform();
    this.update();
  }

  forceUpdate() {
    this._needsForceUpdate = true;
    this._swatchPopoverHelper.hide();
    this._resetCache();
    this.update();
  }

  /**
   * @param {!Event} event
   */
  _sectionsContainerKeyDown(event) {
    const activeElement = this._sectionsContainer.ownerDocument.deepActiveElement();
    if (!activeElement) {
      return;
    }
    const section = activeElement._section;
    if (!section) {
      return;
    }

    switch (event.key) {
      case 'ArrowUp':
      case 'ArrowLeft':
        const sectionToFocus = section.previousSibling() || section.lastSibling();
        sectionToFocus.element.focus();
        event.consume(true);
        break;
      case 'ArrowDown':
      case 'ArrowRight': {
        const sectionToFocus = section.nextSibling() || section.firstSibling();
        sectionToFocus.element.focus();
        event.consume(true);
        break;
      }
      case 'Home':
        section.firstSibling().element.focus();
        event.consume(true);
        break;
      case 'End':
        section.lastSibling().element.focus();
        event.consume(true);
        break;
    }
  }

  _sectionsContainerFocusChanged() {
    this.resetFocus();
  }

  resetFocus() {
    // When a styles section is focused, shift+tab should leave the section.
    // Leaving tabIndex = 0 on the first element would cause it to be focused instead.
    if (this._sectionBlocks[0] && this._sectionBlocks[0].sections[0]) {
      this._sectionBlocks[0].sections[0].element.tabIndex = this._sectionsContainer.hasFocus() ? -1 : 0;
    }
  }

  /**
   * @param {!Event} event
   */
  _onAddButtonLongClick(event) {
    const cssModel = this.cssModel();
    if (!cssModel) {
      return;
    }
    const headers = cssModel.styleSheetHeaders().filter(styleSheetResourceHeader);

    /** @type {!Array.<{text: string, handler: function()}>} */
    const contextMenuDescriptors = [];
    for (let i = 0; i < headers.length; ++i) {
      const header = headers[i];
      const handler = this._createNewRuleInStyleSheet.bind(this, header);
      contextMenuDescriptors.push({text: Bindings.displayNameForURL(header.resourceURL()), handler: handler});
    }

    contextMenuDescriptors.sort(compareDescriptors);

    const contextMenu = new UI.ContextMenu(event);
    for (let i = 0; i < contextMenuDescriptors.length; ++i) {
      const descriptor = contextMenuDescriptors[i];
      contextMenu.defaultSection().appendItem(descriptor.text, descriptor.handler);
    }
    contextMenu.footerSection().appendItem(
        'inspector-stylesheet', this._createNewRuleInViaInspectorStyleSheet.bind(this));
    contextMenu.show();

    /**
     * @param {!{text: string, handler: function()}} descriptor1
     * @param {!{text: string, handler: function()}} descriptor2
     * @return {number}
     */
    function compareDescriptors(descriptor1, descriptor2) {
      return String.naturalOrderComparator(descriptor1.text, descriptor2.text);
    }

    /**
     * @param {!SDK.CSSStyleSheetHeader} header
     * @return {boolean}
     */
    function styleSheetResourceHeader(header) {
      return !header.isViaInspector() && !header.isInline && !!header.resourceURL();
    }
  }

  /**
   * @param {?RegExp} regex
   */
  _onFilterChanged(regex) {
    this._filterRegex = regex;
    this._updateFilter();
  }

  /**
   * @param {!StylePropertiesSection} editedSection
   * @param {!StylePropertyTreeElement=} editedTreeElement
   */
  _refreshUpdate(editedSection, editedTreeElement) {
    if (editedTreeElement) {
      for (const section of this.allSections()) {
        if (section.isBlank) {
          continue;
        }
        section._updateVarFunctions(editedTreeElement);
      }
    }

    if (this._isEditingStyle) {
      return;
    }
    const node = this.node();
    if (!node) {
      return;
    }

    for (const section of this.allSections()) {
      if (section.isBlank) {
        continue;
      }
      section.update(section === editedSection);
    }

    if (this._filterRegex) {
      this._updateFilter();
    }
    this._nodeStylesUpdatedForTest(node, false);
  }

  /**
   * @override
   * @return {!Promise.<?>}
   */
  doUpdate() {
    return this._fetchMatchedCascade().then(this._innerRebuildUpdate.bind(this));
  }

  /**
   * @override
   */
  onResize() {
    this._resizeThrottler.schedule(this._innerResize.bind(this));
  }

  /**
   * @return {!Promise}
   */
  _innerResize() {
    const width = this.contentElement.getBoundingClientRect().width + 'px';
    this.allSections().forEach(section => section.propertiesTreeOutline.element.style.width = width);
    return Promise.resolve();
  }

  _resetCache() {
    if (this.cssModel()) {
      this.cssModel().discardCachedMatchedCascade();
    }
  }

  /**
   * @return {!Promise.<?SDK.CSSMatchedStyles>}
   */
  _fetchMatchedCascade() {
    const node = this.node();
    if (!node || !this.cssModel()) {
      return Promise.resolve(/** @type {?SDK.CSSMatchedStyles} */ (null));
    }

    return this.cssModel().cachedMatchedCascadeForNode(node).then(validateStyles.bind(this));

    /**
     * @param {?SDK.CSSMatchedStyles} matchedStyles
     * @return {?SDK.CSSMatchedStyles}
     * @this {StylesSidebarPane}
     */
    function validateStyles(matchedStyles) {
      return matchedStyles && matchedStyles.node() === this.node() ? matchedStyles : null;
    }
  }

  /**
   * @param {boolean} editing
   * @param {!StylePropertyTreeElement=} treeElement
   */
  setEditingStyle(editing, treeElement) {
    if (this._isEditingStyle === editing) {
      return;
    }
    this.contentElement.classList.toggle('is-editing-style', editing);
    this._isEditingStyle = editing;
    this._setActiveProperty(null);
  }

  /**
   * @param {?StylePropertyTreeElement} treeElement
   */
  _setActiveProperty(treeElement) {
    if (this._isActivePropertyHighlighted) {
      SDK.OverlayModel.hideDOMNodeHighlight();
    }
    this._isActivePropertyHighlighted = false;

    if (!this.node()) {
      return;
    }

    if (!treeElement || treeElement.overloaded() || treeElement.inherited()) {
      return;
    }

    const rule = treeElement.property.ownerStyle.parentRule;
    const selectorList = (rule instanceof SDK.CSSStyleRule) ? rule.selectorText() : undefined;
    for (const mode of ['padding', 'border', 'margin']) {
      if (!treeElement.name.startsWith(mode)) {
        continue;
      }
      this.node().domModel().overlayModel().highlightInOverlay(
          {node: /** @type {!SDK.DOMNode} */ (this.node()), selectorList}, mode);
      this._isActivePropertyHighlighted = true;
      break;
    }
  }

  /**
   * @override
   * @param {!Common.Event=} event
   */
  onCSSModelChanged(event) {
    const edit = event && event.data ? /** @type {?SDK.CSSModel.Edit} */ (event.data.edit) : null;
    if (edit) {
      for (const section of this.allSections()) {
        section._styleSheetEdited(edit);
      }
      return;
    }

    if (this._userOperation || this._isEditingStyle) {
      return;
    }

    this._resetCache();
    this.update();
  }

  /**
   * @return {number}
   */
  focusedSectionIndex() {
    let index = 0;
    for (const block of this._sectionBlocks) {
      for (const section of block.sections) {
        if (section.element.hasFocus()) {
          return index;
        }
        index++;
      }
    }
    return -1;
  }

  /**
   * @param {number} sectionIndex
   * @param {number} propertyIndex
   */
  continueEditingElement(sectionIndex, propertyIndex) {
    const section = this.allSections()[sectionIndex];
    if (section) {
      section.propertiesTreeOutline.rootElement().childAt(propertyIndex).startEditing();
    }
  }

  /**
   * @param {?SDK.CSSMatchedStyles} matchedStyles
   * @return {!Promise}
   */
  async _innerRebuildUpdate(matchedStyles) {
    // ElementsSidebarPane's throttler schedules this method. Usually,
    // rebuild is suppressed while editing (see onCSSModelChanged()), but we need a
    // 'force' flag since the currently running throttler process cannot be canceled.
    if (this._needsForceUpdate) {
      this._needsForceUpdate = false;
    } else if (this._isEditingStyle || this._userOperation) {
      return;
    }
    const focusedIndex = this.focusedSectionIndex();

    this._linkifier.reset();
    this._sectionsContainer.removeChildren();
    this._sectionBlocks = [];

    const node = this.node();
    if (!matchedStyles || !node) {
      this._noMatchesElement.classList.remove('hidden');
      return;
    }

    this._sectionBlocks =
        await this._rebuildSectionsForMatchedStyleRules(/** @type {!SDK.CSSMatchedStyles} */ (matchedStyles));
    let pseudoTypes = [];
    const keys = matchedStyles.pseudoTypes();
    if (keys.delete(Protocol.DOM.PseudoType.Before)) {
      pseudoTypes.push(Protocol.DOM.PseudoType.Before);
    }
    pseudoTypes = pseudoTypes.concat(keys.valuesArray().sort());
    for (const pseudoType of pseudoTypes) {
      const block = SectionBlock.createPseudoTypeBlock(pseudoType);
      for (const style of matchedStyles.pseudoStyles(pseudoType)) {
        const section = new StylePropertiesSection(this, matchedStyles, style);
        block.sections.push(section);
      }
      this._sectionBlocks.push(block);
    }

    for (const keyframesRule of matchedStyles.keyframes()) {
      const block = SectionBlock.createKeyframesBlock(keyframesRule.name().text);
      for (const keyframe of keyframesRule.keyframes()) {
        block.sections.push(new KeyframePropertiesSection(this, matchedStyles, keyframe.style));
      }
      this._sectionBlocks.push(block);
    }
    let index = 0;
    for (const block of this._sectionBlocks) {
      const titleElement = block.titleElement();
      if (titleElement) {
        this._sectionsContainer.appendChild(titleElement);
      }
      for (const section of block.sections) {
        this._sectionsContainer.appendChild(section.element);
        if (index === focusedIndex) {
          section.element.focus();
        }
        index++;
      }
    }
    if (focusedIndex >= index) {
      this._sectionBlocks[0].sections[0].element.focus();
    }

    this._sectionsContainerFocusChanged();

    if (this._filterRegex) {
      this._updateFilter();
    } else {
      this._noMatchesElement.classList.toggle('hidden', this._sectionBlocks.length > 0);
    }

    this._nodeStylesUpdatedForTest(/** @type {!SDK.DOMNode} */ (node), true);
    if (this._decorator) {
      this._decorator.perform();
      this._decorator = null;
    }
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {boolean} rebuild
   */
  _nodeStylesUpdatedForTest(node, rebuild) {
    // For sniffing in tests.
  }

  /**
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @return {!Promise<!Array.<!SectionBlock>>}
   */
  async _rebuildSectionsForMatchedStyleRules(matchedStyles) {
    const blocks = [new SectionBlock(null)];
    let lastParentNode = null;
    for (const style of matchedStyles.nodeStyles()) {
      const parentNode = matchedStyles.isInherited(style) ? matchedStyles.nodeForStyle(style) : null;
      if (parentNode && parentNode !== lastParentNode) {
        lastParentNode = parentNode;
        const block = await SectionBlock._createInheritedNodeBlock(lastParentNode);
        blocks.push(block);
      }
      const section = new StylePropertiesSection(this, matchedStyles, style);
      blocks.peekLast().sections.push(section);
    }
    return blocks;
  }

  async _createNewRuleInViaInspectorStyleSheet() {
    const cssModel = this.cssModel();
    const node = this.node();
    if (!cssModel || !node) {
      return;
    }
    this.setUserOperation(true);

    const styleSheetHeader = await cssModel.requestViaInspectorStylesheet(/** @type {!SDK.DOMNode} */ (node));

    this.setUserOperation(false);
    await this._createNewRuleInStyleSheet(styleSheetHeader);
  }

  /**
   * @param {?SDK.CSSStyleSheetHeader} styleSheetHeader
   */
  async _createNewRuleInStyleSheet(styleSheetHeader) {
    if (!styleSheetHeader) {
      return;
    }

    const text = (await styleSheetHeader.requestContent()).content || '';
    const lines = text.split('\n');
    const range = TextUtils.TextRange.createFromLocation(lines.length - 1, lines[lines.length - 1].length);
    this._addBlankSection(this._sectionBlocks[0].sections[0], styleSheetHeader.id, range);
  }

  /**
   * @param {!StylePropertiesSection} insertAfterSection
   * @param {string} styleSheetId
   * @param {!TextUtils.TextRange} ruleLocation
   */
  _addBlankSection(insertAfterSection, styleSheetId, ruleLocation) {
    const node = this.node();
    const blankSection = new BlankStylePropertiesSection(
        this, insertAfterSection._matchedStyles, node ? node.simpleSelector() : '', styleSheetId, ruleLocation,
        insertAfterSection._style);

    this._sectionsContainer.insertBefore(blankSection.element, insertAfterSection.element.nextSibling);

    for (const block of this._sectionBlocks) {
      const index = block.sections.indexOf(insertAfterSection);
      if (index === -1) {
        continue;
      }
      block.sections.splice(index + 1, 0, blankSection);
      blankSection.startEditingSelector();
    }
  }

  /**
   * @param {!StylePropertiesSection} section
   */
  removeSection(section) {
    for (const block of this._sectionBlocks) {
      const index = block.sections.indexOf(section);
      if (index === -1) {
        continue;
      }
      block.sections.splice(index, 1);
      section.element.remove();
    }
  }

  /**
   * @return {?RegExp}
   */
  filterRegex() {
    return this._filterRegex;
  }

  _updateFilter() {
    let hasAnyVisibleBlock = false;
    for (const block of this._sectionBlocks) {
      hasAnyVisibleBlock |= block.updateFilter();
    }
    this._noMatchesElement.classList.toggle('hidden', !!hasAnyVisibleBlock);
  }

  /**
   * @override
   */
  willHide() {
    this._swatchPopoverHelper.hide();
    super.willHide();
  }

  /**
   * @return {!Array<!StylePropertiesSection>}
   */
  allSections() {
    let sections = [];
    for (const block of this._sectionBlocks) {
      sections = sections.concat(block.sections);
    }
    return sections;
  }

  /**
   * @param {!Event} event
   */
  _clipboardCopy(event) {
    Host.userMetrics.actionTaken(Host.UserMetrics.Action.StyleRuleCopied);
  }

  /**
   * @return {!Element}
   */
  _createStylesSidebarToolbar() {
    const container = this.contentElement.createChild('div', 'styles-sidebar-pane-toolbar-container');
    const hbox = container.createChild('div', 'hbox styles-sidebar-pane-toolbar');
    const filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-filter-box');
    const filterInput =
        StylesSidebarPane.createPropertyFilterElement(ls`Filter`, hbox, this._onFilterChanged.bind(this));
    UI.ARIAUtils.setAccessibleName(filterInput, Common.UIString('Filter Styles'));
    filterContainerElement.appendChild(filterInput);
    const toolbar = new UI.Toolbar('styles-pane-toolbar', hbox);
    toolbar.makeToggledGray();
    toolbar.appendItemsAtLocation('styles-sidebarpane-toolbar');
    const toolbarPaneContainer = container.createChild('div', 'styles-sidebar-toolbar-pane-container');
    const toolbarPaneContent = toolbarPaneContainer.createChild('div', 'styles-sidebar-toolbar-pane');

    return toolbarPaneContent;
  }

  /**
   * @param {?UI.Widget} widget
   * @param {?UI.ToolbarToggle} toggle
   */
  showToolbarPane(widget, toggle) {
    if (this._pendingWidgetToggle) {
      this._pendingWidgetToggle.setToggled(false);
    }
    this._pendingWidgetToggle = toggle;

    if (this._animatedToolbarPane) {
      this._pendingWidget = widget;
    } else {
      this._startToolbarPaneAnimation(widget);
    }

    if (widget && toggle) {
      toggle.setToggled(true);
    }
  }

  /**
   * @param {?UI.Widget} widget
   */
  _startToolbarPaneAnimation(widget) {
    if (widget === this._currentToolbarPane) {
      return;
    }

    if (widget && this._currentToolbarPane) {
      this._currentToolbarPane.detach();
      widget.show(this._toolbarPaneElement);
      this._currentToolbarPane = widget;
      this._currentToolbarPane.focus();
      return;
    }

    this._animatedToolbarPane = widget;

    if (this._currentToolbarPane) {
      this._toolbarPaneElement.style.animationName = 'styles-element-state-pane-slideout';
    } else if (widget) {
      this._toolbarPaneElement.style.animationName = 'styles-element-state-pane-slidein';
    }

    if (widget) {
      widget.show(this._toolbarPaneElement);
    }

    const listener = onAnimationEnd.bind(this);
    this._toolbarPaneElement.addEventListener('animationend', listener, false);

    /**
     * @this {!StylesSidebarPane}
     */
    function onAnimationEnd() {
      this._toolbarPaneElement.style.removeProperty('animation-name');
      this._toolbarPaneElement.removeEventListener('animationend', listener, false);

      if (this._currentToolbarPane) {
        this._currentToolbarPane.detach();
      }

      this._currentToolbarPane = this._animatedToolbarPane;
      if (this._currentToolbarPane) {
        this._currentToolbarPane.focus();
      }
      this._animatedToolbarPane = null;

      if (this._pendingWidget) {
        this._startToolbarPaneAnimation(this._pendingWidget);
        this._pendingWidget = null;
      }
    }
  }
}

export const _maxLinkLength = 23;

export class SectionBlock {
  /**
   * @param {?Element} titleElement
   */
  constructor(titleElement) {
    this._titleElement = titleElement;
    this.sections = [];
  }

  /**
   * @param {!Protocol.DOM.PseudoType} pseudoType
   * @return {!SectionBlock}
   */
  static createPseudoTypeBlock(pseudoType) {
    const separatorElement = createElement('div');
    separatorElement.className = 'sidebar-separator';
    separatorElement.textContent = Common.UIString('Pseudo ::%s element', pseudoType);
    return new SectionBlock(separatorElement);
  }

  /**
   * @param {string} keyframesName
   * @return {!SectionBlock}
   */
  static createKeyframesBlock(keyframesName) {
    const separatorElement = createElement('div');
    separatorElement.className = 'sidebar-separator';
    separatorElement.textContent = `@keyframes ${keyframesName}`;
    return new SectionBlock(separatorElement);
  }

  /**
   * @param {!SDK.DOMNode} node
   * @return {!Promise<!SectionBlock>}
   */
  static async _createInheritedNodeBlock(node) {
    const separatorElement = createElement('div');
    separatorElement.className = 'sidebar-separator';
    separatorElement.createTextChild(ls`Inherited from${' '}`);
    const link = await Common.Linkifier.linkify(node, {preventKeyboardFocus: true});
    separatorElement.appendChild(link);
    return new SectionBlock(separatorElement);
  }

  /**
   * @return {boolean}
   */
  updateFilter() {
    let hasAnyVisibleSection = false;
    for (const section of this.sections) {
      hasAnyVisibleSection |= section._updateFilter();
    }
    if (this._titleElement) {
      this._titleElement.classList.toggle('hidden', !hasAnyVisibleSection);
    }
    return !!hasAnyVisibleSection;
  }

  /**
   * @return {?Element}
   */
  titleElement() {
    return this._titleElement;
  }
}

export class StylePropertiesSection {
  /**
   * @param {!StylesSidebarPane} parentPane
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @param {!SDK.CSSStyleDeclaration} style
   */
  constructor(parentPane, matchedStyles, style) {
    this._parentPane = parentPane;
    this._style = style;
    this._matchedStyles = matchedStyles;
    this.editable = !!(style.styleSheetId && style.range);
    /** @type {?number} */
    this._hoverTimer = null;
    this._willCauseCancelEditing = false;
    this._forceShowAll = false;
    this._originalPropertiesCount = style.leadingProperties().length;

    const rule = style.parentRule;
    this.element = createElementWithClass('div', 'styles-section matched-styles monospace');
    this.element.tabIndex = -1;
    UI.ARIAUtils.markAsTreeitem(this.element);
    this.element.addEventListener('keydown', this._onKeyDown.bind(this), false);
    this.element._section = this;
    this._innerElement = this.element.createChild('div');

    this._titleElement = this._innerElement.createChild('div', 'styles-section-title ' + (rule ? 'styles-selector' : ''));

    this.propertiesTreeOutline = new UI.TreeOutlineInShadow();
    this.propertiesTreeOutline.setFocusable(false);
    this.propertiesTreeOutline.registerRequiredCSS('elements/stylesSectionTree.css');
    this.propertiesTreeOutline.element.classList.add('style-properties', 'matched-styles', 'monospace');
    this.propertiesTreeOutline.section = this;
    this._innerElement.appendChild(this.propertiesTreeOutline.element);

    this._showAllButton = UI.createTextButton('', this._showAllItems.bind(this), 'styles-show-all');
    this._innerElement.appendChild(this._showAllButton);

    const selectorContainer = createElement('div');
    this._selectorElement = createElementWithClass('span', 'selector');
    this._selectorElement.textContent = this._headerText();
    selectorContainer.appendChild(this._selectorElement);
    this._selectorElement.addEventListener('mouseenter', this._onMouseEnterSelector.bind(this), false);
    this._selectorElement.addEventListener('mousemove', event => event.consume(), false);
    this._selectorElement.addEventListener('mouseleave', this._onMouseOutSelector.bind(this), false);

    const openBrace = selectorContainer.createChild('span', 'sidebar-pane-open-brace');
    openBrace.textContent = ' {';
    selectorContainer.addEventListener('mousedown', this._handleEmptySpaceMouseDown.bind(this), false);
    selectorContainer.addEventListener('click', this._handleSelectorContainerClick.bind(this), false);

    const closeBrace = this._innerElement.createChild('div', 'sidebar-pane-closing-brace');
    closeBrace.textContent = '}';

    this._createHoverMenuToolbar(closeBrace);

    this._selectorElement.addEventListener('click', this._handleSelectorClick.bind(this), false);
    this.element.addEventListener('mousedown', this._handleEmptySpaceMouseDown.bind(this), false);
    this.element.addEventListener('click', this._handleEmptySpaceClick.bind(this), false);
    this.element.addEventListener('mousemove', this._onMouseMove.bind(this), false);
    this.element.addEventListener('mouseleave', this._onMouseLeave.bind(this), false);
    this._selectedSinceMouseDown = false;

    if (rule) {
      // Prevent editing the user agent and user rules.
      if (rule.isUserAgent() || rule.isInjected()) {
        this.editable = false;
      } else {
        // Check this is a real CSSRule, not a bogus object coming from BlankStylePropertiesSection.
        if (rule.styleSheetId) {
          const header = rule.cssModel().styleSheetHeaderForId(rule.styleSheetId);
          this.navigable = !header.isAnonymousInlineStyleSheet();
        }
      }
    }

    this._mediaListElement = this._titleElement.createChild('div', 'media-list media-matches');
    this._selectorRefElement = this._titleElement.createChild('div', 'styles-section-subtitle');
    this._updateMediaList();
    this._updateRuleOrigin();
    this._titleElement.appendChild(selectorContainer);
    this._selectorContainer = selectorContainer;

    if (this.navigable) {
      this.element.classList.add('navigable');
    }

    if (!this.editable) {
      this.element.classList.add('read-only');
      this.propertiesTreeOutline.element.classList.add('read-only');
    }

    this._hoverableSelectorsMode = false;
    this._markSelectorMatches();
    this.onpopulate();
  }

  /**
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @param {!Components.Linkifier} linkifier
   * @param {?SDK.CSSRule} rule
   * @return {!Node}
   */
  static createRuleOriginNode(matchedStyles, linkifier, rule) {
    if (!rule) {
      return createTextNode('');
    }

    const ruleLocation = this._getRuleLocationFromCSSRule(rule);

    const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;
    if (ruleLocation && rule.styleSheetId && header && !header.isAnonymousInlineStyleSheet()) {
      return StylePropertiesSection._linkifyRuleLocation(
          matchedStyles.cssModel(), linkifier, rule.styleSheetId, ruleLocation);
    }

    if (rule.isUserAgent()) {
      return createTextNode(Common.UIString('user agent stylesheet'));
    }
    if (rule.isInjected()) {
      return createTextNode(Common.UIString('injected stylesheet'));
    }
    if (rule.isViaInspector()) {
      return createTextNode(Common.UIString('via inspector'));
    }

    if (header && header.ownerNode) {
      const link = linkifyDeferredNodeReference(header.ownerNode, {preventKeyboardFocus: true});
      link.textContent = '<style>';
      return link;
    }

    return createTextNode('');
  }

  /**
   * @param {!SDK.CSSRule} rule
   * @return {?TextUtils.TextRange}
   */
  static _getRuleLocationFromCSSRule(rule) {
    let ruleLocation = null;
    if (rule instanceof SDK.CSSStyleRule) {
      ruleLocation = rule.style.range;
    } else if (rule instanceof SDK.CSSKeyframeRule) {
      ruleLocation = rule.key().range;
    }
    return ruleLocation;
  }

  /**
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @param {?SDK.CSSRule} rule
   */
  static tryNavigateToRuleLocation(matchedStyles, rule) {
    if (!rule) {
      return;
    }

    const ruleLocation = this._getRuleLocationFromCSSRule(rule);
    const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;

    if (ruleLocation && rule.styleSheetId && header && !header.isAnonymousInlineStyleSheet()) {
      const matchingSelectorLocation =
          this._getCSSSelectorLocation(matchedStyles.cssModel(), rule.styleSheetId, ruleLocation);
      this._revealSelectorSource(matchingSelectorLocation, true);
    }
  }

  /**
   * @param {!SDK.CSSModel} cssModel
   * @param {!Components.Linkifier} linkifier
   * @param {string} styleSheetId
   * @param {!TextUtils.TextRange} ruleLocation
   * @return {!Node}
   */
  static _linkifyRuleLocation(cssModel, linkifier, styleSheetId, ruleLocation) {
    const matchingSelectorLocation = this._getCSSSelectorLocation(cssModel, styleSheetId, ruleLocation);
    return linkifier.linkifyCSSLocation(matchingSelectorLocation);
  }

  /**
   * @param {!SDK.CSSModel} cssModel
   * @param {string} styleSheetId
   * @param {!TextUtils.TextRange} ruleLocation
   * @return {!SDK.CSSLocation}
   */
  static _getCSSSelectorLocation(cssModel, styleSheetId, ruleLocation) {
    const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
    const lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
    const columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
    return new SDK.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
  }

  /**
   * @param {!Event} event
   */
  _onKeyDown(event) {
    if (UI.isEditing() || !this.editable || event.altKey || event.ctrlKey || event.metaKey) {
      return;
    }
    switch (event.key) {
      case 'Enter':
      case ' ':
        this._startEditingAtFirstPosition();
        event.consume(true);
        break;
      default:
        // Filter out non-printable key strokes.
        if (event.key.length === 1) {
          this.addNewBlankProperty(0).startEditing();
        }
        break;
    }
  }

  /**
   * @param {boolean} isHovered
   */
  _setSectionHovered(isHovered) {
    this.element.classList.toggle('styles-panel-hovered', isHovered);
    this.propertiesTreeOutline.element.classList.toggle('styles-panel-hovered', isHovered);
    if (this._hoverableSelectorsMode !== isHovered) {
      this._hoverableSelectorsMode = isHovered;
      this._markSelectorMatches();
    }
  }

  /**
   * @param {!Event} event
   */
  _onMouseLeave(event) {
    this._setSectionHovered(false);
    this._parentPane._setActiveProperty(null);
  }

  /**
   * @param {!Event} event
   */
  _onMouseMove(event) {
    const hasCtrlOrMeta = UI.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */ (event));
    this._setSectionHovered(hasCtrlOrMeta);

    const treeElement = this.propertiesTreeOutline.treeElementFromEvent(event);
    if (treeElement instanceof StylePropertyTreeElement) {
      this._parentPane._setActiveProperty(/** @type {!StylePropertyTreeElement} */ (treeElement));
    } else {
      this._parentPane._setActiveProperty(null);
    }
    if (!this._selectedSinceMouseDown && this.element.getComponentSelection().toString()) {
      this._selectedSinceMouseDown = true;
    }
  }

  /**
   * @param {!Element} container
   */
  _createHoverMenuToolbar(container) {
    if (!this.editable) {
      return;
    }
    const items = [];

    const textShadowButton = new UI.ToolbarButton(Common.UIString('Add text-shadow'), 'largeicon-text-shadow');
    textShadowButton.addEventListener(
        UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'text-shadow'));
    textShadowButton.element.tabIndex = -1;
    items.push(textShadowButton);

    const boxShadowButton = new UI.ToolbarButton(Common.UIString('Add box-shadow'), 'largeicon-box-shadow');
    boxShadowButton.addEventListener(
        UI.ToolbarButton.Events.Click, this._onInsertShadowPropertyClick.bind(this, 'box-shadow'));
    boxShadowButton.element.tabIndex = -1;
    items.push(boxShadowButton);

    const colorButton = new UI.ToolbarButton(Common.UIString('Add color'), 'largeicon-foreground-color');
    colorButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertColorPropertyClick, this);
    colorButton.element.tabIndex = -1;
    items.push(colorButton);

    const backgroundButton =
        new UI.ToolbarButton(Common.UIString('Add background-color'), 'largeicon-background-color');
    backgroundButton.addEventListener(UI.ToolbarButton.Events.Click, this._onInsertBackgroundColorPropertyClick, this);
    backgroundButton.element.tabIndex = -1;
    items.push(backgroundButton);

    let newRuleButton = null;
    if (this._style.parentRule) {
      newRuleButton = new UI.ToolbarButton(Common.UIString('Insert Style Rule Below'), 'largeicon-add');
      newRuleButton.addEventListener(UI.ToolbarButton.Events.Click, this._onNewRuleClick, this);
      newRuleButton.element.tabIndex = -1;
      items.push(newRuleButton);
    }

    const sectionToolbar = new UI.Toolbar('sidebar-pane-section-toolbar', container);
    for (let i = 0; i < items.length; ++i) {
      sectionToolbar.appendToolbarItem(items[i]);
    }

    const menuButton = new UI.ToolbarButton('', 'largeicon-menu');
    menuButton.element.tabIndex = -1;
    sectionToolbar.appendToolbarItem(menuButton);
    setItemsVisibility(items, false);
    sectionToolbar.element.addEventListener('mouseenter', setItemsVisibility.bind(null, items, true));
    sectionToolbar.element.addEventListener('mouseleave', setItemsVisibility.bind(null, items, false));
    UI.ARIAUtils.markAsHidden(sectionToolbar.element);

    /**
     * @param {!Array<!UI.ToolbarButton>} items
     * @param {boolean} value
     */
    function setItemsVisibility(items, value) {
      for (let i = 0; i < items.length; ++i) {
        items[i].setVisible(value);
      }
      menuButton.setVisible(!value);
    }
  }

  /**
   * @return {!SDK.CSSStyleDeclaration}
   */
  style() {
    return this._style;
  }

  /**
   * @return {string}
   */
  _headerText() {
    const node = this._matchedStyles.nodeForStyle(this._style);
    if (this._style.type === SDK.CSSStyleDeclaration.Type.Inline) {
      return this._matchedStyles.isInherited(this._style) ? Common.UIString('Style Attribute') : 'element.style';
    }
    if (this._style.type === SDK.CSSStyleDeclaration.Type.Attributes) {
      return ls`${node.nodeNameInCorrectCase()}[Attributes Style]`;
    }
    return this._style.parentRule.selectorText();
  }

  _onMouseOutSelector() {
    if (this._hoverTimer) {
      clearTimeout(this._hoverTimer);
    }
    SDK.OverlayModel.hideDOMNodeHighlight();
  }

  _onMouseEnterSelector() {
    if (this._hoverTimer) {
      clearTimeout(this._hoverTimer);
    }
    this._hoverTimer = setTimeout(this._highlight.bind(this), 300);
  }

  /**
   * @param {string=} mode
   */
  _highlight(mode = 'all') {
    SDK.OverlayModel.hideDOMNodeHighlight();
    const node = this._parentPane.node();
    if (!node) {
      return;
    }
    const selectorList = this._style.parentRule ? this._style.parentRule.selectorText() : undefined;
    node.domModel().overlayModel().highlightInOverlay({node, selectorList}, mode);
  }

  /**
   * @return {?StylePropertiesSection}
   */
  firstSibling() {
    const parent = this.element.parentElement;
    if (!parent) {
      return null;
    }

    let childElement = parent.firstChild;
    while (childElement) {
      if (childElement._section) {
        return childElement._section;
      }
      childElement = childElement.nextSibling;
    }

    return null;
  }

  /**
   * @return {?StylePropertiesSection}
   */
  lastSibling() {
    const parent = this.element.parentElement;
    if (!parent) {
      return null;
    }

    let childElement = parent.lastChild;
    while (childElement) {
      if (childElement._section) {
        return childElement._section;
      }
      childElement = childElement.previousSibling;
    }

    return null;
  }

  /**
   * @return {?StylePropertiesSection}
   */
  nextSibling() {
    let curElement = this.element;
    do {
      curElement = curElement.nextSibling;
    } while (curElement && !curElement._section);

    return curElement ? curElement._section : null;
  }

  /**
   * @return {?StylePropertiesSection}
   */
  previousSibling() {
    let curElement = this.element;
    do {
      curElement = curElement.previousSibling;
    } while (curElement && !curElement._section);

    return curElement ? curElement._section : null;
  }

  /**
   * @param {!Common.Event} event
   */
  _onNewRuleClick(event) {
    event.data.consume();
    const rule = this._style.parentRule;
    const range = TextUtils.TextRange.createFromLocation(rule.style.range.endLine, rule.style.range.endColumn + 1);
    this._parentPane._addBlankSection(this, /** @type {string} */ (rule.styleSheetId), range);
  }

  /**
   * @param {string} propertyName
   * @param {!Common.Event} event
   */
  _onInsertShadowPropertyClick(propertyName, event) {
    event.data.consume(true);
    const treeElement = this.addNewBlankProperty();
    treeElement.property.name = propertyName;
    treeElement.property.value = '0 0 black';
    treeElement.updateTitle();
    const shadowSwatchPopoverHelper = ShadowSwatchPopoverHelper.forTreeElement(treeElement);
    if (shadowSwatchPopoverHelper) {
      shadowSwatchPopoverHelper.showPopover();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onInsertColorPropertyClick(event) {
    event.data.consume(true);
    const treeElement = this.addNewBlankProperty();
    treeElement.property.name = 'color';
    treeElement.property.value = 'black';
    treeElement.updateTitle();
    const colorSwatch = ColorSwatchPopoverIcon.forTreeElement(treeElement);
    if (colorSwatch) {
      colorSwatch.showPopover();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onInsertBackgroundColorPropertyClick(event) {
    event.data.consume(true);
    const treeElement = this.addNewBlankProperty();
    treeElement.property.name = 'background-color';
    treeElement.property.value = 'white';
    treeElement.updateTitle();
    const colorSwatch = ColorSwatchPopoverIcon.forTreeElement(treeElement);
    if (colorSwatch) {
      colorSwatch.showPopover();
    }
  }

  /**
   * @param {!SDK.CSSModel.Edit} edit
   */
  _styleSheetEdited(edit) {
    const rule = this._style.parentRule;
    if (rule) {
      rule.rebase(edit);
    } else {
      this._style.rebase(edit);
    }

    this._updateMediaList();
    this._updateRuleOrigin();
  }

  /**
   * @param {!Array.<!SDK.CSSMedia>} mediaRules
   */
  _createMediaList(mediaRules) {
    for (let i = mediaRules.length - 1; i >= 0; --i) {
      const media = mediaRules[i];
      // Don't display trivial non-print media types.
      if (!media.text.includes('(') && media.text !== 'print') {
        continue;
      }
      const mediaDataElement = this._mediaListElement.createChild('div', 'media');
      const mediaContainerElement = mediaDataElement.createChild('span');
      const mediaTextElement = mediaContainerElement.createChild('span', 'media-text');
      switch (media.source) {
        case SDK.CSSMedia.Source.LINKED_SHEET:
        case SDK.CSSMedia.Source.INLINE_SHEET:
          mediaTextElement.textContent = 'media="' + media.text + '"';
          break;
        case SDK.CSSMedia.Source.MEDIA_RULE:
          const decoration = mediaContainerElement.createChild('span');
          mediaContainerElement.insertBefore(decoration, mediaTextElement);
          decoration.textContent = '@media ';
          mediaTextElement.textContent = media.text;
          if (media.styleSheetId) {
            mediaDataElement.classList.add('editable-media');
            mediaTextElement.addEventListener(
                'click', this._handleMediaRuleClick.bind(this, media, mediaTextElement), false);
          }
          break;
        case SDK.CSSMedia.Source.IMPORT_RULE:
          mediaTextElement.textContent = '@import ' + media.text;
          break;
      }
    }
  }

  _updateMediaList() {
    this._mediaListElement.removeChildren();
    if (this._style.parentRule && this._style.parentRule instanceof SDK.CSSStyleRule) {
      this._createMediaList(this._style.parentRule.media);
    }
  }

  /**
   * @param {string} propertyName
   * @return {boolean}
   */
  isPropertyInherited(propertyName) {
    if (this._matchedStyles.isInherited(this._style)) {
      // While rendering inherited stylesheet, reverse meaning of this property.
      // Render truly inherited properties with black, i.e. return them as non-inherited.
      return !SDK.cssMetadata().isPropertyInherited(propertyName);
    }
    return false;
  }

  /**
   * @return {?StylePropertiesSection}
   */
  nextEditableSibling() {
    let curSection = this;
    do {
      curSection = curSection.nextSibling();
    } while (curSection && !curSection.editable);

    if (!curSection) {
      curSection = this.firstSibling();
      while (curSection && !curSection.editable) {
        curSection = curSection.nextSibling();
      }
    }

    return (curSection && curSection.editable) ? curSection : null;
  }

  /**
   * @return {?StylePropertiesSection}
   */
  previousEditableSibling() {
    let curSection = this;
    do {
      curSection = curSection.previousSibling();
    } while (curSection && !curSection.editable);

    if (!curSection) {
      curSection = this.lastSibling();
      while (curSection && !curSection.editable) {
        curSection = curSection.previousSibling();
      }
    }

    return (curSection && curSection.editable) ? curSection : null;
  }

  /**
   * @param {!StylePropertyTreeElement} editedTreeElement
   */
  refreshUpdate(editedTreeElement) {
    this._parentPane._refreshUpdate(this, editedTreeElement);
  }

  /**
   * @param {!StylePropertyTreeElement} editedTreeElement
   */
  _updateVarFunctions(editedTreeElement) {
    let child = this.propertiesTreeOutline.firstChild();
    while (child) {
      if (child !== editedTreeElement) {
        child.updateTitleIfComputedValueChanged();
      }
      child = child.traverseNextTreeElement(false /* skipUnrevealed */, null /* stayWithin */, true /* dontPopulate */);
    }
  }

  /**
   * @param {boolean} full
   */
  update(full) {
    this._selectorElement.textContent = this._headerText();
    this._markSelectorMatches();
    if (full) {
      this.onpopulate();
    } else {
      let child = this.propertiesTreeOutline.firstChild();
      while (child) {
        child.setOverloaded(this._isPropertyOverloaded(child.property));
        child =
            child.traverseNextTreeElement(false /* skipUnrevealed */, null /* stayWithin */, true /* dontPopulate */);
      }
    }
  }

  /**
   * @param {!Event=} event
   */
  _showAllItems(event) {
    if (event) {
      event.consume();
    }
    if (this._forceShowAll) {
      return;
    }
    this._forceShowAll = true;
    this.onpopulate();
  }

  onpopulate() {
    this._parentPane._setActiveProperty(null);
    this.propertiesTreeOutline.removeChildren();
    const style = this._style;
    let count = 0;
    const properties = style.leadingProperties();
    const maxProperties = StylePropertiesSection.MaxProperties + properties.length - this._originalPropertiesCount;

    for (const property of properties) {
      if (!this._forceShowAll && count >= maxProperties) {
        break;
      }
      count++;
      const isShorthand = !!style.longhandProperties(property.name).length;
      const inherited = this.isPropertyInherited(property.name);
      const overloaded = this._isPropertyOverloaded(property);
      if (style.parentRule && style.parentRule.isUserAgent() && inherited) {
        continue;
      }
      const item = new StylePropertyTreeElement(
          this._parentPane, this._matchedStyles, property, isShorthand, inherited, overloaded, false);
      this.propertiesTreeOutline.appendChild(item);
    }

    if (count < properties.length) {
      this._showAllButton.classList.remove('hidden');
      this._showAllButton.textContent = ls`Show All Properties (${properties.length - count} more)`;
    } else {
      this._showAllButton.classList.add('hidden');
    }
  }

  /**
   * @param {!SDK.CSSProperty} property
   * @return {boolean}
   */
  _isPropertyOverloaded(property) {
    return this._matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Overloaded;
  }

  /**
   * @return {boolean}
   */
  _updateFilter() {
    let hasMatchingChild = false;
    this._showAllItems();
    for (const child of this.propertiesTreeOutline.rootElement().children()) {
      hasMatchingChild |= child._updateFilter();
    }

    const regex = this._parentPane.filterRegex();
    const hideRule = !hasMatchingChild && !!regex && !regex.test(this.element.deepTextContent());
    this.element.classList.toggle('hidden', hideRule);
    if (!hideRule && this._style.parentRule) {
      this._markSelectorHighlights();
    }
    return !hideRule;
  }

  _markSelectorMatches() {
    const rule = this._style.parentRule;
    if (!rule) {
      return;
    }

    this._mediaListElement.classList.toggle('media-matches', this._matchedStyles.mediaMatches(this._style));

    const selectorTexts = rule.selectors.map(selector => selector.text);
    const matchingSelectorIndexes = this._matchedStyles.matchingSelectors(/** @type {!SDK.CSSStyleRule} */ (rule));
    const matchingSelectors = /** @type {!Array<boolean>} */ (new Array(selectorTexts.length).fill(false));
    for (const matchingIndex of matchingSelectorIndexes) {
      matchingSelectors[matchingIndex] = true;
    }

    if (this._parentPane._isEditingStyle) {
      return;
    }

    const fragment = this._hoverableSelectorsMode ? this._renderHoverableSelectors(selectorTexts, matchingSelectors) :
                                                    this._renderSimplifiedSelectors(selectorTexts, matchingSelectors);
    this._selectorElement.removeChildren();
    this._selectorElement.appendChild(fragment);
    this._markSelectorHighlights();
  }

  /**
   * @param {!Array<string>} selectors
   * @param {!Array<boolean>} matchingSelectors
   * @return {!DocumentFragment}
   */
  _renderHoverableSelectors(selectors, matchingSelectors) {
    const fragment = createDocumentFragment();
    for (let i = 0; i < selectors.length; ++i) {
      if (i) {
        fragment.createTextChild(', ');
      }
      fragment.appendChild(this._createSelectorElement(selectors[i], matchingSelectors[i], i));
    }
    return fragment;
  }

  /**
   * @param {string} text
   * @param {boolean} isMatching
   * @param {number=} navigationIndex
   * @return {!Element}
   */
  _createSelectorElement(text, isMatching, navigationIndex) {
    const element = createElementWithClass('span', 'simple-selector');
    element.classList.toggle('selector-matches', isMatching);
    if (typeof navigationIndex === 'number') {
      element._selectorIndex = navigationIndex;
    }
    element.textContent = text;
    return element;
  }

  /**
   * @param {!Array<string>} selectors
   * @param {!Array<boolean>} matchingSelectors
   * @return {!DocumentFragment}
   */
  _renderSimplifiedSelectors(selectors, matchingSelectors) {
    const fragment = createDocumentFragment();
    let currentMatching = false;
    let text = '';
    for (let i = 0; i < selectors.length; ++i) {
      if (currentMatching !== matchingSelectors[i] && text) {
        fragment.appendChild(this._createSelectorElement(text, currentMatching));
        text = '';
      }
      currentMatching = matchingSelectors[i];
      text += selectors[i] + (i === selectors.length - 1 ? '' : ', ');
    }
    if (text) {
      fragment.appendChild(this._createSelectorElement(text, currentMatching));
    }
    return fragment;
  }

  _markSelectorHighlights() {
    const selectors = this._selectorElement.getElementsByClassName('simple-selector');
    const regex = this._parentPane.filterRegex();
    for (let i = 0; i < selectors.length; ++i) {
      const selectorMatchesFilter = !!regex && regex.test(selectors[i].textContent);
      selectors[i].classList.toggle('filter-match', selectorMatchesFilter);
    }
  }

  /**
   * @return {boolean}
   */
  _checkWillCancelEditing() {
    const willCauseCancelEditing = this._willCauseCancelEditing;
    this._willCauseCancelEditing = false;
    return willCauseCancelEditing;
  }

  /**
   * @param {!Event} event
   */
  _handleSelectorContainerClick(event) {
    if (this._checkWillCancelEditing() || !this.editable) {
      return;
    }
    if (event.target === this._selectorContainer) {
      this.addNewBlankProperty(0).startEditing();
      event.consume(true);
    }
  }

  /**
   * @param {number=} index
   * @return {!StylePropertyTreeElement}
   */
  addNewBlankProperty(index = this.propertiesTreeOutline.rootElement().childCount()) {
    const property = this._style.newBlankProperty(index);
    const item =
        new StylePropertyTreeElement(this._parentPane, this._matchedStyles, property, false, false, false, true);
    this.propertiesTreeOutline.insertChild(item, property.index);
    return item;
  }

  _handleEmptySpaceMouseDown() {
    this._willCauseCancelEditing = this._parentPane._isEditingStyle;
    this._selectedSinceMouseDown = false;
  }

  /**
   * @param {!Event} event
   */
  _handleEmptySpaceClick(event) {
    if (!this.editable || this.element.hasSelection() || this._checkWillCancelEditing() ||
        this._selectedSinceMouseDown) {
      return;
    }

    if (event.target.classList.contains('header') || this.element.classList.contains('read-only') ||
        event.target.enclosingNodeOrSelfWithClass('media')) {
      event.consume();
      return;
    }
    const deepTarget = event.deepElementFromPoint();
    if (deepTarget.treeElement) {
      this.addNewBlankProperty(deepTarget.treeElement.property.index + 1).startEditing();
    } else {
      this.addNewBlankProperty().startEditing();
    }
    event.consume(true);
  }

  /**
   * @param {!SDK.CSSMedia} media
   * @param {!Element} element
   * @param {!Event} event
   */
  _handleMediaRuleClick(media, element, event) {
    if (UI.isBeingEdited(element)) {
      return;
    }

    if (UI.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */ (event)) && this.navigable) {
      const location = media.rawLocation();
      if (!location) {
        event.consume(true);
        return;
      }
      const uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(location);
      if (uiLocation) {
        Common.Revealer.reveal(uiLocation);
      }
      event.consume(true);
      return;
    }

    if (!this.editable) {
      return;
    }

    const config = new UI.InplaceEditor.Config(
        this._editingMediaCommitted.bind(this, media), this._editingMediaCancelled.bind(this, element), undefined,
        this._editingMediaBlurHandler.bind(this));
    UI.InplaceEditor.startEditing(element, config);

    element.getComponentSelection().selectAllChildren(element);
    this._parentPane.setEditingStyle(true);
    const parentMediaElement = element.enclosingNodeOrSelfWithClass('media');
    parentMediaElement.classList.add('editing-media');

    event.consume(true);
  }

  /**
   * @param {!Element} element
   */
  _editingMediaFinished(element) {
    this._parentPane.setEditingStyle(false);
    const parentMediaElement = element.enclosingNodeOrSelfWithClass('media');
    parentMediaElement.classList.remove('editing-media');
  }

  /**
   * @param {!Element} element
   */
  _editingMediaCancelled(element) {
    this._editingMediaFinished(element);
    // Mark the selectors in group if necessary.
    // This is overridden by BlankStylePropertiesSection.
    this._markSelectorMatches();
    element.getComponentSelection().collapse(element, 0);
  }

  /**
   * @param {!Element} editor
   * @param {!Event} blurEvent
   * @return {boolean}
   */
  _editingMediaBlurHandler(editor, blurEvent) {
    return true;
  }

  /**
   * @param {!SDK.CSSMedia} media
   * @param {!Element} element
   * @param {string} newContent
   * @param {string} oldContent
   * @param {(!Elements.StylePropertyTreeElement.Context|undefined)} context
   * @param {string} moveDirection
   */
  _editingMediaCommitted(media, element, newContent, oldContent, context, moveDirection) {
    this._parentPane.setEditingStyle(false);
    this._editingMediaFinished(element);

    if (newContent) {
      newContent = newContent.trim();
    }

    /**
     * @param {boolean} success
     * @this {StylePropertiesSection}
     */
    function userCallback(success) {
      if (success) {
        this._matchedStyles.resetActiveProperties();
        this._parentPane._refreshUpdate(this);
      }
      this._parentPane.setUserOperation(false);
      this._editingMediaTextCommittedForTest();
    }

    // This gets deleted in finishOperation(), which is called both on success and failure.
    this._parentPane.setUserOperation(true);
    this._parentPane.cssModel().setMediaText(media.styleSheetId, media.range, newContent).then(userCallback.bind(this));
  }

  _editingMediaTextCommittedForTest() {
  }

  /**
   * @param {!Event} event
   */
  _handleSelectorClick(event) {
    if (UI.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */ (event)) && this.navigable &&
        event.target.classList.contains('simple-selector')) {
      this._navigateToSelectorSource(event.target._selectorIndex, true);
      event.consume(true);
      return;
    }
    if (this.element.hasSelection()) {
      return;
    }
    this._startEditingAtFirstPosition();
    event.consume(true);
  }

  /**
   * @param {number} index
   * @param {boolean} focus
   */
  _navigateToSelectorSource(index, focus) {
    const cssModel = this._parentPane.cssModel();
    const rule = this._style.parentRule;
    const header = cssModel.styleSheetHeaderForId(/** @type {string} */ (rule.styleSheetId));
    if (!header) {
      return;
    }
    const rawLocation = new SDK.CSSLocation(header, rule.lineNumberInSource(index), rule.columnNumberInSource(index));
    StylePropertiesSection._revealSelectorSource(rawLocation, focus);
  }

  /**
   * @param {!SDK.CSSLocation} rawLocation
   * @param {boolean} focus
   */
  static _revealSelectorSource(rawLocation, focus) {
    const uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
    if (uiLocation) {
      Common.Revealer.reveal(uiLocation, !focus);
    }
  }

  _startEditingAtFirstPosition() {
    if (!this.editable) {
      return;
    }

    if (!this._style.parentRule) {
      this.moveEditorFromSelector('forward');
      return;
    }

    this.startEditingSelector();
  }

  startEditingSelector() {
    const element = this._selectorElement;
    if (UI.isBeingEdited(element)) {
      return;
    }

    element.scrollIntoViewIfNeeded(false);
    // Reset selector marks in group, and normalize whitespace.
    element.textContent = element.textContent.replace(/\s+/g, ' ').trim();

    const config =
        new UI.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this));
    UI.InplaceEditor.startEditing(this._selectorElement, config);

    element.getComponentSelection().selectAllChildren(element);
    this._parentPane.setEditingStyle(true);
    if (element.classList.contains('simple-selector')) {
      this._navigateToSelectorSource(0, false);
    }
  }

  /**
   * @param {string} moveDirection
   */
  moveEditorFromSelector(moveDirection) {
    this._markSelectorMatches();

    if (!moveDirection) {
      return;
    }

    if (moveDirection === 'forward') {
      let firstChild = this.propertiesTreeOutline.firstChild();
      while (firstChild && firstChild.inherited()) {
        firstChild = firstChild.nextSibling;
      }
      if (!firstChild) {
        this.addNewBlankProperty().startEditing();
      } else {
        firstChild.startEditing(firstChild.nameElement);
      }
    } else {
      const previousSection = this.previousEditableSibling();
      if (!previousSection) {
        return;
      }

      previousSection.addNewBlankProperty().startEditing();
    }
  }

  /**
   * @param {!Element} element
   * @param {string} newContent
   * @param {string} oldContent
   * @param {(!Elements.StylePropertyTreeElement.Context|undefined)} context
   * @param {string} moveDirection
   */
  editingSelectorCommitted(element, newContent, oldContent, context, moveDirection) {
    this._editingSelectorEnded();
    if (newContent) {
      newContent = newContent.trim();
    }
    if (newContent === oldContent) {
      // Revert to a trimmed version of the selector if need be.
      this._selectorElement.textContent = newContent;
      this.moveEditorFromSelector(moveDirection);
      return;
    }
    const rule = this._style.parentRule;
    if (!rule) {
      return;
    }

    /**
     * @this {StylePropertiesSection}
     */
    function headerTextCommitted() {
      this._parentPane.setUserOperation(false);
      this.moveEditorFromSelector(moveDirection);
      this._editingSelectorCommittedForTest();
    }

    // This gets deleted in finishOperationAndMoveEditor(), which is called both on success and failure.
    this._parentPane.setUserOperation(true);
    this._setHeaderText(rule, newContent).then(headerTextCommitted.bind(this));
  }

  /**
   * @param {!SDK.CSSRule} rule
   * @param {string} newContent
   * @return {!Promise}
   */
  _setHeaderText(rule, newContent) {
    /**
     * @param {!SDK.CSSStyleRule} rule
     * @param {boolean} success
     * @return {!Promise}
     * @this {StylePropertiesSection}
     */
    function onSelectorsUpdated(rule, success) {
      if (!success) {
        return Promise.resolve();
      }
      return this._matchedStyles.recomputeMatchingSelectors(rule).then(updateSourceRanges.bind(this, rule));
    }

    /**
     * @param {!SDK.CSSStyleRule} rule
     * @this {StylePropertiesSection}
     */
    function updateSourceRanges(rule) {
      const doesAffectSelectedNode = this._matchedStyles.matchingSelectors(rule).length > 0;
      this.propertiesTreeOutline.element.classList.toggle('no-affect', !doesAffectSelectedNode);
      this._matchedStyles.resetActiveProperties();
      this._parentPane._refreshUpdate(this);
    }

    console.assert(rule instanceof SDK.CSSStyleRule);
    const oldSelectorRange = rule.selectorRange();
    if (!oldSelectorRange) {
      return Promise.resolve();
    }
    return rule.setSelectorText(newContent)
        .then(onSelectorsUpdated.bind(this, /** @type {!SDK.CSSStyleRule} */ (rule), oldSelectorRange));
  }

  _editingSelectorCommittedForTest() {
  }

  _updateRuleOrigin() {
    this._selectorRefElement.removeChildren();
    this._selectorRefElement.appendChild(StylePropertiesSection.createRuleOriginNode(
        this._matchedStyles, this._parentPane._linkifier, this._style.parentRule));
  }

  _editingSelectorEnded() {
    this._parentPane.setEditingStyle(false);
  }

  editingSelectorCancelled() {
    this._editingSelectorEnded();

    // Mark the selectors in group if necessary.
    // This is overridden by BlankStylePropertiesSection.
    this._markSelectorMatches();
  }
}

StylePropertiesSection.MaxProperties = 50;

export class BlankStylePropertiesSection extends StylePropertiesSection {
  /**
   * @param {!StylesSidebarPane} stylesPane
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @param {string} defaultSelectorText
   * @param {string} styleSheetId
   * @param {!TextUtils.TextRange} ruleLocation
   * @param {!SDK.CSSStyleDeclaration} insertAfterStyle
   */
  constructor(stylesPane, matchedStyles, defaultSelectorText, styleSheetId, ruleLocation, insertAfterStyle) {
    const cssModel = /** @type {!SDK.CSSModel} */ (stylesPane.cssModel());
    const rule = SDK.CSSStyleRule.createDummyRule(cssModel, defaultSelectorText);
    super(stylesPane, matchedStyles, rule.style);
    this._normal = false;
    this._ruleLocation = ruleLocation;
    this._styleSheetId = styleSheetId;
    this._selectorRefElement.removeChildren();
    this._selectorRefElement.appendChild(StylePropertiesSection._linkifyRuleLocation(
        cssModel, this._parentPane._linkifier, styleSheetId, this._actualRuleLocation()));
    if (insertAfterStyle && insertAfterStyle.parentRule) {
      this._createMediaList(insertAfterStyle.parentRule.media);
    }
    this.element.classList.add('blank-section');
  }

  /**
   * @return {!TextUtils.TextRange}
   */
  _actualRuleLocation() {
    const prefix = this._rulePrefix();
    const lines = prefix.split('\n');
    const editRange = new TextUtils.TextRange(0, 0, lines.length - 1, lines.peekLast().length);
    return this._ruleLocation.rebaseAfterTextEdit(TextUtils.TextRange.createFromLocation(0, 0), editRange);
  }

  /**
   * @return {string}
   */
  _rulePrefix() {
    return this._ruleLocation.startLine === 0 && this._ruleLocation.startColumn === 0 ? '' : '\n\n';
  }

  /**
   * @return {boolean}
   */
  get isBlank() {
    return !this._normal;
  }

  /**
   * @override
   * @param {!Element} element
   * @param {string} newContent
   * @param {string} oldContent
   * @param {!Elements.StylePropertyTreeElement.Context|undefined} context
   * @param {string} moveDirection
   */
  editingSelectorCommitted(element, newContent, oldContent, context, moveDirection) {
    if (!this.isBlank) {
      super.editingSelectorCommitted(element, newContent, oldContent, context, moveDirection);
      return;
    }

    /**
     * @param {?SDK.CSSStyleRule} newRule
     * @return {!Promise}
     * @this {BlankStylePropertiesSection}
     */
    function onRuleAdded(newRule) {
      if (!newRule) {
        this.editingSelectorCancelled();
        this._editingSelectorCommittedForTest();
        return Promise.resolve();
      }
      return this._matchedStyles.addNewRule(newRule, this._matchedStyles.node())
          .then(onAddedToCascade.bind(this, newRule));
    }

    /**
     * @param {!SDK.CSSStyleRule} newRule
     * @this {BlankStylePropertiesSection}
     */
    function onAddedToCascade(newRule) {
      const doesSelectorAffectSelectedNode = this._matchedStyles.matchingSelectors(newRule).length > 0;
      this._makeNormal(newRule);

      if (!doesSelectorAffectSelectedNode) {
        this.propertiesTreeOutline.element.classList.add('no-affect');
      }

      this._updateRuleOrigin();

      this._parentPane.setUserOperation(false);
      this._editingSelectorEnded();
      if (this.element.parentElement)  // Might have been detached already.
      {
        this.moveEditorFromSelector(moveDirection);
      }
      this._markSelectorMatches();

      this._editingSelectorCommittedForTest();
    }

    if (newContent) {
      newContent = newContent.trim();
    }
    this._parentPane.setUserOperation(true);

    const cssModel = this._parentPane.cssModel();
    const ruleText = this._rulePrefix() + newContent + ' {}';
    cssModel.addRule(this._styleSheetId, ruleText, this._ruleLocation).then(onRuleAdded.bind(this));
  }

  /**
   * @override
   */
  editingSelectorCancelled() {
    this._parentPane.setUserOperation(false);
    if (!this.isBlank) {
      super.editingSelectorCancelled();
      return;
    }

    this._editingSelectorEnded();
    this._parentPane.removeSection(this);
  }

  /**
   * @param {!SDK.CSSRule} newRule
   */
  _makeNormal(newRule) {
    this.element.classList.remove('blank-section');
    this._style = newRule.style;
    // FIXME: replace this instance by a normal StylePropertiesSection.
    this._normal = true;
  }
}

export class KeyframePropertiesSection extends StylePropertiesSection {
  /**
   * @param {!StylesSidebarPane} stylesPane
   * @param {!SDK.CSSMatchedStyles} matchedStyles
   * @param {!SDK.CSSStyleDeclaration} style
   */
  constructor(stylesPane, matchedStyles, style) {
    super(stylesPane, matchedStyles, style);
    this._selectorElement.className = 'keyframe-key';
  }

  /**
   * @override
   * @return {string}
   */
  _headerText() {
    return this._style.parentRule.key().text;
  }

  /**
   * @override
   * @param {!SDK.CSSRule} rule
   * @param {string} newContent
   * @return {!Promise}
   */
  _setHeaderText(rule, newContent) {
    /**
     * @param {boolean} success
     * @this {KeyframePropertiesSection}
     */
    function updateSourceRanges(success) {
      if (!success) {
        return;
      }
      this._parentPane._refreshUpdate(this);
    }

    console.assert(rule instanceof SDK.CSSKeyframeRule);
    const oldRange = rule.key().range;
    if (!oldRange) {
      return Promise.resolve();
    }
    return rule.setKeyText(newContent).then(updateSourceRanges.bind(this));
  }

  /**
   * @override
   * @param {string} propertyName
   * @return {boolean}
   */
  isPropertyInherited(propertyName) {
    return false;
  }

  /**
   * @override
   * @param {!SDK.CSSProperty} property
   * @return {boolean}
   */
  _isPropertyOverloaded(property) {
    return false;
  }

  /**
   * @override
   */
  _markSelectorHighlights() {
  }

  /**
   * @override
   */
  _markSelectorMatches() {
    this._selectorElement.textContent = this._style.parentRule.key().text;
  }

  /**
   * @override
   */
  _highlight() {
  }
}

export class CSSPropertyPrompt extends UI.TextPrompt {
  /**
   * @param {!StylePropertyTreeElement} treeElement
   * @param {boolean} isEditingName
   */
  constructor(treeElement, isEditingName) {
    // Use the same callback both for applyItemCallback and acceptItemCallback.
    super();
    this.initialize(this._buildPropertyCompletions.bind(this), UI.StyleValueDelimiters);
    this._isColorAware = SDK.cssMetadata().isColorAwareProperty(treeElement.property.name);
    /** @type {!Array<string>} */
    this._cssCompletions = [];
    if (isEditingName) {
      this._cssCompletions = SDK.cssMetadata().allProperties();
      if (!treeElement.node().isSVGNode()) {
        this._cssCompletions = this._cssCompletions.filter(property => !SDK.cssMetadata().isSVGProperty(property));
      }
    } else {
      this._cssCompletions = SDK.cssMetadata().propertyValues(treeElement.nameElement.textContent);
    }

    this._treeElement = treeElement;
    this._isEditingName = isEditingName;
    this._cssVariables = treeElement.matchedStyles().availableCSSVariables(treeElement.property.ownerStyle);
    if (this._cssVariables.length < 1000) {
      this._cssVariables.sort(String.naturalOrderComparator);
    } else {
      this._cssVariables.sort();
    }

    if (!isEditingName) {
      this.disableDefaultSuggestionForEmptyInput();

      // If a CSS value is being edited that has a numeric or hex substring, hint that precision modifier shortcuts are available.
      if (treeElement && treeElement.valueElement) {
        const cssValueText = treeElement.valueElement.textContent;
        const cmdOrCtrl = Host.isMac() ? 'Cmd' : 'Ctrl';
        if (cssValueText.match(/#[\da-f]{3,6}$/i)) {
          this.setTitle(ls
              `Increment/decrement with mousewheel or up/down keys. ${cmdOrCtrl}: R ±1, Shift: G ±1, Alt: B ±1`);
        } else if (cssValueText.match(/\d+/)) {
          this.setTitle(ls
              `Increment/decrement with mousewheel or up/down keys. ${cmdOrCtrl}: ±100, Shift: ±10, Alt: ±0.1`);
        }
      }
    }
  }

  /**
   * @override
   * @param {!Event} event
   */
  onKeyDown(event) {
    switch (event.key) {
      case 'ArrowUp':
      case 'ArrowDown':
      case 'PageUp':
      case 'PageDown':
        if (!this.isSuggestBoxVisible() && this._handleNameOrValueUpDown(event)) {
          event.preventDefault();
          return;
        }
        break;
      case 'Enter':
        if (event.shiftKey) {
          return;
        }
        // Accept any available autocompletions and advance to the next field.
        this.tabKeyPressed();
        event.preventDefault();
        return;
    }

    super.onKeyDown(event);
  }

  /**
   * @override
   * @param {!Event} event
   */
  onMouseWheel(event) {
    if (this._handleNameOrValueUpDown(event)) {
      event.consume(true);
      return;
    }
    super.onMouseWheel(event);
  }

  /**
   * @override
   * @return {boolean}
   */
  tabKeyPressed() {
    this.acceptAutoComplete();

    // Always tab to the next field.
    return false;
  }

  /**
   * @param {!Event} event
   * @return {boolean}
   */
  _handleNameOrValueUpDown(event) {
    /**
     * @param {string} originalValue
     * @param {string} replacementString
     * @this {CSSPropertyPrompt}
     */
    function finishHandler(originalValue, replacementString) {
      // Synthesize property text disregarding any comments, custom whitespace etc.
      this._treeElement.applyStyleText(
          this._treeElement.nameElement.textContent + ': ' + this._treeElement.valueElement.textContent, false);
    }

    /**
     * @param {string} prefix
     * @param {number} number
     * @param {string} suffix
     * @return {string}
     * @this {CSSPropertyPrompt}
     */
    function customNumberHandler(prefix, number, suffix) {
      if (number !== 0 && !suffix.length && SDK.cssMetadata().isLengthProperty(this._treeElement.property.name)) {
        suffix = 'px';
      }
      return prefix + number + suffix;
    }

    // Handle numeric value increment/decrement only at this point.
    if (!this._isEditingName && this._treeElement.valueElement &&
        UI.handleElementValueModifications(
            event, this._treeElement.valueElement, finishHandler.bind(this), this._isValueSuggestion.bind(this),
            customNumberHandler.bind(this))) {
      return true;
    }

    return false;
  }

  /**
   * @param {string} word
   * @return {boolean}
   */
  _isValueSuggestion(word) {
    if (!word) {
      return false;
    }
    word = word.toLowerCase();
    return this._cssCompletions.indexOf(word) !== -1 || word.startsWith('--');
  }

  /**
   * @param {string} expression
   * @param {string} query
   * @param {boolean=} force
   * @return {!Promise<!UI.SuggestBox.Suggestions>}
   */
  _buildPropertyCompletions(expression, query, force) {
    const lowerQuery = query.toLowerCase();
    const editingVariable = !this._isEditingName && expression.trim().endsWith('var(');
    if (!query && !force && !editingVariable && (this._isEditingName || expression)) {
      return Promise.resolve([]);
    }

    const prefixResults = [];
    const anywhereResults = [];
    if (!editingVariable) {
      this._cssCompletions.forEach(completion => filterCompletions.call(this, completion, false /* variable */));
    }
    if (this._isEditingName) {
      const nameValuePresets = SDK.cssMetadata().nameValuePresets(this._treeElement.node().isSVGNode());
      nameValuePresets.forEach(
          preset => filterCompletions.call(this, preset, false /* variable */, true /* nameValue */));
    }
    if (this._isEditingName || editingVariable) {
      this._cssVariables.forEach(variable => filterCompletions.call(this, variable, true /* variable */));
    }

    const results = prefixResults.concat(anywhereResults);
    if (!this._isEditingName && !results.length && query.length > 1 && '!important'.startsWith(lowerQuery)) {
      results.push({text: '!important'});
    }
    const userEnteredText = query.replace('-', '');
    if (userEnteredText && (userEnteredText === userEnteredText.toUpperCase())) {
      for (let i = 0; i < results.length; ++i) {
        if (!results[i].text.startsWith('--')) {
          results[i].text = results[i].text.toUpperCase();
        }
      }
    }
    results.forEach(result => {
      if (editingVariable) {
        result.title = result.text;
        result.text += ')';
        return;
      }
      const valuePreset = SDK.cssMetadata().getValuePreset(this._treeElement.name, result.text);
      if (!this._isEditingName && valuePreset) {
        result.title = result.text;
        result.text = valuePreset.text;
        result.selectionRange = {startColumn: valuePreset.startColumn, endColumn: valuePreset.endColumn};
      }
    });
    if (this._isColorAware && !this._isEditingName) {
      results.sort((a, b) => {
        if (!!a.subtitleRenderer === !!b.subtitleRenderer) {
          return 0;
        }
        return a.subtitleRenderer ? -1 : 1;
      });
    }
    return Promise.resolve(results);

    /**
     * @param {string} completion
     * @param {boolean} variable
     * @param {boolean=} nameValue
     * @this {CSSPropertyPrompt}
     */
    function filterCompletions(completion, variable, nameValue) {
      const index = completion.toLowerCase().indexOf(lowerQuery);
      const result = {text: completion};
      if (variable) {
        const computedValue =
            this._treeElement.matchedStyles().computeCSSVariable(this._treeElement.property.ownerStyle, completion);
        if (computedValue) {
          const color = Common.Color.parse(computedValue);
          if (color) {
            result.subtitleRenderer = swatchRenderer.bind(null, color);
          }
        }
      }
      if (nameValue) {
        result.hideGhostText = true;
      }
      if (index === 0) {
        result.priority = this._isEditingName ? SDK.cssMetadata().propertyUsageWeight(completion) : 1;
        prefixResults.push(result);
      } else if (index > -1) {
        anywhereResults.push(result);
      }
    }

    /**
     * @param {!Common.Color} color
     * @return {!Element}
     */
    function swatchRenderer(color) {
      const swatch = InlineEditor.ColorSwatch.create();
      swatch.hideText(true);
      swatch.setColor(color);
      swatch.style.pointerEvents = 'none';
      return swatch;
    }
  }
}

export class StylesSidebarPropertyRenderer {
  /**
   * @param {?SDK.CSSRule} rule
   * @param {?SDK.DOMNode} node
   * @param {string} name
   * @param {string} value
   */
  constructor(rule, node, name, value) {
    this._rule = rule;
    this._node = node;
    this._propertyName = name;
    this._propertyValue = value;
    /** @type {?function(string):!Node} */
    this._colorHandler = null;
    /** @type {?function(string):!Node} */
    this._bezierHandler = null;
    /** @type {?function(string, string):!Node} */
    this._shadowHandler = null;
    /** @type {?function(string, string):!Node} */
    this._gridHandler = null;
    /** @type {?function(string):!Node} */
    this._varHandler = createTextNode;
  }

  /**
   * @param {function(string):!Node} handler
   */
  setColorHandler(handler) {
    this._colorHandler = handler;
  }

  /**
   * @param {function(string):!Node} handler
   */
  setBezierHandler(handler) {
    this._bezierHandler = handler;
  }

  /**
   * @param {function(string, string):!Node} handler
   */
  setShadowHandler(handler) {
    this._shadowHandler = handler;
  }

  /**
   * @param {function(string, string):!Node} handler
   */
  setGridHandler(handler) {
    this._gridHandler = handler;
  }

  /**
   * @param {function(string):!Node} handler
   */
  setVarHandler(handler) {
    this._varHandler = handler;
  }

  /**
   * @return {!Element}
   */
  renderName() {
    const nameElement = createElement('span');
    nameElement.className = 'webkit-css-property';
    nameElement.textContent = this._propertyName;
    nameElement.normalize();
    return nameElement;
  }

  /**
   * @return {!Element}
   */
  renderValue() {
    const valueElement = createElement('span');
    valueElement.className = 'value';
    if (!this._propertyValue) {
      return valueElement;
    }

    if (this._shadowHandler && (this._propertyName === 'box-shadow' || this._propertyName === 'text-shadow' ||
                                this._propertyName === '-webkit-box-shadow') &&
        !SDK.CSSMetadata.VariableRegex.test(this._propertyValue)) {
      valueElement.appendChild(this._shadowHandler(this._propertyValue, this._propertyName));
      valueElement.normalize();
      return valueElement;
    }

    if (this._gridHandler && SDK.cssMetadata().isGridAreaDefiningProperty(this._propertyName)) {
      valueElement.appendChild(this._gridHandler(this._propertyValue, this._propertyName));
      valueElement.normalize();
      return valueElement;
    }

    const regexes = [SDK.CSSMetadata.VariableRegex, SDK.CSSMetadata.URLRegex];
    const processors = [this._varHandler, this._processURL.bind(this)];
    if (this._bezierHandler && SDK.cssMetadata().isBezierAwareProperty(this._propertyName)) {
      regexes.push(UI.Geometry.CubicBezier.Regex);
      processors.push(this._bezierHandler);
    }
    if (this._colorHandler && SDK.cssMetadata().isColorAwareProperty(this._propertyName)) {
      regexes.push(Common.Color.Regex);
      processors.push(this._colorHandler);
    }
    const results = TextUtils.TextUtils.splitStringByRegexes(this._propertyValue, regexes);
    for (let i = 0; i < results.length; i++) {
      const result = results[i];
      const processor = result.regexIndex === -1 ? createTextNode : processors[result.regexIndex];
      valueElement.appendChild(processor(result.value));
    }
    valueElement.normalize();
    return valueElement;
  }

  /**
   * @param {string} text
   * @return {!Node}
   */
  _processURL(text) {
    // Strip "url(" and ")" along with whitespace.
    let url = text.substring(4, text.length - 1).trim();
    const isQuoted = /^'.*'$/.test(url) || /^".*"$/.test(url);
    if (isQuoted) {
      url = url.substring(1, url.length - 1);
    }
    const container = createDocumentFragment();
    container.createTextChild('url(');
    let hrefUrl = null;
    if (this._rule && this._rule.resourceURL()) {
      hrefUrl = Common.ParsedURL.completeURL(this._rule.resourceURL(), url);
    } else if (this._node) {
      hrefUrl = this._node.resolveURL(url);
    }
    container.appendChild(Components.Linkifier.linkifyURL(hrefUrl || url, {text: url, preventClick: true}));
    container.createTextChild(')');
    return container;
  }
}

/**
 * @implements {UI.ToolbarItem.Provider}
 */
export class ButtonProvider {
  constructor() {
    this._button = new UI.ToolbarButton(Common.UIString('New Style Rule'), 'largeicon-add');
    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._clicked, this);
    const longclickTriangle = UI.Icon.create('largeicon-longclick-triangle', 'long-click-glyph');
    this._button.element.appendChild(longclickTriangle);

    new UI.LongClickController(this._button.element, this._longClicked.bind(this));
    UI.context.addFlavorChangeListener(SDK.DOMNode, onNodeChanged.bind(this));
    onNodeChanged.call(this);

    /**
     * @this {ButtonProvider}
     */
    function onNodeChanged() {
      let node = UI.context.flavor(SDK.DOMNode);
      node = node ? node.enclosingElementOrSelf() : null;
      this._button.setEnabled(!!node);
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _clicked(event) {
    StylesSidebarPane._instance._createNewRuleInViaInspectorStyleSheet();
  }

  /**
   * @param {!Event} e
   */
  _longClicked(e) {
    StylesSidebarPane._instance._onAddButtonLongClick(e);
  }

  /**
   * @override
   * @return {!UI.ToolbarItem}
   */
  item() {
    return this._button;
  }
}
