/*
 * Copyright (C) 2011 Google Inc.  All rights reserved.
 * Copyright (C) 2007, 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.
 * 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.
 */
/**
 * @implements {Console.ConsoleViewportElement}
 * @unrestricted
 */
export default class ConsoleViewMessage {
  /**
   * @param {!SDK.ConsoleMessage} consoleMessage
   * @param {!Components.Linkifier} linkifier
   * @param {number} nestingLevel
   * @param {function(!Common.Event)} onResize
   */
  constructor(consoleMessage, linkifier, nestingLevel, onResize) {
    this._message = consoleMessage;
    this._linkifier = linkifier;
    this._repeatCount = 1;
    this._closeGroupDecorationCount = 0;
    this._nestingLevel = nestingLevel;
    /** @type {!Array<{element: !Element, forceSelect: function()}>} */
    this._selectableChildren = [];
    this._messageResized = onResize;

    /** @type {?DataGrid.DataGrid} */
    this._dataGrid = null;
    this._previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
    this._searchRegex = null;
    /** @type {?UI.Icon} */
    this._messageLevelIcon = null;
    this._traceExpanded = false;
    /** @type {?function(boolean)} */
    this._expandTrace = null;
    /** @type {?Element} */
    this._anchorElement = null;
  }

  /**
   * @override
   * @return {!Element}
   */
  element() {
    return this.toMessageElement();
  }

  /**
   * @override
   */
  wasShown() {
    if (this._dataGrid) {
      this._dataGrid.updateWidths();
    }
    this._isVisible = true;
  }

  onResize() {
    if (!this._isVisible) {
      return;
    }
    if (this._dataGrid) {
      this._dataGrid.onResize();
    }
  }

  /**
   * @override
   */
  willHide() {
    this._isVisible = false;
    this._cachedHeight = this.element().offsetHeight;
  }

  /**
   * @return {number}
   */
  fastHeight() {
    if (this._cachedHeight) {
      return this._cachedHeight;
    }
    // This value reflects the 18px min-height of .console-message, plus the
    // 1px border of .console-message-wrapper. Keep in sync with consoleView.css.
    const defaultConsoleRowHeight = 19;
    if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
      const table = this._message.parameters[0];
      if (table && table.preview) {
        return defaultConsoleRowHeight * table.preview.properties.length;
      }
    }
    return defaultConsoleRowHeight;
  }

  /**
   * @return {!SDK.ConsoleMessage}
   */
  consoleMessage() {
    return this._message;
  }

  /**
   * @return {!Element}
   */
  _buildTableMessage() {
    const formattedMessage = createElementWithClass('span', 'source-code');
    this._anchorElement = this._buildMessageAnchor();
    if (this._anchorElement) {
      formattedMessage.appendChild(this._anchorElement);
    }

    let table = this._message.parameters && this._message.parameters.length ? this._message.parameters[0] : null;
    if (table) {
      table = this._parameterToRemoteObject(table);
    }
    if (!table || !table.preview) {
      return this._buildMessage();
    }

    const rawValueColumnSymbol = Symbol('rawValueColumn');
    const columnNames = [];
    const preview = table.preview;
    const rows = [];
    for (let i = 0; i < preview.properties.length; ++i) {
      const rowProperty = preview.properties[i];
      let rowSubProperties;
      if (rowProperty.valuePreview) {
        rowSubProperties = rowProperty.valuePreview.properties;
      } else if (rowProperty.value) {
        rowSubProperties = [{name: rawValueColumnSymbol, type: rowProperty.type, value: rowProperty.value}];
      } else {
        continue;
      }

      const rowValue = {};
      const maxColumnsToRender = 20;
      for (let j = 0; j < rowSubProperties.length; ++j) {
        const cellProperty = rowSubProperties[j];
        let columnRendered = columnNames.indexOf(cellProperty.name) !== -1;
        if (!columnRendered) {
          if (columnNames.length === maxColumnsToRender) {
            continue;
          }
          columnRendered = true;
          columnNames.push(cellProperty.name);
        }

        if (columnRendered) {
          const cellElement = this._renderPropertyPreviewOrAccessor(table, [rowProperty, cellProperty]);
          cellElement.classList.add('console-message-nowrap-below');
          rowValue[cellProperty.name] = cellElement;
        }
      }
      rows.push([rowProperty.name, rowValue]);
    }

    const flatValues = [];
    for (let i = 0; i < rows.length; ++i) {
      const rowName = rows[i][0];
      const rowValue = rows[i][1];
      flatValues.push(rowName);
      for (let j = 0; j < columnNames.length; ++j) {
        flatValues.push(rowValue[columnNames[j]]);
      }
    }
    columnNames.unshift(Common.UIString('(index)'));
    const columnDisplayNames = columnNames.map(name => name === rawValueColumnSymbol ? Common.UIString('Value') : name);

    if (flatValues.length) {
      this._dataGrid = DataGrid.SortableDataGrid.create(columnDisplayNames, flatValues);
      this._dataGrid.setStriped(true);
      this._dataGrid.setFocusable(false);

      const formattedResult = createElementWithClass('span', 'console-message-text');
      const tableElement = formattedResult.createChild('div', 'console-message-formatted-table');
      const dataGridContainer = tableElement.createChild('span');
      tableElement.appendChild(this._formatParameter(table, true, false));
      dataGridContainer.appendChild(this._dataGrid.element);
      formattedMessage.appendChild(formattedResult);
      this._dataGrid.renderInline();
    }
    return formattedMessage;
  }

  /**
   * @return {!Element}
   */
  _buildMessage() {
    let messageElement;
    let messageText = this._message.messageText;
    if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
      switch (this._message.type) {
        case SDK.ConsoleMessage.MessageType.Trace:
          messageElement = this._format(this._message.parameters || ['console.trace']);
          break;
        case SDK.ConsoleMessage.MessageType.Clear:
          messageElement = createElementWithClass('span', 'console-info');
          if (Common.moduleSetting('preserveConsoleLog').get()) {
            messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
          } else {
            messageElement.textContent = Common.UIString('Console was cleared');
          }
          messageElement.title =
              ls`Clear all messages with ${UI.shortcutRegistry.shortcutTitleForAction('console.clear')}`;
          break;
        case SDK.ConsoleMessage.MessageType.Dir: {
          const obj = this._message.parameters ? this._message.parameters[0] : undefined;
          const args = ['%O', obj];
          messageElement = this._format(args);
          break;
        }
        case SDK.ConsoleMessage.MessageType.Profile:
        case SDK.ConsoleMessage.MessageType.ProfileEnd:
          messageElement = this._format([messageText]);
          break;
        case SDK.ConsoleMessage.MessageType.Assert:
          this._messagePrefix = ls`Assertion failed: `;
          // Fall through.
        default: {
          if (this._message.parameters && this._message.parameters.length === 1 &&
              this._message.parameters[0].type === 'string') {
            messageElement = this._tryFormatAsError(/** @type {string} */ (this._message.parameters[0].value));
          }
          const args = this._message.parameters || [messageText];
          messageElement = messageElement || this._format(args);
        }
      }
    } else {
      if (this._message.source === SDK.ConsoleMessage.MessageSource.Network) {
        messageElement = this._formatAsNetworkRequest() || this._format([messageText]);
      } else {
        const messageInParameters =
            this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
        if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation) {
          messageText = Common.UIString('[Violation] %s', messageText);
        } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention) {
          messageText = Common.UIString('[Intervention] %s', messageText);
        } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation) {
          messageText = Common.UIString('[Deprecation] %s', messageText);
        }
        const args = this._message.parameters || [messageText];
        if (messageInParameters) {
          args[0] = messageText;
        }
        messageElement = this._format(args);
      }
    }
    messageElement.classList.add('console-message-text');

    const formattedMessage = createElementWithClass('span', 'source-code');
    this._anchorElement = this._buildMessageAnchor();
    if (this._anchorElement) {
      formattedMessage.appendChild(this._anchorElement);
    }
    formattedMessage.appendChild(messageElement);
    return formattedMessage;
  }

  /**
   * @return {?Element}
   */
  _formatAsNetworkRequest() {
    const request = SDK.NetworkLog.requestForConsoleMessage(this._message);
    if (!request) {
      return null;
    }
    const messageElement = createElement('span');
    if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
      messageElement.createTextChild(request.requestMethod + ' ');
      const linkElement = Components.Linkifier.linkifyRevealable(request, request.url(), request.url());
      // Focus is handled by the viewport.
      linkElement.tabIndex = -1;
      this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
      messageElement.appendChild(linkElement);
      if (request.failed) {
        messageElement.createTextChildren(' ', request.localizedFailDescription);
      }
      if (request.statusCode !== 0) {
        messageElement.createTextChildren(' ', String(request.statusCode));
      }
      if (request.statusText) {
        messageElement.createTextChildren(' (', request.statusText, ')');
      }
    } else {
      const messageText = this._message.messageText;
      const fragment = this._linkifyWithCustomLinkifier(messageText, (text, url, lineNumber, columnNumber) => {
        let linkElement;
        if (url === request.url()) {
          linkElement = Components.Linkifier.linkifyRevealable(
              /** @type {!SDK.NetworkRequest} */ (request), url, request.url());
        } else {
          linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
        }
        linkElement.tabIndex = -1;
        this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
        return linkElement;
      });
      messageElement.appendChild(fragment);
    }
    return messageElement;
  }

  /**
   * @return {?Element}
   */
  _buildMessageAnchor() {
    let anchorElement = null;
    if (this._message.scriptId) {
      anchorElement = this._linkifyScriptId(
          this._message.scriptId, this._message.url || '', this._message.line, this._message.column);
    } else if (this._message.stackTrace && this._message.stackTrace.callFrames.length) {
      anchorElement = this._linkifyStackTraceTopFrame(this._message.stackTrace);
    } else if (this._message.url && this._message.url !== 'undefined') {
      anchorElement = this._linkifyLocation(this._message.url, this._message.line, this._message.column);
    }

    // Append a space to prevent the anchor text from being glued to the console message when the user selects and copies the console messages.
    if (anchorElement) {
      anchorElement.tabIndex = -1;
      this._selectableChildren.push({
        element: anchorElement,
        forceSelect: () => anchorElement.focus(),
      });
      const anchorWrapperElement = createElementWithClass('span', 'console-message-anchor');
      anchorWrapperElement.appendChild(anchorElement);
      anchorWrapperElement.createTextChild(' ');
      return anchorWrapperElement;
    }
    return null;
  }

  /**
   * @return {!Element}
   */
  _buildMessageWithStackTrace() {
    const toggleElement = createElementWithClass('div', 'console-message-stack-trace-toggle');
    const contentElement = toggleElement.createChild('div', 'console-message-stack-trace-wrapper');

    const messageElement = this._buildMessage();
    const icon = UI.Icon.create('smallicon-triangle-right', 'console-message-expand-icon');
    const clickableElement = contentElement.createChild('div');
    clickableElement.appendChild(icon);
    // Intercept focus to avoid highlight on click.
    clickableElement.tabIndex = -1;

    clickableElement.appendChild(messageElement);
    const stackTraceElement = contentElement.createChild('div');
    const stackTracePreview = Components.JSPresentationUtils.buildStackTracePreviewContents(
        this._message.runtimeModel().target(), this._linkifier, this._message.stackTrace);
    stackTraceElement.appendChild(stackTracePreview.element);
    for (const linkElement of stackTracePreview.links) {
      linkElement.tabIndex = -1;
      this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
    }
    stackTraceElement.classList.add('hidden');
    UI.ARIAUtils.markAsTreeitem(this.element());
    UI.ARIAUtils.setExpanded(this.element(), false);
    this._expandTrace = expand => {
      icon.setIconType(expand ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
      stackTraceElement.classList.toggle('hidden', !expand);
      UI.ARIAUtils.setExpanded(this.element(), expand);
      this._traceExpanded = expand;
    };

    /**
     * @this {!Console.ConsoleViewMessage}
     * @param {?Event} event
     */
    function toggleStackTrace(event) {
      if (UI.isEditing() || contentElement.hasSelection()) {
        return;
      }
      this._expandTrace(stackTraceElement.classList.contains('hidden'));
      event.consume();
    }

    clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
    if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
      this._expandTrace(true);
    }

    toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
    return toggleElement;
  }

  /**
   * @param {string} url
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?Element}
   */
  _linkifyLocation(url, lineNumber, columnNumber) {
    if (!this._message.runtimeModel()) {
      return null;
    }
    return this._linkifier.linkifyScriptLocation(
        this._message.runtimeModel().target(), null, url, lineNumber, columnNumber);
  }

  /**
   * @param {!Protocol.Runtime.StackTrace} stackTrace
   * @return {?Element}
   */
  _linkifyStackTraceTopFrame(stackTrace) {
    if (!this._message.runtimeModel()) {
      return null;
    }
    return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
  }

  /**
   * @param {string} scriptId
   * @param {string} url
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?Element}
   */
  _linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
    if (!this._message.runtimeModel()) {
      return null;
    }
    return this._linkifier.linkifyScriptLocation(
        this._message.runtimeModel().target(), scriptId, url, lineNumber, columnNumber);
  }

  /**
   * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|string} parameter
   * @return {!SDK.RemoteObject}
   */
  _parameterToRemoteObject(parameter) {
    if (parameter instanceof SDK.RemoteObject) {
      return parameter;
    }
    const runtimeModel = this._message.runtimeModel();
    if (!runtimeModel) {
      return SDK.RemoteObject.fromLocalObject(parameter);
    }
    if (typeof parameter === 'object') {
      return runtimeModel.createRemoteObject(parameter);
    }
    return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
  }

  /**
   * @param {!Array.<!SDK.RemoteObject|string>} rawParameters
   * @return {!Element}
   */
  _format(rawParameters) {
    // This node is used like a Builder. Values are continually appended onto it.
    const formattedResult = createElement('span');
    if (this._messagePrefix) {
      formattedResult.createChild('span').textContent = this._messagePrefix;
    }
    if (!rawParameters.length) {
      return formattedResult;
    }

    // Formatting code below assumes that parameters are all wrappers whereas frontend console
    // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
    // FIXME: Only pass runtime wrappers here.
    let parameters = [];
    for (let i = 0; i < rawParameters.length; ++i) {
      parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
    }

    // There can be string log and string eval result. We distinguish between them based on message type.
    const shouldFormatMessage =
        SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
        (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
         this._message.level === SDK.ConsoleMessage.MessageLevel.Error);

    // Multiple parameters with the first being a format string. Save unused substitutions.
    if (shouldFormatMessage) {
      const result = this._formatWithSubstitutionString(
          /** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
      parameters = result.unusedSubstitutions;
      if (parameters.length) {
        formattedResult.createTextChild(' ');
      }
    }

    // Single parameter, or unused substitutions from above.
    for (let i = 0; i < parameters.length; ++i) {
      // Inline strings when formatting.
      if (shouldFormatMessage && parameters[i].type === 'string') {
        formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
      } else {
        formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
      }
      if (i < parameters.length - 1) {
        formattedResult.createTextChild(' ');
      }
    }
    return formattedResult;
  }

  /**
   * @param {!SDK.RemoteObject} output
   * @param {boolean=} forceObjectFormat
   * @param {boolean=} includePreview
   * @return {!Element}
   */
  _formatParameter(output, forceObjectFormat, includePreview) {
    if (output.customPreview()) {
      return (new ObjectUI.CustomPreviewComponent(output)).element;
    }

    const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
    let element;
    switch (type) {
      case 'error':
        element = this._formatParameterAsError(output);
        break;
      case 'function':
        element = this._formatParameterAsFunction(output, includePreview);
        break;
      case 'array':
      case 'arraybuffer':
      case 'blob':
      case 'dataview':
      case 'generator':
      case 'iterator':
      case 'map':
      case 'object':
      case 'promise':
      case 'proxy':
      case 'set':
      case 'typedarray':
      case 'weakmap':
      case 'weakset':
        element = this._formatParameterAsObject(output, includePreview);
        break;
      case 'node':
        element = output.isNode() ? this._formatParameterAsNode(output) : this._formatParameterAsObject(output, false);
        break;
      case 'string':
        element = this._formatParameterAsString(output);
        break;
      case 'boolean':
      case 'date':
      case 'null':
      case 'number':
      case 'regexp':
      case 'symbol':
      case 'undefined':
      case 'bigint':
        element = this._formatParameterAsValue(output);
        break;
      default:
        element = this._formatParameterAsValue(output);
        console.error('Tried to format remote object of unknown type.');
    }
    element.classList.add('object-value-' + type);
    element.classList.add('source-code');
    return element;
  }

  /**
   * @param {!SDK.RemoteObject} obj
   * @return {!Element}
   */
  _formatParameterAsValue(obj) {
    const result = createElement('span');
    const description = obj.description || '';
    if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
      result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
    } else {
      result.createTextChild(description);
    }
    if (obj.objectId) {
      result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
    }
    return result;
  }

  /**
   * @param {!SDK.RemoteObject} obj
   * @param {boolean=} includePreview
   * @return {!Element}
   */
  _formatParameterAsObject(obj, includePreview) {
    const titleElement = createElementWithClass('span', 'console-object');
    if (includePreview && obj.preview) {
      titleElement.classList.add('console-object-preview');
      this._previewFormatter.appendObjectPreview(titleElement, obj.preview, false /* isEntry */);
    } else if (obj.type === 'function') {
      const functionElement = titleElement.createChild('span');
      ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(obj, functionElement, false);
      titleElement.classList.add('object-value-function');
    } else {
      titleElement.createTextChild(obj.description || '');
    }

    if (!obj.hasChildren || obj.customPreview()) {
      return titleElement;
    }

    const note = titleElement.createChild('span', 'object-state-note info-note');
    if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
      note.title = ls`This value will not be collected until console is cleared.`;
    } else {
      note.title = ls`Value below was evaluated just now.`;
    }

    const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
    section.element.classList.add('console-view-object-properties-section');
    section.enableContextMenu();
    section.setShowSelectionOnKeyboardFocus(true, true);
    this._selectableChildren.push(section);
    section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
    section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
    section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
    return section.element;
  }

  /**
   * @param {!SDK.RemoteObject} func
   * @param {boolean=} includePreview
   * @return {!Element}
   */
  _formatParameterAsFunction(func, includePreview) {
    const result = createElement('span');
    SDK.RemoteFunction.objectAsFunction(func).targetFunction().then(formatTargetFunction.bind(this));
    return result;

    /**
     * @param {!SDK.RemoteObject} targetFunction
     * @this {Console.ConsoleViewMessage}
     */
    function formatTargetFunction(targetFunction) {
      const functionElement = createElement('span');
      const promise = ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(
          targetFunction, functionElement, true, includePreview);
      result.appendChild(functionElement);
      if (targetFunction !== func) {
        const note = result.createChild('span', 'object-info-state-note');
        note.title = Common.UIString('Function was resolved from bound function.');
      }
      result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, targetFunction), false);
      promise.then(() => this._formattedParameterAsFunctionForTest());
    }
  }

  _formattedParameterAsFunctionForTest() {
  }

  /**
   * @param {!SDK.RemoteObject} obj
   * @param {!Event} event
   */
  _contextMenuEventFired(obj, event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.appendApplicableItems(obj);
    contextMenu.show();
  }

  /**
   * @param {?SDK.RemoteObject} object
   * @param {!Array.<!Protocol.Runtime.PropertyPreview>} propertyPath
   * @return {!Element}
   */
  _renderPropertyPreviewOrAccessor(object, propertyPath) {
    const property = propertyPath.peekLast();
    if (property.type === 'accessor') {
      return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
    }
    return this._previewFormatter.renderPropertyPreview(
        property.type, /** @type {string} */ (property.subtype), property.value);
  }

  /**
   * @param {!SDK.RemoteObject} remoteObject
   * @return {!Element}
   */
  _formatParameterAsNode(remoteObject) {
    const result = createElement('span');

    const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
    if (!domModel) {
      return result;
    }
    domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
      if (!node) {
        result.appendChild(this._formatParameterAsObject(remoteObject, false));
        return;
      }
      const renderResult = await UI.Renderer.render(/** @type {!Object} */ (node));
      if (renderResult) {
        if (renderResult.tree) {
          this._selectableChildren.push(renderResult.tree);
          renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementAttached, this._messageResized);
          renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._messageResized);
          renderResult.tree.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._messageResized);
        }
        result.appendChild(renderResult.node);
      } else {
        result.appendChild(this._formatParameterAsObject(remoteObject, false));
      }
      this._formattedParameterAsNodeForTest();
    });

    return result;
  }

  _formattedParameterAsNodeForTest() {
  }

  /**
   * @param {!SDK.RemoteObject} output
   * @return {!Element}
   */
  _formatParameterAsString(output) {
    const span = createElement('span');
    span.appendChild(this._linkifyStringAsFragment(output.description || ''));

    const result = createElement('span');
    result.createChild('span', 'object-value-string-quote').textContent = '"';
    result.appendChild(span);
    result.createChild('span', 'object-value-string-quote').textContent = '"';
    return result;
  }

  /**
   * @param {!SDK.RemoteObject} output
   * @return {!Element}
   */
  _formatParameterAsError(output) {
    const result = createElement('span');
    const errorSpan = this._tryFormatAsError(output.description || '');
    result.appendChild(errorSpan ? errorSpan : this._linkifyStringAsFragment(output.description || ''));
    return result;
  }

  /**
   * @param {!SDK.RemoteObject} output
   * @return {!Element}
   */
  _formatAsArrayEntry(output) {
    return this._previewFormatter.renderPropertyPreview(output.type, output.subtype, output.description);
  }

  /**
   * @param {?SDK.RemoteObject} object
   * @param {!Array.<string>} propertyPath
   * @param {boolean} isArrayEntry
   * @return {!Element}
   */
  _formatAsAccessorProperty(object, propertyPath, isArrayEntry) {
    const rootElement = ObjectUI.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
        object, propertyPath, onInvokeGetterClick.bind(this));

    /**
     * @param {!SDK.CallFunctionResult} result
     * @this {Console.ConsoleViewMessage}
     */
    function onInvokeGetterClick(result) {
      const wasThrown = result.wasThrown;
      const object = result.object;
      if (!object) {
        return;
      }
      rootElement.removeChildren();
      if (wasThrown) {
        const element = rootElement.createChild('span');
        element.textContent = Common.UIString('<exception>');
        element.title = /** @type {string} */ (object.description);
      } else if (isArrayEntry) {
        rootElement.appendChild(this._formatAsArrayEntry(object));
      } else {
        // Make a PropertyPreview from the RemoteObject similar to the backend logic.
        const maxLength = 100;
        const type = object.type;
        const subtype = object.subtype;
        let description = '';
        if (type !== 'function' && object.description) {
          if (type === 'string' || subtype === 'regexp') {
            description = object.description.trimMiddle(maxLength);
          } else {
            description = object.description.trimEndWithMaxLength(maxLength);
          }
        }
        rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
      }
    }

    return rootElement;
  }

  /**
   * @param {string} format
   * @param {!Array.<!SDK.RemoteObject>} parameters
   * @param {!Element} formattedResult
   */
  _formatWithSubstitutionString(format, parameters, formattedResult) {
    const formatters = {};

    /**
     * @param {boolean} force
     * @param {boolean} includePreview
     * @param {!SDK.RemoteObject} obj
     * @return {!Element}
     * @this {Console.ConsoleViewMessage}
     */
    function parameterFormatter(force, includePreview, obj) {
      return this._formatParameter(obj, force, includePreview);
    }

    function stringFormatter(obj) {
      return obj.description;
    }

    function floatFormatter(obj) {
      if (typeof obj.value !== 'number') {
        return 'NaN';
      }
      return obj.value;
    }

    function integerFormatter(obj) {
      if (obj.type === 'bigint') {
        return obj.description;
      }
      if (typeof obj.value !== 'number') {
        return 'NaN';
      }
      return Math.floor(obj.value);
    }

    function bypassFormatter(obj) {
      return (obj instanceof Node) ? obj : '';
    }

    let currentStyle = null;
    function styleFormatter(obj) {
      currentStyle = {};
      const buffer = createElement('span');
      buffer.setAttribute('style', obj.description);
      for (let i = 0; i < buffer.style.length; i++) {
        const property = buffer.style[i];
        if (isWhitelistedProperty(property)) {
          currentStyle[property] = buffer.style[property];
        }
      }
    }

    function isWhitelistedProperty(property) {
      // Make sure that allowed properties do not interfere with link visibility.
      const prefixes = [
        'background', 'border', 'color', 'font', 'line', 'margin', 'padding', 'text', '-webkit-background',
        '-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
      ];
      for (let i = 0; i < prefixes.length; i++) {
        if (property.startsWith(prefixes[i])) {
          return true;
        }
      }
      return false;
    }

    // Firebug uses %o for formatting objects.
    formatters.o = parameterFormatter.bind(this, false /* force */, true /* includePreview */);
    formatters.s = stringFormatter;
    formatters.f = floatFormatter;
    // Firebug allows both %i and %d for formatting integers.
    formatters.i = integerFormatter;
    formatters.d = integerFormatter;

    // Firebug uses %c for styling the message.
    formatters.c = styleFormatter;

    // Support %O to force object formatting, instead of the type-based %o formatting.
    formatters.O = parameterFormatter.bind(this, true /* force */, false /* includePreview */);

    formatters._ = bypassFormatter;

    /**
     * @param {!Element} a
     * @param {*} b
     * @this {!Console.ConsoleViewMessage}
     * @return {!Element}
     */
    function append(a, b) {
      if (b instanceof Node) {
        a.appendChild(b);
        return a;
      }
      if (typeof b === 'undefined') {
        return a;
      }
      if (!currentStyle) {
        a.appendChild(this._linkifyStringAsFragment(String(b)));
        return a;
      }
      const lines = String(b).split('\n');
      for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        const lineFragment = this._linkifyStringAsFragment(line);
        const wrapper = createElement('span');
        wrapper.style.setProperty('contain', 'paint');
        wrapper.style.setProperty('display', 'inline-block');
        wrapper.style.setProperty('max-width', '100%');
        wrapper.appendChild(lineFragment);
        applyCurrentStyle(wrapper);
        for (const child of wrapper.children) {
          if (child.classList.contains('devtools-link')) {
            this._applyForcedVisibleStyle(child);
          }
        }
        a.appendChild(wrapper);
        if (i < lines.length - 1) {
          a.appendChild(createElement('br'));
        }
      }
      return a;
    }

    /**
     * @param {!Element} element
     */
    function applyCurrentStyle(element) {
      for (const key in currentStyle) {
        element.style[key] = currentStyle[key];
      }
    }

    // String.format does treat formattedResult like a Builder, result is an object.
    return String.format(format, parameters, formatters, formattedResult, append.bind(this));
  }

  /**
   * @param {!Element} element
   */
  _applyForcedVisibleStyle(element) {
    element.style.setProperty('-webkit-text-stroke', '0', 'important');
    element.style.setProperty('text-decoration', 'underline', 'important');

    const themedColor = UI.themeSupport.patchColorText('rgb(33%, 33%, 33%)', UI.ThemeSupport.ColorUsage.Foreground);
    element.style.setProperty('color', themedColor, 'important');

    let backgroundColor = 'hsl(0, 0%, 100%)';
    if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
      backgroundColor = 'hsl(0, 100%, 97%)';
    } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
      backgroundColor = 'hsl(50, 100%, 95%)';
    }
    const themedBackgroundColor =
        UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
    element.style.setProperty('background-color', themedBackgroundColor, 'important');
  }

  /**
   * @return {boolean}
   */
  matchesFilterRegex(regexObject) {
    regexObject.lastIndex = 0;
    const contentElement = this.contentElement();
    const anchorText = this._anchorElement ? this._anchorElement.deepTextContent() : '';
    return (anchorText && regexObject.test(anchorText.trim())) ||
        regexObject.test(contentElement.deepTextContent().slice(anchorText.length));
  }

  /**
   * @param {string} filter
   * @return {boolean}
   */
  matchesFilterText(filter) {
    const text = this.contentElement().deepTextContent();
    return text.toLowerCase().includes(filter.toLowerCase());
  }

  updateTimestamp() {
    if (!this._contentElement) {
      return;
    }

    if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
      if (!this._timestampElement) {
        this._timestampElement = createElementWithClass('span', 'console-timestamp');
      }
      this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
      this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
      this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
    } else if (this._timestampElement) {
      this._timestampElement.remove();
      delete this._timestampElement;
    }
  }

  /**
   * @return {number}
   */
  nestingLevel() {
    return this._nestingLevel;
  }

  /**
   * @param {boolean} inSimilarGroup
   * @param {boolean=} isLast
   */
  setInSimilarGroup(inSimilarGroup, isLast) {
    this._inSimilarGroup = inSimilarGroup;
    this._lastInSimilarGroup = inSimilarGroup && !!isLast;
    if (this._similarGroupMarker && !inSimilarGroup) {
      this._similarGroupMarker.remove();
      this._similarGroupMarker = null;
    } else if (this._element && !this._similarGroupMarker && inSimilarGroup) {
      this._similarGroupMarker = createElementWithClass('div', 'nesting-level-marker');
      this._element.insertBefore(this._similarGroupMarker, this._element.firstChild);
      this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
    }
  }

  /**
   * @return {boolean}
   */
  isLastInSimilarGroup() {
    return this._inSimilarGroup && this._lastInSimilarGroup;
  }

  resetCloseGroupDecorationCount() {
    if (!this._closeGroupDecorationCount) {
      return;
    }
    this._closeGroupDecorationCount = 0;
    this._updateCloseGroupDecorations();
  }

  incrementCloseGroupDecorationCount() {
    ++this._closeGroupDecorationCount;
    this._updateCloseGroupDecorations();
  }

  _updateCloseGroupDecorations() {
    if (!this._nestingLevelMarkers) {
      return;
    }
    for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
      const marker = this._nestingLevelMarkers[i];
      marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
    }
  }

  /**
   * @return {number}
   */
  _focusedChildIndex() {
    if (!this._selectableChildren.length) {
      return -1;
    }
    return this._selectableChildren.findIndex(child => child.element.hasFocus());
  }

  /**
   * @param {!Event} event
   */
  _onKeyDown(event) {
    if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
      return;
    }
    if (this.maybeHandleOnKeyDown(event)) {
      event.consume(true);
    }
  }

  /**
   * @protected
   * @param {!Event} event
   */
  maybeHandleOnKeyDown(event) {
    // Handle trace expansion.
    const focusedChildIndex = this._focusedChildIndex();
    const isWrapperFocused = focusedChildIndex === -1;
    if (this._expandTrace && isWrapperFocused) {
      if ((event.key === 'ArrowLeft' && this._traceExpanded) || (event.key === 'ArrowRight' && !this._traceExpanded)) {
        this._expandTrace(!this._traceExpanded);
        return true;
      }
    }
    if (!this._selectableChildren.length) {
      return false;
    }

    if (event.key === 'ArrowLeft') {
      this._element.focus();
      return true;
    }
    if (event.key === 'ArrowRight') {
      if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
        return true;
      }
    }
    if (event.key === 'ArrowUp') {
      const firstVisibleChild = this._nearestVisibleChild(0);
      if (this._selectableChildren[focusedChildIndex] === firstVisibleChild && firstVisibleChild) {
        this._element.focus();
        return true;
      } else if (this._selectNearestVisibleChild(focusedChildIndex - 1, true /* backwards */)) {
        return true;
      }
    }
    if (event.key === 'ArrowDown') {
      if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
        return true;
      }
      if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param {number} fromIndex
   * @param {boolean=} backwards
   * @return {boolean}
   */
  _selectNearestVisibleChild(fromIndex, backwards) {
    const nearestChild = this._nearestVisibleChild(fromIndex, backwards);
    if (nearestChild) {
      nearestChild.forceSelect();
      return true;
    }
    return false;
  }

  /**
   * @param {number} fromIndex
   * @param {boolean=} backwards
   * @return {?{element: !Element, forceSelect: function()}}
   */
  _nearestVisibleChild(fromIndex, backwards) {
    const childCount = this._selectableChildren.length;
    if (fromIndex < 0 || fromIndex >= childCount) {
      return null;
    }
    const direction = backwards ? -1 : 1;
    let index = fromIndex;

    while (!this._selectableChildren[index].element.offsetParent) {
      index += direction;
      if (index < 0 || index >= childCount) {
        return null;
      }
    }
    return this._selectableChildren[index];
  }

  focusLastChildOrSelf() {
    if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
      this._element.focus();
    }
  }

  /**
   * @return {!Element}
   */
  contentElement() {
    if (this._contentElement) {
      return this._contentElement;
    }

    const contentElement = createElementWithClass('div', 'console-message');
    if (this._messageLevelIcon) {
      contentElement.appendChild(this._messageLevelIcon);
    }
    this._contentElement = contentElement;

    let formattedMessage;
    const shouldIncludeTrace = !!this._message.stackTrace &&
        (this._message.source === SDK.ConsoleMessage.MessageSource.Network ||
         this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
         this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
         this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
         this._message.type === SDK.ConsoleMessage.MessageType.Trace);
    if (this._message.runtimeModel() && shouldIncludeTrace) {
      formattedMessage = this._buildMessageWithStackTrace();
    } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
      formattedMessage = this._buildTableMessage();
    } else {
      formattedMessage = this._buildMessage();
    }
    contentElement.appendChild(formattedMessage);

    this.updateTimestamp();
    return this._contentElement;
  }

  /**
   * @return {!Element}
   */
  toMessageElement() {
    if (this._element) {
      return this._element;
    }

    this._element = createElement('div');
    this._element.tabIndex = -1;
    this._element.addEventListener('keydown', this._onKeyDown.bind(this));
    this.updateMessageElement();
    return this._element;
  }

  updateMessageElement() {
    if (!this._element) {
      return;
    }

    this._element.className = 'console-message-wrapper';
    this._element.removeChildren();
    if (this._message.isGroupStartMessage()) {
      this._element.classList.add('console-group-title');
    }
    if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
      this._element.classList.add('console-from-api');
    }
    if (this._inSimilarGroup) {
      this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
      this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
    }

    this._nestingLevelMarkers = [];
    for (let i = 0; i < this._nestingLevel; ++i) {
      this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
    }
    this._updateCloseGroupDecorations();
    this._element.message = this;

    switch (this._message.level) {
      case SDK.ConsoleMessage.MessageLevel.Verbose:
        this._element.classList.add('console-verbose-level');
        break;
      case SDK.ConsoleMessage.MessageLevel.Info:
        this._element.classList.add('console-info-level');
        if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
          this._element.classList.add('console-system-type');
        }
        break;
      case SDK.ConsoleMessage.MessageLevel.Warning:
        this._element.classList.add('console-warning-level');
        break;
      case SDK.ConsoleMessage.MessageLevel.Error:
        this._element.classList.add('console-error-level');
        break;
    }
    this._updateMessageLevelIcon();
    if (this._shouldRenderAsWarning()) {
      this._element.classList.add('console-warning-level');
    }

    this._element.appendChild(this.contentElement());
    if (this._repeatCount > 1) {
      this._showRepeatCountElement();
    }
  }

  /**
   * @return {boolean}
   */
  _shouldRenderAsWarning() {
    return (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
            this._message.level === SDK.ConsoleMessage.MessageLevel.Info) &&
        (this._message.source === SDK.ConsoleMessage.MessageSource.Violation ||
         this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation ||
         this._message.source === SDK.ConsoleMessage.MessageSource.Intervention ||
         this._message.source === SDK.ConsoleMessage.MessageSource.Recommendation);
  }

  _updateMessageLevelIcon() {
    let iconType = '';
    let accessibleName = '';
    if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
      iconType = 'smallicon-warning';
      accessibleName = ls`Warning`;
    } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
      iconType = 'smallicon-error';
      accessibleName = ls`Error`;
    }
    if (!iconType && !this._messageLevelIcon) {
      return;
    }
    if (iconType && !this._messageLevelIcon) {
      this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
      if (this._contentElement) {
        this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
      }
    }
    this._messageLevelIcon.setIconType(iconType);
    UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
  }

  /**
   * @return {number}
   */
  repeatCount() {
    return this._repeatCount || 1;
  }

  resetIncrementRepeatCount() {
    this._repeatCount = 1;
    if (!this._repeatCountElement) {
      return;
    }

    this._repeatCountElement.remove();
    if (this._contentElement) {
      this._contentElement.classList.remove('repeated-message');
    }
    delete this._repeatCountElement;
  }

  incrementRepeatCount() {
    this._repeatCount++;
    this._showRepeatCountElement();
  }

  /**
   * @param {number} repeatCount
   */
  setRepeatCount(repeatCount) {
    this._repeatCount = repeatCount;
    this._showRepeatCountElement();
  }

  _showRepeatCountElement() {
    if (!this._element) {
      return;
    }

    if (!this._repeatCountElement) {
      this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
      switch (this._message.level) {
        case SDK.ConsoleMessage.MessageLevel.Warning:
          this._repeatCountElement.type = 'warning';
          break;
        case SDK.ConsoleMessage.MessageLevel.Error:
          this._repeatCountElement.type = 'error';
          break;
        case SDK.ConsoleMessage.MessageLevel.Verbose:
          this._repeatCountElement.type = 'verbose';
          break;
        default:
          this._repeatCountElement.type = 'info';
      }
      if (this._shouldRenderAsWarning()) {
        this._repeatCountElement.type = 'warning';
      }

      this._element.insertBefore(this._repeatCountElement, this._contentElement);
      this._contentElement.classList.add('repeated-message');
    }
    this._repeatCountElement.textContent = this._repeatCount;
    let accessibleName = ls`Repeat ${this._repeatCount}`;
    if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
      accessibleName = ls`Warning ${accessibleName}`;
    } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
      accessibleName = ls`Error ${accessibleName}`;
    }
    UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
  }

  get text() {
    return this._message.messageText;
  }

  /**
   * @return {string}
   */
  toExportString() {
    const lines = [];
    const nodes = this.contentElement().childTextNodes();
    const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
    for (let i = 0; i < this.repeatCount(); ++i) {
      lines.push(messageContent);
    }
    return lines.join('\n');
  }

  /**
   * @param {?RegExp} regex
   */
  setSearchRegex(regex) {
    if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
      UI.revertDomChanges(this._searchHiglightNodeChanges);
    }
    this._searchRegex = regex;
    this._searchHighlightNodes = [];
    this._searchHiglightNodeChanges = [];
    if (!this._searchRegex) {
      return;
    }

    const text = this.contentElement().deepTextContent();
    let match;
    this._searchRegex.lastIndex = 0;
    const sourceRanges = [];
    while ((match = this._searchRegex.exec(text)) && match[0]) {
      sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
    }

    if (sourceRanges.length) {
      this._searchHighlightNodes =
          UI.highlightSearchResults(this.contentElement(), sourceRanges, this._searchHiglightNodeChanges);
    }
  }

  /**
   * @return {?RegExp}
   */
  searchRegex() {
    return this._searchRegex;
  }

  /**
   * @return {number}
   */
  searchCount() {
    return this._searchHighlightNodes.length;
  }

  /**
   * @return {!Element}
   */
  searchHighlightNode(index) {
    return this._searchHighlightNodes[index];
  }

  /**
   * @param {string} string
   * @return {?Element}
   */
  _tryFormatAsError(string) {
    /**
     * @param {string} prefix
     */
    function startsWith(prefix) {
      return string.startsWith(prefix);
    }

    const errorPrefixes =
        ['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
    if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
      return null;
    }
    const debuggerModel = this._message.runtimeModel().debuggerModel();
    const baseURL = this._message.runtimeModel().target().inspectedURL();

    const lines = string.split('\n');
    const links = [];
    let position = 0;
    for (let i = 0; i < lines.length; ++i) {
      position += i > 0 ? lines[i - 1].length + 1 : 0;
      const isCallFrameLine = /^\s*at\s/.test(lines[i]);
      if (!isCallFrameLine && links.length) {
        return null;
      }

      if (!isCallFrameLine) {
        continue;
      }

      let openBracketIndex = -1;
      let closeBracketIndex = -1;
      const inBracketsWithLineAndColumn = /\([^\)\(]+:\d+:\d+\)/g;
      const inBrackets = /\([^\)\(]+\)/g;
      let lastMatch = null;
      let currentMatch;
      while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
        lastMatch = currentMatch;
      }
      if (!lastMatch) {
        while ((currentMatch = inBrackets.exec(lines[i]))) {
          lastMatch = currentMatch;
        }
      }
      if (lastMatch) {
        openBracketIndex = lastMatch.index;
        closeBracketIndex = lastMatch.index + lastMatch[0].length - 1;
      }
      const hasOpenBracket = openBracketIndex !== -1;
      const left = hasOpenBracket ? openBracketIndex + 1 : lines[i].indexOf('at') + 3;
      const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
      const linkCandidate = lines[i].substring(left, right);
      const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
      if (!splitResult) {
        return null;
      }

      if (splitResult.url === '<anonymous>') {
        continue;
      }
      let url = parseOrScriptMatch(splitResult.url);
      if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
        url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
      }
      if (!url) {
        return null;
      }

      links.push({
        url: url,
        positionLeft: position + left,
        positionRight: position + right,
        lineNumber: splitResult.lineNumber,
        columnNumber: splitResult.columnNumber
      });
    }

    if (!links.length) {
      return null;
    }

    const formattedResult = createElement('span');
    let start = 0;
    for (let i = 0; i < links.length; ++i) {
      formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start, links[i].positionLeft)));
      const scriptLocationLink = this._linkifier.linkifyScriptLocation(
          debuggerModel.target(), null, links[i].url, links[i].lineNumber, links[i].columnNumber);
      scriptLocationLink.tabIndex = -1;
      this._selectableChildren.push({element: scriptLocationLink, forceSelect: () => scriptLocationLink.focus()});
      formattedResult.appendChild(scriptLocationLink);
      start = links[i].positionRight;
    }

    if (start !== string.length) {
      formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
    }

    return formattedResult;

    /**
     * @param {?string} url
     * @return {?string}
     */
    function parseOrScriptMatch(url) {
      if (!url) {
        return null;
      }
      const parsedURL = Common.ParsedURL.fromString(url);
      if (parsedURL) {
        return parsedURL.url;
      }
      if (debuggerModel.scriptsForSourceURL(url).length) {
        return url;
      }
      return null;
    }
  }

  /**
   * @param {string} string
   * @param {function(string,string,number=,number=):!Node} linkifier
   * @return {!DocumentFragment}
   */
  _linkifyWithCustomLinkifier(string, linkifier) {
    if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
      return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
    }
    const container = createDocumentFragment();
    const tokens = Console.ConsoleViewMessage._tokenizeMessageText(string);
    for (const token of tokens) {
      if (!token.text) {
        continue;
      }
      switch (token.type) {
        case 'url': {
          const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
          const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
          let linkNode;
          if (splitResult) {
            linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
          } else {
            linkNode = linkifier(token.text, token.value);
          }
          container.appendChild(linkNode);
          break;
        }
        default:
          container.appendChild(createTextNode(token.text));
          break;
      }
    }
    return container;
  }

  /**
   * @param {string} string
   * @return {!DocumentFragment}
   */
  _linkifyStringAsFragment(string) {
    return this._linkifyWithCustomLinkifier(string, (text, url, lineNumber, columnNumber) => {
      const linkElement = Components.Linkifier.linkifyURL(url, {text, lineNumber, columnNumber});
      linkElement.tabIndex = -1;
      this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
      return linkElement;
    });
  }

  /**
   * @param {string} string
   * @return {!Array<{type: string, text: (string|undefined)}>}
   */
  static _tokenizeMessageText(string) {
    if (!Console.ConsoleViewMessage._tokenizerRegexes) {
      const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
      const linkStringRegex = new RegExp(
          '(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' + controlCodes + '"]{2,}[^\\s' + controlCodes +
              '"\')}\\],:;.!?]',
          'u');
      const pathLineRegex = /(?:\/[\w\.-]*)+\:[\d]+/;
      const timeRegex = /took [\d]+ms/;
      const eventRegex = /'\w+' event/;
      const milestoneRegex = /\sM[6-7]\d/;
      const autofillRegex = /\(suggested: \"[\w-]+\"\)/;
      const handlers = new Map();
      handlers.set(linkStringRegex, 'url');
      handlers.set(pathLineRegex, 'url');
      handlers.set(timeRegex, 'time');
      handlers.set(eventRegex, 'event');
      handlers.set(milestoneRegex, 'milestone');
      handlers.set(autofillRegex, 'autofill');
      Console.ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
      Console.ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
    }
    if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
      return [{text: string, type: undefined}];
    }
    const results = TextUtils.TextUtils.splitStringByRegexes(string, Console.ConsoleViewMessage._tokenizerRegexes);
    return results.map(
        result => ({text: result.value, type: Console.ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
  }

  /**
   * @return {string}
   */
  groupKey() {
    if (!this._groupKey) {
      this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
    }
    return this._groupKey;
  }

  /**
   * @return {string}
   */
  groupTitle() {
    const tokens = Console.ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
    const result = tokens.reduce((acc, token) => {
      let text = token.text;
      if (token.type === 'url') {
        text = Common.UIString('<URL>');
      } else if (token.type === 'time') {
        text = Common.UIString('took <N>ms');
      } else if (token.type === 'event') {
        text = Common.UIString('<some> event');
      } else if (token.type === 'milestone') {
        text = Common.UIString(' M<XX>');
      } else if (token.type === 'autofill') {
        text = Common.UIString('<attribute>');
      }
      return acc + text;
    }, '');
    return result.replace(/[%]o/g, '');
  }
}

/**
 * @unrestricted
 */
export class ConsoleGroupViewMessage extends ConsoleViewMessage {
  /**
   * @param {!SDK.ConsoleMessage} consoleMessage
   * @param {!Components.Linkifier} linkifier
   * @param {number} nestingLevel
   * @param {function()} onToggle
   * @param {function(!Common.Event)} onResize
   */
  constructor(consoleMessage, linkifier, nestingLevel, onToggle, onResize) {
    console.assert(consoleMessage.isGroupStartMessage());
    super(consoleMessage, linkifier, nestingLevel, onResize);
    this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
    /** @type {?UI.Icon} */
    this._expandGroupIcon = null;
    this._onToggle = onToggle;
  }

  /**
   * @param {boolean} collapsed
   */
  _setCollapsed(collapsed) {
    this._collapsed = collapsed;
    if (this._expandGroupIcon) {
      this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
    }
    this._onToggle.call(null);
  }

  /**
   * @return {boolean}
   */
  collapsed() {
    return this._collapsed;
  }

  /**
   * @override
   * @param {!Event} event
   */
  maybeHandleOnKeyDown(event) {
    const focusedChildIndex = this._focusedChildIndex();
    if (focusedChildIndex === -1) {
      if ((event.key === 'ArrowLeft' && !this._collapsed) || (event.key === 'ArrowRight' && this._collapsed)) {
        this._setCollapsed(!this._collapsed);
        return true;
      }
    }
    return super.maybeHandleOnKeyDown(event);
  }

  /**
   * @override
   * @return {!Element}
   */
  toMessageElement() {
    if (!this._element) {
      super.toMessageElement();
      const iconType = this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down';
      this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
      // Intercept focus to avoid highlight on click.
      this._contentElement.tabIndex = -1;
      if (this._repeatCountElement) {
        this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
      } else {
        this._element.insertBefore(this._expandGroupIcon, this._contentElement);
      }
      this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
    }
    return this._element;
  }

  /**
   * @override
   */
  _showRepeatCountElement() {
    super._showRepeatCountElement();
    if (this._repeatCountElement && this._expandGroupIcon) {
      this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
    }
  }
}

/**
 * @const
 * @type {number}
 */
export const MaxLengthForLinks = 40;

export const _MaxTokenizableStringLength = 10000;
export const _LongStringVisibleLength = 5000;

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

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

/**
 * @implements {Console.ConsoleViewportElement}
 * @unrestricted
 * @constructor
 */
Console.ConsoleViewMessage = ConsoleViewMessage;

/**
 * @constructor
 */
Console.ConsoleGroupViewMessage = ConsoleGroupViewMessage;

/**
 * @const
 * @type {number}
 */
Console.ConsoleViewMessage.MaxLengthForLinks = MaxLengthForLinks;
Console.ConsoleViewMessage._MaxTokenizableStringLength = _MaxTokenizableStringLength;
Console.ConsoleViewMessage._LongStringVisibleLength = _LongStringVisibleLength;
