/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. 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 GOOGLE INC.
 * 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.
 */

Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  constructor(uiSourceCode) {
    super(workingCopy);
    this._uiSourceCode = uiSourceCode;

    if (Root.Runtime.experiments.isEnabled('sourceDiff')) {
      this._diff = new SourceFrame.SourceCodeDiff(this.textEditor);
    }

    this._muteSourceCodeEvents = false;
    this._isSettingContent = false;

    /** @type {?Persistence.PersistenceBinding} */
    this._persistenceBinding = Persistence.persistence.binding(uiSourceCode);

    /** @type {!Map<number, !Sources.UISourceCodeFrame.RowMessageBucket>} */
    this._rowMessageBuckets = new Map();
    /** @type {!Set<string>} */
    this._typeDecorationsPending = new Set();

    this._uiSourceCodeEventListeners = [];
    this._messageAndDecorationListeners = [];

    this._boundOnBindingChanged = this._onBindingChanged.bind(this);

    this.textEditor.addEventListener(
        SourceFrame.SourcesTextEditor.Events.EditorBlurred,
        () => UI.context.setFlavor(Sources.UISourceCodeFrame, null));
    this.textEditor.addEventListener(
        SourceFrame.SourcesTextEditor.Events.EditorFocused,
        () => UI.context.setFlavor(Sources.UISourceCodeFrame, this));
    Common.settings.moduleSetting('persistenceNetworkOverridesEnabled')
        .addChangeListener(this._onNetworkPersistenceChanged, this);


    this._errorPopoverHelper = new UI.PopoverHelper(this.element, this._getErrorPopoverContent.bind(this));
    this._errorPopoverHelper.setHasPadding(true);

    this._errorPopoverHelper.setTimeout(100, 100);

    /** @type {!Array<!Sources.UISourceCodeFrame.Plugin>} */
    this._plugins = [];

    this._initializeUISourceCode();

    /**
     * @return {!Promise<!Common.DeferredContent>}
     */
    function workingCopy() {
      if (uiSourceCode.isDirty()) {
        return Promise.resolve({content: uiSourceCode.workingCopy(), isEncoded: false});
      }
      return uiSourceCode.requestContent();
    }
  }

  _installMessageAndDecorationListeners() {
    if (this._persistenceBinding) {
      const networkSourceCode = this._persistenceBinding.network;
      const fileSystemSourceCode = this._persistenceBinding.fileSystem;
      this._messageAndDecorationListeners = [
        networkSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageAdded, this._onMessageAdded, this),
        networkSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageRemoved, this._onMessageRemoved, this),
        networkSourceCode.addEventListener(
            Workspace.UISourceCode.Events.LineDecorationAdded, this._onLineDecorationAdded, this),
        networkSourceCode.addEventListener(
            Workspace.UISourceCode.Events.LineDecorationRemoved, this._onLineDecorationRemoved, this),

        fileSystemSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageAdded, this._onMessageAdded, this),
        fileSystemSourceCode.addEventListener(
            Workspace.UISourceCode.Events.MessageRemoved, this._onMessageRemoved, this),
      ];
    } else {
      this._messageAndDecorationListeners = [
        this._uiSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageAdded, this._onMessageAdded, this),
        this._uiSourceCode.addEventListener(Workspace.UISourceCode.Events.MessageRemoved, this._onMessageRemoved, this),
        this._uiSourceCode.addEventListener(
            Workspace.UISourceCode.Events.LineDecorationAdded, this._onLineDecorationAdded, this),
        this._uiSourceCode.addEventListener(
            Workspace.UISourceCode.Events.LineDecorationRemoved, this._onLineDecorationRemoved, this)
      ];
    }
  }

  /**
   * @return {!Workspace.UISourceCode}
   */
  uiSourceCode() {
    return this._uiSourceCode;
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  setUISourceCode(uiSourceCode) {
    this._unloadUISourceCode();
    this._uiSourceCode = uiSourceCode;
    if (uiSourceCode.contentLoaded()) {
      if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
        this._innerSetContent(uiSourceCode.workingCopy());
      }
    } else {
      uiSourceCode.requestContent().then(() => {
        if (this._uiSourceCode !== uiSourceCode) {
          return;
        }
        if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
          this._innerSetContent(uiSourceCode.workingCopy());
        }
      });
    }
    this._initializeUISourceCode();
  }

  _unloadUISourceCode() {
    this._disposePlugins();
    for (const message of this._allMessages()) {
      this._removeMessageFromSource(message);
    }
    Common.EventTarget.removeEventListeners(this._messageAndDecorationListeners);
    Common.EventTarget.removeEventListeners(this._uiSourceCodeEventListeners);
    this._uiSourceCode.removeWorkingCopyGetter();
    Persistence.persistence.unsubscribeFromBindingEvent(this._uiSourceCode, this._boundOnBindingChanged);
  }

  _initializeUISourceCode() {
    this._uiSourceCodeEventListeners = [
      this._uiSourceCode.addEventListener(
          Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this),
      this._uiSourceCode.addEventListener(
          Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this),
      this._uiSourceCode.addEventListener(
          Workspace.UISourceCode.Events.TitleChanged, this._refreshHighlighterType, this)
    ];

    Persistence.persistence.subscribeForBindingEvent(this._uiSourceCode, this._boundOnBindingChanged);
    for (const message of this._allMessages()) {
      this._addMessageToSource(message);
    }
    this._installMessageAndDecorationListeners();
    this._updateStyle();
    this._decorateAllTypes();
    this._refreshHighlighterType();
    if (Root.Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
      const supportedPrettyTypes = new Set(['text/html', 'text/css', 'text/javascript']);
      this.setCanPrettyPrint(supportedPrettyTypes.has(this.highlighterType()), true);
    }
    this._ensurePluginsLoaded();
  }

  /**
   * @override
   */
  wasShown() {
    super.wasShown();
    // We need CodeMirrorTextEditor to be initialized prior to this call as it calls |cursorPositionToCoordinates| internally. @see crbug.com/506566
    setImmediate(this._updateBucketDecorations.bind(this));
    this.setEditable(this._canEditSource());
    for (const plugin of this._plugins) {
      plugin.wasShown();
    }
  }

  /**
   * @override
   */
  willHide() {
    for (const plugin of this._plugins) {
      plugin.willHide();
    }
    super.willHide();
    UI.context.setFlavor(Sources.UISourceCodeFrame, null);
    this._uiSourceCode.removeWorkingCopyGetter();
  }

  _refreshHighlighterType() {
    const binding = Persistence.persistence.binding(this._uiSourceCode);
    const highlighterType = binding ? binding.network.mimeType() : this._uiSourceCode.mimeType();
    if (this.highlighterType() === highlighterType) {
      return;
    }
    this._disposePlugins();
    this.setHighlighterType(highlighterType);
    this._ensurePluginsLoaded();
  }

  /**
   * @return {boolean}
   */
  _canEditSource() {
    if (this.hasLoadError()) {
      return false;
    }
    if (Persistence.persistence.binding(this._uiSourceCode)) {
      return true;
    }
    if (this._uiSourceCode.project().canSetFileContent()) {
      return true;
    }
    if (this._uiSourceCode.project().isServiceProject()) {
      return false;
    }
    if (this._uiSourceCode.project().type() === Workspace.projectTypes.Network &&
        Persistence.networkPersistenceManager.active()) {
      return true;
    }
    // Because live edit fails on large whitespace changes, pretty printed scripts are not editable.
    if (this.pretty && this._uiSourceCode.contentType().hasScripts()) {
      return false;
    }
    return this._uiSourceCode.contentType() !== Common.resourceTypes.Document;
  }

  _onNetworkPersistenceChanged() {
    this.setEditable(this._canEditSource());
  }

  commitEditing() {
    if (!this._uiSourceCode.isDirty()) {
      return;
    }

    this._muteSourceCodeEvents = true;
    this._uiSourceCode.commitWorkingCopy();
    this._muteSourceCodeEvents = false;
  }

  /**
   * @override
   * @param {?string} content
   * @param {?string} loadError
   */
  setContent(content, loadError) {
    this._disposePlugins();
    this._rowMessageBuckets.clear();
    super.setContent(content, loadError);
    for (const message of this._allMessages()) {
      this._addMessageToSource(message);
    }
    this._decorateAllTypes();
    this._ensurePluginsLoaded();
  }

  /**
   * @return {!Set<!Workspace.UISourceCode.Message>}
   */
  _allMessages() {
    if (this._persistenceBinding) {
      const combinedSet = this._persistenceBinding.network.messages();
      combinedSet.addAll(this._persistenceBinding.fileSystem.messages());
      return combinedSet;
    }
    return this._uiSourceCode.messages();
  }

  /**
   * @override
   * @param {!TextUtils.TextRange} oldRange
   * @param {!TextUtils.TextRange} newRange
   */
  onTextChanged(oldRange, newRange) {
    const wasPretty = this.pretty;
    super.onTextChanged(oldRange, newRange);
    this._errorPopoverHelper.hidePopover();
    if (this._isSettingContent) {
      return;
    }
    Sources.SourcesPanel.instance().updateLastModificationTime();
    this._muteSourceCodeEvents = true;
    if (this.isClean()) {
      this._uiSourceCode.resetWorkingCopy();
    } else {
      this._uiSourceCode.setWorkingCopyGetter(this.textEditor.text.bind(this.textEditor));
    }
    this._muteSourceCodeEvents = false;
    if (wasPretty !== this.pretty) {
      this._updateStyle();
      this._disposePlugins();
      this._ensurePluginsLoaded();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onWorkingCopyChanged(event) {
    if (this._muteSourceCodeEvents) {
      return;
    }
    this._innerSetContent(this._uiSourceCode.workingCopy());
  }

  /**
   * @param {!Common.Event} event
   */
  _onWorkingCopyCommitted(event) {
    if (!this._muteSourceCodeEvents) {
      this._innerSetContent(this._uiSourceCode.workingCopy());
    }
    this.contentCommitted();
    this._updateStyle();
  }

  _ensurePluginsLoaded() {
    if (!this.loaded || this._plugins.length) {
      return;
    }

    const binding = Persistence.persistence.binding(this._uiSourceCode);
    const pluginUISourceCode = binding ? binding.network : this._uiSourceCode;

    // The order of these plugins matters for toolbar items
    if (Sources.DebuggerPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.DebuggerPlugin(this.textEditor, pluginUISourceCode, this.transformer()));
    }
    if (Sources.CSSPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.CSSPlugin(this.textEditor));
    }
    if (!this.pretty && Sources.JavaScriptCompilerPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.JavaScriptCompilerPlugin(this.textEditor, pluginUISourceCode));
    }
    if (Sources.SnippetsPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.SnippetsPlugin(this.textEditor, pluginUISourceCode));
    }
    if (Sources.ScriptOriginPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.ScriptOriginPlugin(this.textEditor, pluginUISourceCode));
    }
    if (!this.pretty && Root.Runtime.experiments.isEnabled('sourceDiff') &&
        Sources.GutterDiffPlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.GutterDiffPlugin(this.textEditor, pluginUISourceCode));
    }
    if (Sources.CoveragePlugin.accepts(pluginUISourceCode)) {
      this._plugins.push(new Sources.CoveragePlugin(this.textEditor, pluginUISourceCode));
    }

    this.dispatchEventToListeners(Sources.UISourceCodeFrame.Events.ToolbarItemsChanged);
    for (const plugin of this._plugins) {
      plugin.wasShown();
    }
  }

  _disposePlugins() {
    this.textEditor.operation(() => {
      for (const plugin of this._plugins) {
        plugin.dispose();
      }
    });
    this._plugins = [];
  }

  _onBindingChanged() {
    const binding = Persistence.persistence.binding(this._uiSourceCode);
    if (binding === this._persistenceBinding) {
      return;
    }
    this._unloadUISourceCode();
    this._persistenceBinding = binding;
    this._initializeUISourceCode();
  }

  _updateStyle() {
    this.setEditable(this._canEditSource());
  }

  /**
   * @param {string} content
   */
  _innerSetContent(content) {
    this._isSettingContent = true;
    const oldContent = this.textEditor.text();
    if (this._diff) {
      this._diff.highlightModifiedLines(oldContent, content);
    }
    if (oldContent !== content) {
      this.setContent(content, null);
    }
    this._isSettingContent = false;
  }

  /**
   * @override
   * @return {!Promise}
   */
  async populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber) {
    await super.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber);
    contextMenu.appendApplicableItems(this._uiSourceCode);
    const location = this.transformer().editorToRawLocation(editorLineNumber, editorColumnNumber);
    contextMenu.appendApplicableItems(new Workspace.UILocation(this._uiSourceCode, location[0], location[1]));
    contextMenu.appendApplicableItems(this);
    for (const plugin of this._plugins) {
      await plugin.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber);
    }
  }

  dispose() {
    this._errorPopoverHelper.dispose();
    this._unloadUISourceCode();
    this.textEditor.dispose();
    this.detach();
    Common.settings.moduleSetting('persistenceNetworkOverridesEnabled')
        .removeChangeListener(this._onNetworkPersistenceChanged, this);
  }

  /**
   * @param {!Common.Event} event
   */
  _onMessageAdded(event) {
    const message = /** @type {!Workspace.UISourceCode.Message} */ (event.data);
    this._addMessageToSource(message);
  }

  /**
   * @param {!Workspace.UISourceCode.Message} message
   */
  _addMessageToSource(message) {
    if (!this.loaded) {
      return;
    }
    const editorLocation = this.transformer().rawToEditorLocation(message.lineNumber(), message.columnNumber());
    let editorLineNumber = editorLocation[0];
    if (editorLineNumber >= this.textEditor.linesCount) {
      editorLineNumber = this.textEditor.linesCount - 1;
    }
    if (editorLineNumber < 0) {
      editorLineNumber = 0;
    }

    let messageBucket = this._rowMessageBuckets.get(editorLineNumber);
    if (!messageBucket) {
      messageBucket = new Sources.UISourceCodeFrame.RowMessageBucket(this, this.textEditor, editorLineNumber);
      this._rowMessageBuckets.set(editorLineNumber, messageBucket);
    }
    messageBucket.addMessage(message);
  }

  /**
   * @param {!Common.Event} event
   */
  _onMessageRemoved(event) {
    const message = /** @type {!Workspace.UISourceCode.Message} */ (event.data);
    this._removeMessageFromSource(message);
  }

  /**
   * @param {!Workspace.UISourceCode.Message} message
   */
  _removeMessageFromSource(message) {
    if (!this.loaded) {
      return;
    }

    const editorLocation = this.transformer().rawToEditorLocation(message.lineNumber(), message.columnNumber());
    let editorLineNumber = editorLocation[0];
    if (editorLineNumber >= this.textEditor.linesCount) {
      editorLineNumber = this.textEditor.linesCount - 1;
    }
    if (editorLineNumber < 0) {
      editorLineNumber = 0;
    }

    const messageBucket = this._rowMessageBuckets.get(editorLineNumber);
    if (!messageBucket) {
      return;
    }
    messageBucket.removeMessage(message);
    if (!messageBucket.uniqueMessagesCount()) {
      messageBucket.detachFromEditor();
      this._rowMessageBuckets.delete(editorLineNumber);
    }
  }

  /**
   * @param {!Event} event
   * @return {?UI.PopoverRequest}
   */
  _getErrorPopoverContent(event) {
    const element = event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ||
        event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-wave');
    if (!element) {
      return null;
    }
    const anchor = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ?
        element.boxInWindow() :
        new AnchorBox(event.clientX, event.clientY, 1, 1);
    return {
      box: anchor,
      show: popover => {
        const messageBucket = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration')._messageBucket;
        const messagesOutline = messageBucket.messagesDescription();
        popover.contentElement.appendChild(messagesOutline);
        return Promise.resolve(true);
      }
    };
  }

  _updateBucketDecorations() {
    for (const bucket of this._rowMessageBuckets.values()) {
      bucket._updateDecoration();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _onLineDecorationAdded(event) {
    const marker = /** @type {!Workspace.UISourceCode.LineMarker} */ (event.data);
    this._decorateTypeThrottled(marker.type());
  }

  /**
   * @param {!Common.Event} event
   */
  _onLineDecorationRemoved(event) {
    const marker = /** @type {!Workspace.UISourceCode.LineMarker} */ (event.data);
    this._decorateTypeThrottled(marker.type());
  }

  /**
   * @param {string} type
   */
  async _decorateTypeThrottled(type) {
    if (this._typeDecorationsPending.has(type)) {
      return;
    }
    this._typeDecorationsPending.add(type);
    const decorator = await self.runtime.extensions(SourceFrame.LineDecorator)
                          .find(extension => extension.descriptor()['decoratorType'] === type)
                          .instance();
    this._typeDecorationsPending.delete(type);
    this.textEditor.codeMirror().operation(() => {
      decorator.decorate(
          this._persistenceBinding ? this._persistenceBinding.network : this.uiSourceCode(), this.textEditor, type);
    });
  }

  _decorateAllTypes() {
    if (!this.loaded) {
      return;
    }
    for (const extension of self.runtime.extensions(SourceFrame.LineDecorator)) {
      const type = extension.descriptor()['decoratorType'];
      if (this._uiSourceCode.decorationsForType(type)) {
        this._decorateTypeThrottled(type);
      }
    }
  }

  /**
   * @override
   * @return {!Array<!UI.ToolbarItem>}
   */
  syncToolbarItems() {
    const leftToolbarItems = super.syncToolbarItems();
    const rightToolbarItems = [];
    for (const plugin of this._plugins) {
      leftToolbarItems.pushAll(plugin.leftToolbarItems());
      rightToolbarItems.pushAll(plugin.rightToolbarItems());
    }

    if (!rightToolbarItems.length) {
      return leftToolbarItems;
    }

    return [...leftToolbarItems, new UI.ToolbarSeparator(true), ...rightToolbarItems];
  }

  /**
   * @override
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} lineNumber
   * @return {!Promise}
   */
  async populateLineGutterContextMenu(contextMenu, lineNumber) {
    await super.populateLineGutterContextMenu(contextMenu, lineNumber);
    for (const plugin of this._plugins) {
      await plugin.populateLineGutterContextMenu(contextMenu, lineNumber);
    }
  }
};

Sources.UISourceCodeFrame._iconClassPerLevel = {};
Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Error] = 'smallicon-error';
Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'smallicon-warning';

Sources.UISourceCodeFrame._bubbleTypePerLevel = {};
Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Error] = 'error';
Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Level.Warning] = 'warning';

Sources.UISourceCodeFrame._lineClassPerLevel = {};
Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Error] =
    'text-editor-line-with-error';
Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Level.Warning] =
    'text-editor-line-with-warning';

/**
 * @unrestricted
 */
Sources.UISourceCodeFrame.RowMessage = class {
  /**
   * @param {!Workspace.UISourceCode.Message} message
   */
  constructor(message) {
    this._message = message;
    this._repeatCount = 1;
    this.element = createElementWithClass('div', 'text-editor-row-message');
    this._icon = this.element.createChild('label', '', 'dt-icon-label');
    this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[message.level()];
    this._repeatCountElement =
        this.element.createChild('span', 'text-editor-row-message-repeat-count hidden', 'dt-small-bubble');
    this._repeatCountElement.type = Sources.UISourceCodeFrame._bubbleTypePerLevel[message.level()];
    const linesContainer = this.element.createChild('div');
    const lines = this._message.text().split('\n');
    for (let i = 0; i < lines.length; ++i) {
      const messageLine = linesContainer.createChild('div');
      messageLine.textContent = lines[i];
    }
  }

  /**
   * @return {!Workspace.UISourceCode.Message}
   */
  message() {
    return this._message;
  }

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

  setRepeatCount(repeatCount) {
    if (this._repeatCount === repeatCount) {
      return;
    }
    this._repeatCount = repeatCount;
    this._updateMessageRepeatCount();
  }

  _updateMessageRepeatCount() {
    this._repeatCountElement.textContent = this._repeatCount;
    const showRepeatCount = this._repeatCount > 1;
    this._repeatCountElement.classList.toggle('hidden', !showRepeatCount);
    this._icon.classList.toggle('hidden', showRepeatCount);
  }
};

Sources.UISourceCodeFrame.RowMessageBucket = class {
  /**
   * @param {!Sources.UISourceCodeFrame} sourceFrame
   * @param {!TextEditor.CodeMirrorTextEditor} textEditor
   * @param {number} editorLineNumber
   */
  constructor(sourceFrame, textEditor, editorLineNumber) {
    this._sourceFrame = sourceFrame;
    this.textEditor = textEditor;
    this._lineHandle = textEditor.textEditorPositionHandle(editorLineNumber, 0);
    this._decoration = createElementWithClass('div', 'text-editor-line-decoration');
    this._decoration._messageBucket = this;
    this._wave = this._decoration.createChild('div', 'text-editor-line-decoration-wave');
    this._icon = this._wave.createChild('span', 'text-editor-line-decoration-icon', 'dt-icon-label');
    /** @type {?number} */
    this._decorationStartColumn = null;

    this._messagesDescriptionElement = createElementWithClass('div', 'text-editor-messages-description-container');
    /** @type {!Array.<!Sources.UISourceCodeFrame.RowMessage>} */
    this._messages = [];

    this._level = null;
  }

  /**
   * @param {number} editorLineNumber
   * @param {number} columnNumber
   */
  _updateWavePosition(editorLineNumber, columnNumber) {
    editorLineNumber = Math.min(editorLineNumber, this.textEditor.linesCount - 1);
    const lineText = this.textEditor.line(editorLineNumber);
    columnNumber = Math.min(columnNumber, lineText.length);
    const lineIndent = TextUtils.TextUtils.lineIndent(lineText).length;
    const startColumn = Math.max(columnNumber - 1, lineIndent);
    if (this._decorationStartColumn === startColumn) {
      return;
    }
    if (this._decorationStartColumn !== null) {
      this.textEditor.removeDecoration(this._decoration, editorLineNumber);
    }
    this.textEditor.addDecoration(this._decoration, editorLineNumber, startColumn);
    this._decorationStartColumn = startColumn;
  }

  /**
   * @return {!Element}
   */
  messagesDescription() {
    this._messagesDescriptionElement.removeChildren();
    UI.appendStyle(this._messagesDescriptionElement, 'source_frame/messagesPopover.css');
    for (let i = 0; i < this._messages.length; ++i) {
      this._messagesDescriptionElement.appendChild(this._messages[i].element);
    }

    return this._messagesDescriptionElement;
  }

  detachFromEditor() {
    const position = this._lineHandle.resolve();
    if (!position) {
      return;
    }
    const editorLineNumber = position.lineNumber;
    if (this._level) {
      this.textEditor.toggleLineClass(
          editorLineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], false);
    }
    if (this._decorationStartColumn !== null) {
      this.textEditor.removeDecoration(this._decoration, editorLineNumber);
      this._decorationStartColumn = null;
    }
  }

  /**
   * @return {number}
   */
  uniqueMessagesCount() {
    return this._messages.length;
  }

  /**
   * @param {!Workspace.UISourceCode.Message} message
   */
  addMessage(message) {
    for (let i = 0; i < this._messages.length; ++i) {
      const rowMessage = this._messages[i];
      if (rowMessage.message().isEqual(message)) {
        rowMessage.setRepeatCount(rowMessage.repeatCount() + 1);
        return;
      }
    }

    const rowMessage = new Sources.UISourceCodeFrame.RowMessage(message);
    this._messages.push(rowMessage);
    this._updateDecoration();
  }

  /**
   * @param {!Workspace.UISourceCode.Message} message
   */
  removeMessage(message) {
    for (let i = 0; i < this._messages.length; ++i) {
      const rowMessage = this._messages[i];
      if (!rowMessage.message().isEqual(message)) {
        continue;
      }
      rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
      if (!rowMessage.repeatCount()) {
        this._messages.splice(i, 1);
      }
      this._updateDecoration();
      return;
    }
  }

  _updateDecoration() {
    if (!this._sourceFrame.isShowing()) {
      return;
    }
    if (!this._messages.length) {
      return;
    }
    const position = this._lineHandle.resolve();
    if (!position) {
      return;
    }

    const editorLineNumber = position.lineNumber;
    let columnNumber = Number.MAX_VALUE;
    let maxMessage = null;
    for (let i = 0; i < this._messages.length; ++i) {
      const message = this._messages[i].message();
      const editorLocation =
          this._sourceFrame.transformer().rawToEditorLocation(editorLineNumber, message.columnNumber());
      columnNumber = Math.min(columnNumber, editorLocation[1]);
      if (!maxMessage || Workspace.UISourceCode.Message.messageLevelComparator(maxMessage, message) < 0) {
        maxMessage = message;
      }
    }
    this._updateWavePosition(editorLineNumber, columnNumber);

    if (this._level === maxMessage.level()) {
      return;
    }
    if (this._level) {
      this.textEditor.toggleLineClass(
          editorLineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], false);
      this._icon.type = '';
    }
    this._level = maxMessage.level();
    if (!this._level) {
      return;
    }
    this.textEditor.toggleLineClass(editorLineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], true);
    this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[this._level];
  }
};

Workspace.UISourceCode.Message._messageLevelPriority = {
  'Warning': 3,
  'Error': 4
};

/**
 * @param {!Workspace.UISourceCode.Message} a
 * @param {!Workspace.UISourceCode.Message} b
 * @return {number}
 */
Workspace.UISourceCode.Message.messageLevelComparator = function(a, b) {
  return Workspace.UISourceCode.Message._messageLevelPriority[a.level()] -
      Workspace.UISourceCode.Message._messageLevelPriority[b.level()];
};

Sources.UISourceCodeFrame.Plugin = class {
  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  static accepts(uiSourceCode) {
    return false;
  }

  wasShown() {
  }

  willHide() {
  }

  /**
   * @return {!Array<!UI.ToolbarItem>}
   */
  rightToolbarItems() {
    return [];
  }

  /**
   * @return {!Array<!UI.ToolbarItem>}
   */
  leftToolbarItems() {
    return [];
  }

  /**
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} lineNumber
   * @return {!Promise}
   */
  populateLineGutterContextMenu(contextMenu, lineNumber) {
    return Promise.resolve();
  }

  /**
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {!Promise}
   */
  populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) {
    return Promise.resolve();
  }

  dispose() {
  }
};

/** @enum {symbol} */
Sources.UISourceCodeFrame.Events = {
  ToolbarItemsChanged: Symbol('ToolbarItemsChanged')
};
