/*
 * Copyright (C) 2008 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
 * 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
 */
ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {?string|!Element=} title
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} ignoreHasOwnProperty
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   */
  constructor(object, title, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) {
    super();
    this._object = object;
    this._editable = true;
    this.hideOverflow();
    this.setFocusable(false);
    this._objectTreeElement = new ObjectUI.ObjectPropertiesSection.RootElement(
        object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties);
    this.appendChild(this._objectTreeElement);
    if (typeof title === 'string' || !title) {
      this.titleElement = this.element.createChild('span');
      this.titleElement.textContent = title || '';
    } else {
      this.titleElement = title;
      this.element.appendChild(title);
    }

    this.element._section = this;
    this.registerRequiredCSS('object_ui/objectValue.css');
    this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
    this.rootElement().childrenListElement.classList.add('source-code', 'object-properties-section');
  }

  /**
   * @param {!SDK.RemoteObject} object
   * @param {!Components.Linkifier=} linkifier
   * @param {boolean=} skipProto
   * @return {!Element}
   */
  static defaultObjectPresentation(object, linkifier, skipProto) {
    const componentRoot = createElementWithClass('span', 'source-code');
    const shadowRoot = UI.createShadowRootWithCoreStyles(componentRoot, 'object_ui/objectValue.css');
    shadowRoot.appendChild(
        ObjectUI.ObjectPropertiesSection.createValueElement(object, false /* wasThrown */, true /* showPreview */));
    if (!object.hasChildren)
      return componentRoot;

    const objectPropertiesSection = new ObjectUI.ObjectPropertiesSection(object, componentRoot, linkifier);
    objectPropertiesSection.editable = false;
    if (skipProto)
      objectPropertiesSection.skipProto();

    return objectPropertiesSection.element;
  }

  /**
   * @param {!SDK.RemoteObjectProperty} propertyA
   * @param {!SDK.RemoteObjectProperty} propertyB
   * @return {number}
   */
  static CompareProperties(propertyA, propertyB) {
    const a = propertyA.name;
    const b = propertyB.name;
    if (a === '__proto__')
      return 1;
    if (b === '__proto__')
      return -1;
    if (!propertyA.enumerable && propertyB.enumerable)
      return 1;
    if (!propertyB.enumerable && propertyA.enumerable)
      return -1;
    if (a.startsWith('_') && !b.startsWith('_'))
      return 1;
    if (b.startsWith('_') && !a.startsWith('_'))
      return -1;
    if (propertyA.symbol && !propertyB.symbol)
      return 1;
    if (propertyB.symbol && !propertyA.symbol)
      return -1;
    return String.naturalOrderComparator(a, b);
  }

  /**
   * @param {?string} name
   * @return {!Element}
   */
  static createNameElement(name) {
    const nameElement = createElementWithClass('span', 'name');
    if (/^\s|\s$|^$|\n/.test(name))
      nameElement.createTextChildren('"', name.replace(/\n/g, '\u21B5'), '"');
    else
      nameElement.textContent = name;
    return nameElement;
  }

  /**
   * @param {?string=} description
   * @param {boolean=} includePreview
   * @param {string=} defaultName
   * @return {!Element} valueElement
   */
  static valueElementForFunctionDescription(description, includePreview, defaultName) {
    const valueElement = createElementWithClass('span', 'object-value-function');
    description = description || '';
    const text = description.replace(/^function [gs]et /, 'function ')
                     .replace(/^function [gs]et\(/, 'function\(')
                     .replace(/^[gs]et /, '');
    defaultName = defaultName || '';

    // This set of best-effort regular expressions captures common function descriptions.
    // Ideally, some parser would provide prefix, arguments, function body text separately.
    const asyncMatch = text.match(/^(async\s+function)/);
    const isGenerator = text.startsWith('function*');
    const isGeneratorShorthand = text.startsWith('*');
    const isBasic = !isGenerator && text.startsWith('function');
    const isClass = text.startsWith('class ') || text.startsWith('class{');
    const firstArrowIndex = text.indexOf('=>');
    const isArrow = !asyncMatch && !isGenerator && !isBasic && !isClass && firstArrowIndex > 0;

    let textAfterPrefix;
    if (isClass) {
      textAfterPrefix = text.substring('class'.length);
      const classNameMatch = /^[^{\s]+/.exec(textAfterPrefix.trim());
      let className = defaultName;
      if (classNameMatch)
        className = classNameMatch[0].trim() || defaultName;
      addElements('class', textAfterPrefix, className);
    } else if (asyncMatch) {
      textAfterPrefix = text.substring(asyncMatch[1].length);
      addElements('async \u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isGenerator) {
      textAfterPrefix = text.substring('function*'.length);
      addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isGeneratorShorthand) {
      textAfterPrefix = text.substring('*'.length);
      addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isBasic) {
      textAfterPrefix = text.substring('function'.length);
      addElements('\u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isArrow) {
      const maxArrowFunctionCharacterLength = 60;
      let abbreviation = text;
      if (defaultName)
        abbreviation = defaultName + '()';
      else if (text.length > maxArrowFunctionCharacterLength)
        abbreviation = text.substring(0, firstArrowIndex + 2) + ' {\u2026}';
      addElements('', text, abbreviation);
    } else {
      addElements('\u0192', text, nameAndArguments(text));
    }
    valueElement.title = description.trimEnd(500);
    return valueElement;

    /**
     * @param {string} contents
     * @return {string}
     */
    function nameAndArguments(contents) {
      const startOfArgumentsIndex = contents.indexOf('(');
      const endOfArgumentsMatch = contents.match(/\)\s*{/);
      if (startOfArgumentsIndex !== -1 && endOfArgumentsMatch && endOfArgumentsMatch.index > startOfArgumentsIndex) {
        const name = contents.substring(0, startOfArgumentsIndex).trim() || defaultName;
        const args = contents.substring(startOfArgumentsIndex, endOfArgumentsMatch.index + 1);
        return name + args;
      }
      return defaultName + '()';
    }

    /**
     * @param {string} prefix
     * @param {string} body
     * @param {string} abbreviation
     */
    function addElements(prefix, body, abbreviation) {
      const maxFunctionBodyLength = 200;
      if (prefix.length)
        valueElement.createChild('span', 'object-value-function-prefix').textContent = prefix + ' ';
      if (includePreview)
        valueElement.createTextChild(body.trim().trimEnd(maxFunctionBodyLength));
      else
        valueElement.createTextChild(abbreviation.replace(/\n/g, ' '));
    }
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @param {boolean} wasThrown
   * @param {boolean} showPreview
   * @param {!Element=} parentElement
   * @param {!Components.Linkifier=} linkifier
   * @return {!Element}
   */
  static createValueElementWithCustomSupport(value, wasThrown, showPreview, parentElement, linkifier) {
    if (value.customPreview()) {
      const result = (new ObjectUI.CustomPreviewComponent(value)).element;
      result.classList.add('object-properties-section-custom-section');
      return result;
    }
    return ObjectUI.ObjectPropertiesSection.createValueElement(value, wasThrown, showPreview, parentElement, linkifier);
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @param {boolean} wasThrown
   * @param {boolean} showPreview
   * @param {!Element=} parentElement
   * @param {!Components.Linkifier=} linkifier
   * @return {!Element}
   */
  static createValueElement(value, wasThrown, showPreview, parentElement, linkifier) {
    let valueElement;
    const type = value.type;
    const subtype = value.subtype;
    const description = value.description;
    if (type === 'object' && subtype === 'internal#location') {
      const rawLocation = value.debuggerModel().createRawLocationByScriptId(
          value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
      if (rawLocation && linkifier)
        return linkifier.linkifyRawLocation(rawLocation, '');
      valueElement = createUnknownInternalLocationElement();
    } else if (type === 'string' && typeof description === 'string') {
      valueElement = createStringElement();
    } else if (type === 'function') {
      valueElement = ObjectUI.ObjectPropertiesSection.valueElementForFunctionDescription(description);
    } else if (type === 'object' && subtype === 'node' && description) {
      valueElement = createNodeElement();
    } else if (type === 'number' && description && description.indexOf('e') !== -1) {
      valueElement = createNumberWithExponentElement();
      if (parentElement)  // FIXME: do it in the caller.
        parentElement.classList.add('hbox');
    } else {
      valueElement = createElementWithClass('span', 'object-value-' + (subtype || type));
      valueElement.title = description || '';
      if (value.preview && showPreview) {
        const previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
        previewFormatter.appendObjectPreview(valueElement, value.preview, false /* isEntry */);
      } else if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength) {
        valueElement.appendChild(UI.createExpandableText(description, 50));
      } else {
        valueElement.textContent = description;
      }
    }

    if (wasThrown) {
      const wrapperElement = createElementWithClass('span', 'error value');
      wrapperElement.createTextChild('[' + Common.UIString('Exception') + ': ');
      wrapperElement.appendChild(valueElement);
      wrapperElement.createTextChild(']');
      return wrapperElement;
    }
    valueElement.classList.add('value');
    return valueElement;

    /**
     * @return {!Element}
     */
    function createUnknownInternalLocationElement() {
      const valueElement = createElementWithClass('span');
      valueElement.textContent = '<' + Common.UIString('unknown') + '>';
      valueElement.title = description || '';
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createStringElement() {
      const valueElement = createElementWithClass('span', 'object-value-string');
      const text = description.replace(/\n/g, '\u21B5');
      valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
      if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength)
        valueElement.appendChild(UI.createExpandableText(text, 50));
      else
        valueElement.createTextChild(text);
      valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
      valueElement.title = description || '';
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createNodeElement() {
      const valueElement = createElementWithClass('span', 'object-value-node');
      ObjectUI.RemoteObjectPreviewFormatter.createSpansForNodeTitle(valueElement, /** @type {string} */ (description));
      valueElement.addEventListener('click', event => {
        Common.Revealer.reveal(value);
        event.consume(true);
      }, false);
      valueElement.addEventListener('mousemove', () => SDK.OverlayModel.highlightObjectAsDOMNode(value), false);
      valueElement.addEventListener('mouseleave', () => SDK.OverlayModel.hideDOMNodeHighlight(), false);
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createNumberWithExponentElement() {
      const valueElement = createElementWithClass('span', 'object-value-number');
      const numberParts = description.split('e');
      valueElement.createChild('span', 'object-value-scientific-notation-mantissa').textContent = numberParts[0];
      valueElement.createChild('span', 'object-value-scientific-notation-exponent').textContent = 'e' + numberParts[1];
      valueElement.classList.add('object-value-scientific-notation-number');
      valueElement.title = description || '';
      return valueElement;
    }
  }

  /**
   * @param {!SDK.RemoteObject} func
   * @param {!Element} element
   * @param {boolean} linkify
   * @param {boolean=} includePreview
   */
  static formatObjectAsFunction(func, element, linkify, includePreview) {
    func.debuggerModel().functionDetailsPromise(func).then(didGetDetails);

    /**
     * @param {?SDK.DebuggerModel.FunctionDetails} response
     */
    function didGetDetails(response) {
      if (linkify && response && response.location) {
        element.classList.add('linkified');
        element.addEventListener('click', () => Common.Revealer.reveal(response.location) && false);
      }

      // The includePreview flag is false for formats such as console.dir().
      let defaultName = includePreview ? '' : 'anonymous';
      if (response && response.functionName)
        defaultName = response.functionName;
      const valueElement = ObjectUI.ObjectPropertiesSection.valueElementForFunctionDescription(
          func.description, includePreview, defaultName);
      element.appendChild(valueElement);
    }
  }

  skipProto() {
    this._skipProto = true;
  }

  expand() {
    this._objectTreeElement.expand();
  }

  /**
   * @param {boolean} value
   */
  setEditable(value) {
    this._editable = value;
  }

  /**
   * @return {!UI.TreeElement}
   */
  objectTreeElement() {
    return this._objectTreeElement;
  }

  enableContextMenu() {
    this.element.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false);
  }

  _contextMenuEventFired(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.appendApplicableItems(this._object);
    if (this._object instanceof SDK.LocalJSONObject) {
      contextMenu.viewSection().appendItem(
          ls`Expand recursively`,
          this._objectTreeElement.expandRecursively.bind(this._objectTreeElement, Number.MAX_VALUE));
      contextMenu.viewSection().appendItem(
          ls`Collapse children`, this._objectTreeElement.collapseChildren.bind(this._objectTreeElement));
    }
    contextMenu.show();
  }

  titleLessMode() {
    this._objectTreeElement.listItemElement.classList.add('hidden');
    this._objectTreeElement.childrenListElement.classList.add('title-less-mode');
    this._objectTreeElement.expand();
  }
};

/** @const */
ObjectUI.ObjectPropertiesSection._arrayLoadThreshold = 100;
/** @const */
ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = 10000;


/**
 * @unrestricted
 */
ObjectUI.ObjectPropertiesSection.RootElement = class extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} ignoreHasOwnProperty
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   */
  constructor(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) {
    const contentElement = createElement('content');
    super(contentElement);

    this._object = object;
    this._extraProperties = extraProperties || [];
    this._ignoreHasOwnProperty = !!ignoreHasOwnProperty;
    this._emptyPlaceholder = emptyPlaceholder;

    this.setExpandable(true);
    this.selectable = false;
    this.toggleOnClick = true;
    this.listItemElement.classList.add('object-properties-section-root-element');
    this._linkifier = linkifier;
  }

  /**
   * @override
   */
  onexpand() {
    if (this.treeOutline)
      this.treeOutline.element.classList.add('expanded');
  }

  /**
   * @override
   */
  oncollapse() {
    if (this.treeOutline)
      this.treeOutline.element.classList.remove('expanded');
  }

  /**
   * @override
   * @param {!Event} e
   * @return {boolean}
   */
  ondblclick(e) {
    return true;
  }

  /**
   * @override
   */
  onpopulate() {
    ObjectUI.ObjectPropertyTreeElement._populate(
        this, this._object, !!this.treeOutline._skipProto, this._linkifier, this._emptyPlaceholder,
        this._ignoreHasOwnProperty, this._extraProperties);
  }
};

/**
 * @unrestricted
 */
ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObjectProperty} property
   * @param {!Components.Linkifier=} linkifier
   */
  constructor(property, linkifier) {
    // Pass an empty title, the title gets made later in onattach.
    super();

    this.property = property;
    this.toggleOnClick = true;
    this.selectable = false;
    /** @type {!Array.<!Object>} */
    this._highlightChanges = [];
    this._linkifier = linkifier;
    this.listItemElement.addEventListener('contextmenu', this._contextMenuFired.bind(this), false);
  }

  /**
   * @param {!UI.TreeElement} treeElement
   * @param {!SDK.RemoteObject} value
   * @param {boolean} skipProto
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} flattenProtoChain
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   * @param {!SDK.RemoteObject=} targetValue
   */
  static _populate(
      treeElement,
      value,
      skipProto,
      linkifier,
      emptyPlaceholder,
      flattenProtoChain,
      extraProperties,
      targetValue) {
    if (value.arrayLength() > ObjectUI.ObjectPropertiesSection._arrayLoadThreshold) {
      treeElement.removeChildren();
      ObjectUI.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1, linkifier);
      return;
    }

    /**
     * @param {?Array.<!SDK.RemoteObjectProperty>} properties
     * @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
     */
    function callback(properties, internalProperties) {
      treeElement.removeChildren();
      if (!properties)
        return;

      extraProperties = extraProperties || [];
      for (let i = 0; i < extraProperties.length; ++i)
        properties.push(extraProperties[i]);

      ObjectUI.ObjectPropertyTreeElement.populateWithProperties(
          treeElement, properties, internalProperties, skipProto, targetValue || value, linkifier, emptyPlaceholder);
    }

    if (flattenProtoChain)
      value.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */, callback);
    else
      SDK.RemoteObject.loadFromObjectPerProto(value, true /* generatePreview */, callback);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!Array.<!SDK.RemoteObjectProperty>} properties
   * @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
   * @param {boolean} skipProto
   * @param {?SDK.RemoteObject} value
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   */
  static populateWithProperties(
      treeNode,
      properties,
      internalProperties,
      skipProto,
      value,
      linkifier,
      emptyPlaceholder) {
    properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);

    const tailProperties = [];
    let protoProperty = null;
    for (let i = 0; i < properties.length; ++i) {
      const property = properties[i];
      property.parentObject = value;
      if (property.name === '__proto__' && !property.isAccessorProperty()) {
        protoProperty = property;
        continue;
      }

      if (property.isOwn && property.getter) {
        const getterProperty = new SDK.RemoteObjectProperty('get ' + property.name, property.getter, false);
        getterProperty.parentObject = value;
        tailProperties.push(getterProperty);
      }
      if (property.isOwn && property.setter) {
        const setterProperty = new SDK.RemoteObjectProperty('set ' + property.name, property.setter, false);
        setterProperty.parentObject = value;
        tailProperties.push(setterProperty);
      }
      const canShowProperty = property.getter || !property.isAccessorProperty();
      if (canShowProperty && property.name !== '__proto__')
        treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(property, linkifier));
    }
    for (let i = 0; i < tailProperties.length; ++i)
      treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(tailProperties[i], linkifier));
    if (!skipProto && protoProperty)
      treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(protoProperty, linkifier));

    if (internalProperties) {
      for (let i = 0; i < internalProperties.length; i++) {
        internalProperties[i].parentObject = value;
        const treeElement = new ObjectUI.ObjectPropertyTreeElement(internalProperties[i], linkifier);
        if (internalProperties[i].name === '[[Entries]]') {
          treeElement.setExpandable(true);
          treeElement.expand();
        }
        treeNode.appendChild(treeElement);
      }
    }

    ObjectUI.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {?string=} emptyPlaceholder
   */
  static _appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder) {
    if (treeNode.childCount())
      return;
    const title = createElementWithClass('div', 'gray-info-message');
    title.textContent = emptyPlaceholder || Common.UIString('No properties');
    const infoElement = new UI.TreeElement(title);
    treeNode.appendChild(infoElement);
  }

  /**
   * @param {?SDK.RemoteObject} object
   * @param {!Array.<string>} propertyPath
   * @param {function(?SDK.RemoteObject, boolean=)} callback
   * @return {!Element}
   */
  static createRemoteObjectAccessorPropertySpan(object, propertyPath, callback) {
    const rootElement = createElement('span');
    const element = rootElement.createChild('span');
    element.textContent = Common.UIString('(...)');
    if (!object)
      return rootElement;
    element.classList.add('object-value-calculate-value-button');
    element.title = Common.UIString('Invoke property getter');
    element.addEventListener('click', onInvokeGetterClick, false);

    function onInvokeGetterClick(event) {
      event.consume();
      object.getProperty(propertyPath, callback);
    }

    return rootElement;
  }

  /**
   * @param {!RegExp} regex
   * @param {string=} additionalCssClassName
   * @return {boolean}
   */
  setSearchRegex(regex, additionalCssClassName) {
    let cssClasses = UI.highlightedSearchResultClassName;
    if (additionalCssClassName)
      cssClasses += ' ' + additionalCssClassName;
    this.revertHighlightChanges();

    this._applySearch(regex, this.nameElement, cssClasses);
    const valueType = this.property.value.type;
    if (valueType !== 'object')
      this._applySearch(regex, this.valueElement, cssClasses);

    return !!this._highlightChanges.length;
  }

  /**
   * @param {!RegExp} regex
   * @param {!Element} element
   * @param {string} cssClassName
   */
  _applySearch(regex, element, cssClassName) {
    const ranges = [];
    const content = element.textContent;
    regex.lastIndex = 0;
    let match = regex.exec(content);
    while (match) {
      ranges.push(new TextUtils.SourceRange(match.index, match[0].length));
      match = regex.exec(content);
    }
    if (ranges.length)
      UI.highlightRangesWithStyleClass(element, ranges, cssClassName, this._highlightChanges);
  }

  revertHighlightChanges() {
    UI.revertDomChanges(this._highlightChanges);
    this._highlightChanges = [];
  }

  /**
   * @override
   */
  onpopulate() {
    const propertyValue = /** @type {!SDK.RemoteObject} */ (this.property.value);
    console.assert(propertyValue);
    const skipProto = this.treeOutline ? this.treeOutline._skipProto : true;
    const targetValue = this.property.name !== '__proto__' ? propertyValue : this.property.parentObject;
    ObjectUI.ObjectPropertyTreeElement._populate(
        this, propertyValue, skipProto, this._linkifier, undefined, undefined, undefined, targetValue);
  }

  /**
   * @override
   * @return {boolean}
   */
  ondblclick(event) {
    const inEditableElement = event.target.isSelfOrDescendant(this.valueElement) ||
        (this.expandedValueElement && event.target.isSelfOrDescendant(this.expandedValueElement));
    if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter))
      this._startEditing();
    return false;
  }

  /**
   * @override
   */
  onattach() {
    this.update();
    this._updateExpandable();
  }

  /**
   * @override
   */
  onexpand() {
    this._showExpandedValueElement(true);
  }

  /**
   * @override
   */
  oncollapse() {
    this._showExpandedValueElement(false);
  }

  /**
   * @param {boolean} value
   */
  _showExpandedValueElement(value) {
    if (!this.expandedValueElement)
      return;
    if (value)
      this._rowContainer.replaceChild(this.expandedValueElement, this.valueElement);
    else
      this._rowContainer.replaceChild(this.valueElement, this.expandedValueElement);
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @return {?Element}
   */
  _createExpandedValueElement(value) {
    const needsAlternateValue = value.hasChildren && !value.customPreview() && value.subtype !== 'node' &&
        value.type !== 'function' && (value.type !== 'object' || value.preview);
    if (!needsAlternateValue)
      return null;

    const valueElement = createElementWithClass('span', 'value');
    if (value.description === 'Object')
      valueElement.textContent = '';
    else
      valueElement.setTextContentTruncatedIfNeeded(value.description || '');
    valueElement.classList.add('object-value-' + (value.subtype || value.type));
    valueElement.title = value.description || '';
    return valueElement;
  }

  update() {
    this.nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(this.property.name);
    if (!this.property.enumerable)
      this.nameElement.classList.add('object-properties-section-dimmed');
    if (this.property.synthetic)
      this.nameElement.classList.add('synthetic-property');

    this._updatePropertyPath();

    if (this.property.value) {
      const showPreview = this.property.name !== '__proto__';
      this.valueElement = ObjectUI.ObjectPropertiesSection.createValueElementWithCustomSupport(
          this.property.value, this.property.wasThrown, showPreview, this.listItemElement, this._linkifier);
    } else if (this.property.getter) {
      this.valueElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
          this.property.parentObject, [this.property.name], this._onInvokeGetterClick.bind(this));
    } else {
      this.valueElement = createElementWithClass('span', 'object-value-undefined');
      this.valueElement.textContent = Common.UIString('<unreadable>');
      this.valueElement.title = Common.UIString('No property getter');
    }

    const valueText = this.valueElement.textContent;
    if (this.property.value && valueText && !this.property.wasThrown)
      this.expandedValueElement = this._createExpandedValueElement(this.property.value);

    this.listItemElement.removeChildren();
    this._rowContainer = UI.html`<span>${this.nameElement}: ${this.valueElement}</span>`;
    this.listItemElement.appendChild(this._rowContainer);
  }

  _updatePropertyPath() {
    if (this.nameElement.title)
      return;

    const name = this.property.name;

    if (this.property.synthetic) {
      this.nameElement.title = name;
      return;
    }

    const useDotNotation = /^(_|\$|[A-Z])(_|\$|[A-Z]|\d)*$/i;
    const isInteger = /^[1-9]\d*$/;

    const parentPath =
        (this.parent.nameElement && !this.parent.property.synthetic) ? this.parent.nameElement.title : '';

    if (useDotNotation.test(name))
      this.nameElement.title = parentPath ? `${parentPath}.${name}` : name;
    else if (isInteger.test(name))
      this.nameElement.title = parentPath + '[' + name + ']';
    else
      this.nameElement.title = parentPath + '["' + JSON.stringify(name) + '"]';
  }

  /**
   * @param {!Event} event
   */
  _contextMenuFired(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.appendApplicableItems(this);
    if (this.property.symbol)
      contextMenu.appendApplicableItems(this.property.symbol);
    if (this.property.value)
      contextMenu.appendApplicableItems(this.property.value);
    if (!this.property.synthetic && this.nameElement && this.nameElement.title) {
      const copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title);
      contextMenu.clipboardSection().appendItem(ls`Copy property path`, copyPathHandler);
    }
    if (this.property.parentObject instanceof SDK.LocalJSONObject) {
      contextMenu.viewSection().appendItem(ls`Expand recursively`, this.expandRecursively.bind(this, Number.MAX_VALUE));
      contextMenu.viewSection().appendItem(ls`Collapse children`, this.collapseChildren.bind(this));
    }
    contextMenu.show();
  }

  _startEditing() {
    if (this._prompt || !this.treeOutline._editable || this._readOnly)
      return;

    this._editableDiv = this._rowContainer.createChild('span', 'editable-div');

    let text = this.property.value.description;
    if (this.property.value.type === 'string' && typeof text === 'string')
      text = '"' + text + '"';

    this._editableDiv.setTextContentTruncatedIfNeeded(text, Common.UIString('<string is too large to edit>'));
    const originalContent = this._editableDiv.textContent;

    // Lie about our children to prevent expanding on double click and to collapse subproperties.
    this.setExpandable(false);
    this.listItemElement.classList.add('editing-sub-part');
    this.valueElement.classList.add('hidden');

    this._prompt = new ObjectUI.ObjectPropertyPrompt();

    const proxyElement =
        this._prompt.attachAndStartEditing(this._editableDiv, this._editingCommitted.bind(this, originalContent));
    this.listItemElement.getComponentSelection().selectAllChildren(this._editableDiv);
    proxyElement.addEventListener('keydown', this._promptKeyDown.bind(this, originalContent), false);
  }

  _editingEnded() {
    this._prompt.detach();
    delete this._prompt;
    this._editableDiv.remove();
    this._updateExpandable();
    this.listItemElement.scrollLeft = 0;
    this.listItemElement.classList.remove('editing-sub-part');
  }

  _editingCancelled() {
    this.valueElement.classList.remove('hidden');
    this._editingEnded();
  }

  /**
   * @param {string} originalContent
   */
  _editingCommitted(originalContent) {
    const userInput = this._prompt.text();
    if (userInput === originalContent) {
      this._editingCancelled();  // nothing changed, so cancel
      return;
    }

    this._editingEnded();
    this._applyExpression(userInput);
  }

  /**
   * @param {string} originalContent
   * @param {!Event} event
   */
  _promptKeyDown(originalContent, event) {
    if (isEnterKey(event)) {
      event.consume();
      this._editingCommitted(originalContent);
      return;
    }
    if (event.key === 'Escape') {
      event.consume();
      this._editingCancelled();
      return;
    }
  }

  /**
   * @param {string} expression
   */
  async _applyExpression(expression) {
    const property = SDK.RemoteObject.toCallArgument(this.property.symbol || this.property.name);
    expression = SDK.RuntimeModel.wrapObjectLiteralExpressionIfNeeded(expression.trim());

    if (this.property.synthetic) {
      let invalidate = false;
      if (expression)
        invalidate = await this.property.setSyntheticValue(expression);
      if (invalidate) {
        const parent = this.parent;
        parent.invalidateChildren();
        parent.onpopulate();
      } else {
        this.update();
      }
      return;
    }

    const errorPromise = expression ? this.property.parentObject.setPropertyValue(property, expression) :
                                      this.property.parentObject.deleteProperty(property);
    const error = await errorPromise;
    if (error) {
      this.update();
      return;
    }

    if (!expression) {
      // The property was deleted, so remove this tree element.
      this.parent.removeChild(this);
    } else {
      // Call updateSiblings since their value might be based on the value that just changed.
      const parent = this.parent;
      parent.invalidateChildren();
      parent.onpopulate();
    }
  }

  /**
   * @param {?SDK.RemoteObject} result
   * @param {boolean=} wasThrown
   */
  _onInvokeGetterClick(result, wasThrown) {
    if (!result)
      return;
    this.property.value = result;
    this.property.wasThrown = wasThrown;

    this.update();
    this.invalidateChildren();
    this._updateExpandable();
  }

  _updateExpandable() {
    if (this.property.value) {
      this.setExpandable(
          !this.property.value.customPreview() && this.property.value.hasChildren && !this.property.wasThrown);
    } else {
      this.setExpandable(false);
    }
  }

  /**
   * @return {string}
   */
  path() {
    return this.nameElement.title;
  }
};


/**
 * @unrestricted
 */
ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {number} propertyCount
   * @param {!Components.Linkifier=} linkifier
   */
  constructor(object, fromIndex, toIndex, propertyCount, linkifier) {
    super(String.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
    this.toggleOnClick = true;
    this.selectable = false;
    this._fromIndex = fromIndex;
    this._toIndex = toIndex;
    this._object = object;
    this._readOnly = true;
    this._propertyCount = propertyCount;
    this._linkifier = linkifier;
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {!Components.Linkifier=} linkifier
   */
  static _populateArray(treeNode, object, fromIndex, toIndex, linkifier) {
    ObjectUI.ArrayGroupingTreeElement._populateRanges(treeNode, object, fromIndex, toIndex, true, linkifier);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {boolean} topLevel
   * @param {!Components.Linkifier=} linkifier
   * @this {ObjectUI.ArrayGroupingTreeElement}
   */
  static _populateRanges(treeNode, object, fromIndex, toIndex, topLevel, linkifier) {
    object.callFunctionJSON(
        packRanges,
        [
          {value: fromIndex}, {value: toIndex}, {value: ObjectUI.ArrayGroupingTreeElement._bucketThreshold},
          {value: ObjectUI.ArrayGroupingTreeElement._sparseIterationThreshold},
          {value: ObjectUI.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold}
        ],
        callback);

    /**
     * Note: must declare params as optional.
     * @param {number=} fromIndex
     * @param {number=} toIndex
     * @param {number=} bucketThreshold
     * @param {number=} sparseIterationThreshold
     * @param {number=} getOwnPropertyNamesThreshold
     * @suppressReceiverCheck
     * @this {Object}
     */
    function packRanges(fromIndex, toIndex, bucketThreshold, sparseIterationThreshold, getOwnPropertyNamesThreshold) {
      let ownPropertyNames = null;
      const consecutiveRange = (toIndex - fromIndex >= sparseIterationThreshold) && ArrayBuffer.isView(this);
      const skipGetOwnPropertyNames = consecutiveRange && (toIndex - fromIndex >= getOwnPropertyNamesThreshold);

      function* arrayIndexes(object) {
        if (toIndex - fromIndex < sparseIterationThreshold) {
          for (let i = fromIndex; i <= toIndex; ++i) {
            if (i in object)
              yield i;
          }
        } else {
          ownPropertyNames = ownPropertyNames || Object.getOwnPropertyNames(object);
          for (let i = 0; i < ownPropertyNames.length; ++i) {
            const name = ownPropertyNames[i];
            const index = name >>> 0;
            if (('' + index) === name && fromIndex <= index && index <= toIndex)
              yield index;
          }
        }
      }

      let count = 0;
      if (consecutiveRange) {
        count = toIndex - fromIndex + 1;
      } else {
        for (const i of arrayIndexes(this))  // eslint-disable-line
          ++count;
      }

      let bucketSize = count;
      if (count <= bucketThreshold)
        bucketSize = count;
      else
        bucketSize = Math.pow(bucketThreshold, Math.ceil(Math.log(count) / Math.log(bucketThreshold)) - 1);

      const ranges = [];
      if (consecutiveRange) {
        for (let i = fromIndex; i <= toIndex; i += bucketSize) {
          const groupStart = i;
          let groupEnd = groupStart + bucketSize - 1;
          if (groupEnd > toIndex)
            groupEnd = toIndex;
          ranges.push([groupStart, groupEnd, groupEnd - groupStart + 1]);
        }
      } else {
        count = 0;
        let groupStart = -1;
        let groupEnd = 0;
        for (const i of arrayIndexes(this)) {
          if (groupStart === -1)
            groupStart = i;
          groupEnd = i;
          if (++count === bucketSize) {
            ranges.push([groupStart, groupEnd, count]);
            count = 0;
            groupStart = -1;
          }
        }
        if (count > 0)
          ranges.push([groupStart, groupEnd, count]);
      }

      return {ranges: ranges, skipGetOwnPropertyNames: skipGetOwnPropertyNames};
    }

    function callback(result) {
      if (!result)
        return;
      const ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges);
      if (ranges.length === 1) {
        ObjectUI.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, ranges[0][0], ranges[0][1], linkifier);
      } else {
        for (let i = 0; i < ranges.length; ++i) {
          const fromIndex = ranges[i][0];
          const toIndex = ranges[i][1];
          const count = ranges[i][2];
          if (fromIndex === toIndex)
            ObjectUI.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier);
          else
            treeNode.appendChild(new ObjectUI.ArrayGroupingTreeElement(object, fromIndex, toIndex, count, linkifier));
        }
      }
      if (topLevel) {
        ObjectUI.ArrayGroupingTreeElement._populateNonIndexProperties(
            treeNode, object, result.skipGetOwnPropertyNames, linkifier);
      }
    }
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {!Components.Linkifier=} linkifier
   * @this {ObjectUI.ArrayGroupingTreeElement}
   */
  static _populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier) {
    object.callFunction(
        buildArrayFragment,
        [{value: fromIndex}, {value: toIndex}, {value: ObjectUI.ArrayGroupingTreeElement._sparseIterationThreshold}],
        processArrayFragment.bind(this));

    /**
     * @suppressReceiverCheck
     * @this {Object}
     * @param {number=} fromIndex // must declare optional
     * @param {number=} toIndex // must declare optional
     * @param {number=} sparseIterationThreshold // must declare optional
     */
    function buildArrayFragment(fromIndex, toIndex, sparseIterationThreshold) {
      const result = Object.create(null);
      if (toIndex - fromIndex < sparseIterationThreshold) {
        for (let i = fromIndex; i <= toIndex; ++i) {
          if (i in this)
            result[i] = this[i];
        }
      } else {
        const ownPropertyNames = Object.getOwnPropertyNames(this);
        for (let i = 0; i < ownPropertyNames.length; ++i) {
          const name = ownPropertyNames[i];
          const index = name >>> 0;
          if (String(index) === name && fromIndex <= index && index <= toIndex)
            result[index] = this[index];
        }
      }
      return result;
    }

    /**
     * @param {?SDK.RemoteObject} arrayFragment
     * @param {boolean=} wasThrown
     * @this {ObjectUI.ArrayGroupingTreeElement}
     */
    function processArrayFragment(arrayFragment, wasThrown) {
      if (!arrayFragment || wasThrown)
        return;
      arrayFragment.getAllProperties(
          false /* accessorPropertiesOnly */, true /* generatePreview */, processProperties.bind(this));
    }

    /** @this {ObjectUI.ArrayGroupingTreeElement} */
    function processProperties(properties, internalProperties) {
      if (!properties)
        return;

      properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);
      for (let i = 0; i < properties.length; ++i) {
        properties[i].parentObject = this._object;
        const childTreeElement = new ObjectUI.ObjectPropertyTreeElement(properties[i], linkifier);
        childTreeElement._readOnly = true;
        treeNode.appendChild(childTreeElement);
      }
    }
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {boolean} skipGetOwnPropertyNames
   * @param {!Components.Linkifier=} linkifier
   * @this {ObjectUI.ArrayGroupingTreeElement}
   */
  static _populateNonIndexProperties(treeNode, object, skipGetOwnPropertyNames, linkifier) {
    object.callFunction(buildObjectFragment, [{value: skipGetOwnPropertyNames}], processObjectFragment.bind(this));

    /**
     * @param {boolean=} skipGetOwnPropertyNames
     * @suppressReceiverCheck
     * @this {Object}
     */
    function buildObjectFragment(skipGetOwnPropertyNames) {
      const result = {__proto__: this.__proto__};
      if (skipGetOwnPropertyNames)
        return result;
      const names = Object.getOwnPropertyNames(this);
      for (let i = 0; i < names.length; ++i) {
        const name = names[i];
        // Array index check according to the ES5-15.4.
        if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff)
          continue;
        const descriptor = Object.getOwnPropertyDescriptor(this, name);
        if (descriptor)
          Object.defineProperty(result, name, descriptor);
      }
      return result;
    }

    /**
     * @param {?SDK.RemoteObject} arrayFragment
     * @param {boolean=} wasThrown
     * @this {ObjectUI.ArrayGroupingTreeElement}
     */
    function processObjectFragment(arrayFragment, wasThrown) {
      if (!arrayFragment || wasThrown)
        return;
      arrayFragment.getOwnProperties(true /* generatePreview */, processProperties.bind(this));
    }

    /**
     * @param {?Array.<!SDK.RemoteObjectProperty>} properties
     * @param {?Array.<!SDK.RemoteObjectProperty>=} internalProperties
     * @this {ObjectUI.ArrayGroupingTreeElement}
     */
    function processProperties(properties, internalProperties) {
      if (!properties)
        return;
      properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);
      for (let i = 0; i < properties.length; ++i) {
        properties[i].parentObject = this._object;
        const childTreeElement = new ObjectUI.ObjectPropertyTreeElement(properties[i], linkifier);
        childTreeElement._readOnly = true;
        treeNode.appendChild(childTreeElement);
      }
    }
  }

  /**
   * @override
   */
  onpopulate() {
    if (this._propertyCount >= ObjectUI.ArrayGroupingTreeElement._bucketThreshold) {
      ObjectUI.ArrayGroupingTreeElement._populateRanges(
          this, this._object, this._fromIndex, this._toIndex, false, this._linkifier);
      return;
    }
    ObjectUI.ArrayGroupingTreeElement._populateAsFragment(
        this, this._object, this._fromIndex, this._toIndex, this._linkifier);
  }

  /**
   * @override
   */
  onattach() {
    this.listItemElement.classList.add('object-properties-section-name');
  }
};

ObjectUI.ArrayGroupingTreeElement._bucketThreshold = 100;
ObjectUI.ArrayGroupingTreeElement._sparseIterationThreshold = 250000;
ObjectUI.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold = 500000;


/**
 * @unrestricted
 */
ObjectUI.ObjectPropertyPrompt = class extends UI.TextPrompt {
  constructor() {
    super();
    this.initialize(
        ObjectUI.javaScriptAutocomplete.completionsForTextInCurrentContext.bind(ObjectUI.javaScriptAutocomplete));
  }
};

/**
 * @unrestricted
 */
ObjectUI.ObjectPropertiesSectionExpandController = class {
  constructor() {
    /** @type {!Set.<string>} */
    this._expandedProperties = new Set();
  }

  /**
   * @param {string} id
   * @param {!ObjectUI.ObjectPropertiesSection} section
   */
  watchSection(id, section) {
    section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._elementAttached, this);
    section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._elementExpanded, this);
    section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this);
    section[ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId] = id;

    if (this._expandedProperties.has(id))
      section.expand();
  }

  /**
   * @param {string} id
   */
  stopWatchSectionsWithId(id) {
    for (const property of this._expandedProperties) {
      if (property.startsWith(id + ':'))
        this._expandedProperties.delete(property);
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _elementAttached(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element)))
      element.expand();
  }

  /**
   * @param {!Common.Event} event
   */
  _elementExpanded(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    this._expandedProperties.add(this._propertyPath(element));
  }

  /**
   * @param {!Common.Event} event
   */
  _elementCollapsed(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    this._expandedProperties.delete(this._propertyPath(element));
  }

  /**
   * @param {!UI.TreeElement} treeElement
   * @return {string}
   */
  _propertyPath(treeElement) {
    const cachedPropertyPath = treeElement[ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol];
    if (cachedPropertyPath)
      return cachedPropertyPath;

    let current = treeElement;
    const rootElement = treeElement.treeOutline.objectTreeElement();

    let result;

    while (current !== rootElement) {
      let currentName = '';
      if (current.property)
        currentName = current.property.name;
      else
        currentName = typeof current.title === 'string' ? current.title : current.title.textContent;

      result = currentName + (result ? '.' + result : '');
      current = current.parent;
    }
    const treeOutlineId = treeElement.treeOutline[ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId];
    result = treeOutlineId + (result ? ':' + result : '');
    treeElement[ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol] = result;
    return result;
  }
};

ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol = Symbol('cachedPath');
ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId = Symbol('treeOutlineId');

/**
 * @implements {Common.Renderer}
 */
ObjectUI.ObjectPropertiesSection.Renderer = class {
  /**
   * @override
   * @param {!Object} object
   * @param {!Common.Renderer.Options=} options
   * @return {!Promise<?Node>}
   */
  render(object, options) {
    if (!(object instanceof SDK.RemoteObject))
      return Promise.reject(new Error('Can\'t render ' + object));
    options = options || {};
    const title = options.title;
    const section = new ObjectUI.ObjectPropertiesSection(object, title);
    if (!title)
      section.titleLessMode();
    if (options.expanded)
      section.expand();
    section.editable = !!options.editable;
    return Promise.resolve(section.element);
  }
};