/*
 * Copyright (C) 2011 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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.
 */

/**
 * @extends {WebInspector.VBox}
 * @constructor
 * @implements {WebInspector.Replaceable}
 * @param {!WebInspector.ContentProvider} contentProvider
 */
WebInspector.SourceFrame = function(contentProvider)
{
    WebInspector.VBox.call(this);
    this.element.classList.add("script-view");

    this._url = contentProvider.contentURL();
    this._contentProvider = contentProvider;

    var textEditorDelegate = new WebInspector.TextEditorDelegateForSourceFrame(this);

    this._textEditor = new WebInspector.CodeMirrorTextEditor(this._url, textEditorDelegate);

    this._currentSearchResultIndex = -1;
    this._searchResults = [];

    this._messages = [];
    this._rowMessageBuckets = {};

    this._textEditor.setReadOnly(!this.canEditSource());

    this._shortcuts = {};
    this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);

    this._sourcePosition = new WebInspector.StatusBarText("", "source-frame-cursor-position");

    this._errorPopoverHelper = new WebInspector.PopoverHelper(this.element, this._getErrorAnchor.bind(this), this._showErrorPopover.bind(this));
    this._errorPopoverHelper.setTimeout(100, 100);
}

/**
 * @param {string} query
 * @param {string=} modifiers
 * @return {!RegExp}
 */
WebInspector.SourceFrame.createSearchRegex = function(query, modifiers)
{
    var regex;
    modifiers = modifiers || "";

    // First try creating regex if user knows the / / hint.
    try {
        if (/^\/.+\/$/.test(query)) {
            regex = new RegExp(query.substring(1, query.length - 1), modifiers);
            regex.__fromRegExpQuery = true;
        }
    } catch (e) {
        // Silent catch.
    }

    // Otherwise just do case-insensitive search.
    if (!regex)
        regex = createPlainTextSearchRegex(query, "i" + modifiers);

    return regex;
}

WebInspector.SourceFrame.Events = {
    ScrollChanged: "ScrollChanged",
    SelectionChanged: "SelectionChanged",
    JumpHappened: "JumpHappened"
}

WebInspector.SourceFrame.prototype = {
    /**
     * @param {!Element} target
     * @param {!Event} event
     * @return {(!Element|undefined)}
     */
    _getErrorAnchor: function(target, event)
    {
        var element = target.enclosingNodeOrSelfWithClass("text-editor-line-decoration-icon")
            || target.enclosingNodeOrSelfWithClass("text-editor-line-decoration-wave");
        if (!element)
            return;
        this._errorWavePopoverAnchor = new AnchorBox(event.clientX, event.clientY, 1, 1);
        return element;
    },

    /**
     * @param {!Element} anchor
     * @param {!WebInspector.Popover} popover
     */
    _showErrorPopover: function(anchor, popover)
    {
        var messageBucket = anchor.enclosingNodeOrSelfWithClass("text-editor-line-decoration")._messageBucket;
        var messagesOutline = messageBucket.messagesDescription();
        var popoverAnchor = anchor.enclosingNodeOrSelfWithClass("text-editor-line-decoration-icon") ? anchor : this._errorWavePopoverAnchor;
        popover.show(messagesOutline, popoverAnchor);
    },

    /**
     * @param {number} key
     * @param {function():boolean} handler
     */
    addShortcut: function(key, handler)
    {
        this._shortcuts[key] = handler;
    },

    wasShown: function()
    {
        this._ensureContentLoaded();
        this._textEditor.show(this.element);
        this._editorAttached = true;
        for (var line in this._rowMessageBuckets) {
            var bucket = this._rowMessageBuckets[line];
            bucket._updateDecorationPosition();
        }
        this._wasShownOrLoaded();
    },

    /**
     * @return {boolean}
     */
    _isEditorShowing: function()
    {
        return this.isShowing() && this._editorAttached;
    },

    willHide: function()
    {
        WebInspector.View.prototype.willHide.call(this);

        this._clearPositionToReveal();
    },

    /**
     * @return {?Element}
     */
    statusBarText: function()
    {
        return this._sourcePosition.element;
    },

    /**
     * @return {!Array.<!Element>}
     */
    statusBarItems: function()
    {
        return [];
    },

    /**
     * @return {!Element}
     */
    defaultFocusedElement: function()
    {
        return this._textEditor.defaultFocusedElement();
    },

    get loaded()
    {
        return this._loaded;
    },

    /**
     * @return {boolean}
     */
    hasContent: function()
    {
        return true;
    },

    get textEditor()
    {
        return this._textEditor;
    },

    _ensureContentLoaded: function()
    {
        if (!this._contentRequested) {
            this._contentRequested = true;
            this._contentProvider.requestContent(this.setContent.bind(this));
        }
    },

    addMessage: function(msg)
    {
        this._messages.push(msg);
        if (this.loaded)
            this.addMessageToSource(msg.line - 1, msg);
    },

    clearMessages: function()
    {
        for (var line in this._rowMessageBuckets) {
            var bubble = this._rowMessageBuckets[line];
            bubble.detachFromEditor();
        }

        this._messages = [];
        this._rowMessageBuckets = {};
    },

    /**
     * @param {number} line
     * @param {number=} column
     * @param {boolean=} shouldHighlight
     */
    revealPosition: function(line, column, shouldHighlight)
    {
        this._clearLineToScrollTo();
        this._clearSelectionToSet();
        this._positionToReveal = { line: line, column: column, shouldHighlight: shouldHighlight };
        this._innerRevealPositionIfNeeded();
    },

    _innerRevealPositionIfNeeded: function()
    {
        if (!this._positionToReveal)
            return;

        if (!this.loaded || !this._isEditorShowing())
            return;

        this._textEditor.revealPosition(this._positionToReveal.line, this._positionToReveal.column, this._positionToReveal.shouldHighlight);
        delete this._positionToReveal;
    },

    _clearPositionToReveal: function()
    {
        this._textEditor.clearPositionHighlight();
        delete this._positionToReveal;
    },

    /**
     * @param {number} line
     */
    scrollToLine: function(line)
    {
        this._clearPositionToReveal();
        this._lineToScrollTo = line;
        this._innerScrollToLineIfNeeded();
    },

    _innerScrollToLineIfNeeded: function()
    {
        if (typeof this._lineToScrollTo === "number") {
            if (this.loaded && this._isEditorShowing()) {
                this._textEditor.scrollToLine(this._lineToScrollTo);
                delete this._lineToScrollTo;
            }
        }
    },

    _clearLineToScrollTo: function()
    {
        delete this._lineToScrollTo;
    },

    /**
     * @return {!WebInspector.TextRange}
     */
    selection: function()
    {
        return this.textEditor.selection();
    },

    /**
     * @param {!WebInspector.TextRange} textRange
     */
    setSelection: function(textRange)
    {
        this._selectionToSet = textRange;
        this._innerSetSelectionIfNeeded();
    },

    _innerSetSelectionIfNeeded: function()
    {
        if (this._selectionToSet && this.loaded && this._isEditorShowing()) {
            this._textEditor.setSelection(this._selectionToSet);
            delete this._selectionToSet;
        }
    },

    _clearSelectionToSet: function()
    {
        delete this._selectionToSet;
    },

    _wasShownOrLoaded: function()
    {
        this._innerRevealPositionIfNeeded();
        this._innerSetSelectionIfNeeded();
        this._innerScrollToLineIfNeeded();
    },

    onTextChanged: function(oldRange, newRange)
    {
        if (this._searchResultsChangedCallback && !this._isReplacing)
            this._searchResultsChangedCallback();
        this.clearMessages();
    },

    _simplifyMimeType: function(content, mimeType)
    {
        if (!mimeType)
            return "";
        if (mimeType.indexOf("javascript") >= 0 ||
            mimeType.indexOf("jscript") >= 0 ||
            mimeType.indexOf("ecmascript") >= 0)
            return "text/javascript";
        // A hack around the fact that files with "php" extension might be either standalone or html embedded php scripts.
        if (mimeType === "text/x-php" && content.match(/\<\?.*\?\>/g))
            return "application/x-httpd-php";
        return mimeType;
    },

    /**
     * @param {string} highlighterType
     */
    setHighlighterType: function(highlighterType)
    {
        this._highlighterType = highlighterType;
        this._updateHighlighterType("");
    },

    /**
     * @param {string} content
     */
    _updateHighlighterType: function(content)
    {
        this._textEditor.setMimeType(this._simplifyMimeType(content, this._highlighterType));
    },

    /**
     * @param {?string} content
     */
    setContent: function(content)
    {
        if (!this._loaded) {
            this._loaded = true;
            this._textEditor.setText(content || "");
            this._textEditor.markClean();
        } else {
            var firstLine = this._textEditor.firstVisibleLine();
            var selection = this._textEditor.selection();
            this._textEditor.setText(content || "");
            this._textEditor.scrollToLine(firstLine);
            this._textEditor.setSelection(selection);
        }

        this._updateHighlighterType(content || "");

        this._textEditor.beginUpdates();

        this._setTextEditorDecorations();

        this._wasShownOrLoaded();

        if (this._delayedFindSearchMatches) {
            this._delayedFindSearchMatches();
            delete this._delayedFindSearchMatches;
        }

        this.onTextEditorContentLoaded();

        this._textEditor.endUpdates();
    },

    onTextEditorContentLoaded: function() {},

    _setTextEditorDecorations: function()
    {
        this._rowMessageBuckets = {};

        this._textEditor.beginUpdates();
        this._addExistingMessagesToSource();
        this._textEditor.endUpdates();
    },

    /**
     * @param {string} query
     * @param {boolean} shouldJump
     * @param {boolean} jumpBackwards
     * @param {function(!WebInspector.View, number)} callback
     * @param {function(number)} currentMatchChangedCallback
     * @param {function()} searchResultsChangedCallback
     */
    performSearch: function(query, shouldJump, jumpBackwards, callback, currentMatchChangedCallback, searchResultsChangedCallback)
    {
        /**
         * @param {string} query
         * @this {WebInspector.SourceFrame}
         */
        function doFindSearchMatches(query)
        {
            this._currentSearchResultIndex = -1;
            this._searchResults = [];

            var regex = WebInspector.SourceFrame.createSearchRegex(query);
            this._searchRegex = regex;
            this._searchResults = this._collectRegexMatches(regex);
            if (!this._searchResults.length)
                this._textEditor.cancelSearchResultsHighlight();
            else if (shouldJump && jumpBackwards)
                this.jumpToPreviousSearchResult();
            else if (shouldJump)
                this.jumpToNextSearchResult();
            else
                this._textEditor.highlightSearchResults(regex, null);
            callback(this, this._searchResults.length);
        }

        this._resetSearch();
        this._currentSearchMatchChangedCallback = currentMatchChangedCallback;
        this._searchResultsChangedCallback = searchResultsChangedCallback;
        if (this.loaded)
            doFindSearchMatches.call(this, query);
        else
            this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query);

        this._ensureContentLoaded();
    },

    _editorFocused: function()
    {
        this._resetCurrentSearchResultIndex();
    },

    _resetCurrentSearchResultIndex: function()
    {
        if (!this._searchResults.length)
            return;
        this._currentSearchResultIndex = -1;
        if (this._currentSearchMatchChangedCallback)
            this._currentSearchMatchChangedCallback(this._currentSearchResultIndex);
        this._textEditor.highlightSearchResults(this._searchRegex, null);
    },

    _resetSearch: function()
    {
        delete this._delayedFindSearchMatches;
        delete this._currentSearchMatchChangedCallback;
        delete this._searchResultsChangedCallback;
        this._currentSearchResultIndex = -1;
        this._searchResults = [];
        delete this._searchRegex;
    },

    searchCanceled: function()
    {
        var range = this._currentSearchResultIndex !== -1 ? this._searchResults[this._currentSearchResultIndex] : null;
        this._resetSearch();
        if (!this.loaded)
            return;
        this._textEditor.cancelSearchResultsHighlight();
        if (range)
            this._textEditor.setSelection(range);
    },

    /**
     * @return {boolean}
     */
    hasSearchResults: function()
    {
        return this._searchResults.length > 0;
    },

    jumpToFirstSearchResult: function()
    {
        this.jumpToSearchResult(0);
    },

    jumpToLastSearchResult: function()
    {
        this.jumpToSearchResult(this._searchResults.length - 1);
    },

    /**
     * @return {number}
     */
    _searchResultIndexForCurrentSelection: function()
    {
        return insertionIndexForObjectInListSortedByFunction(this._textEditor.selection(), this._searchResults, WebInspector.TextRange.comparator);
    },

    jumpToNextSearchResult: function()
    {
        var currentIndex = this._searchResultIndexForCurrentSelection();
        var nextIndex = this._currentSearchResultIndex === -1 ? currentIndex : currentIndex + 1;
        this.jumpToSearchResult(nextIndex);
    },

    jumpToPreviousSearchResult: function()
    {
        var currentIndex = this._searchResultIndexForCurrentSelection();
        this.jumpToSearchResult(currentIndex - 1);
    },

    /**
     * @return {boolean}
     */
    showingFirstSearchResult: function()
    {
        return this._searchResults.length &&  this._currentSearchResultIndex === 0;
    },

    /**
     * @return {boolean}
     */
    showingLastSearchResult: function()
    {
        return this._searchResults.length && this._currentSearchResultIndex === (this._searchResults.length - 1);
    },

    get currentSearchResultIndex()
    {
        return this._currentSearchResultIndex;
    },

    jumpToSearchResult: function(index)
    {
        if (!this.loaded || !this._searchResults.length)
            return;
        this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
        if (this._currentSearchMatchChangedCallback)
            this._currentSearchMatchChangedCallback(this._currentSearchResultIndex);
        this._textEditor.highlightSearchResults(this._searchRegex, this._searchResults[this._currentSearchResultIndex]);
    },

    /**
     * @param {string} text
     */
    replaceSelectionWith: function(text)
    {
        var range = this._searchResults[this._currentSearchResultIndex];
        if (!range)
            return;
        this._textEditor.highlightSearchResults(this._searchRegex, null);

        this._isReplacing = true;
        var newRange = this._textEditor.editRange(range, text);
        delete this._isReplacing;

        this._textEditor.setSelection(newRange.collapseToEnd());
    },

    /**
     * @param {string} query
     * @param {string} replacement
     */
    replaceAllWith: function(query, replacement)
    {
        this._resetCurrentSearchResultIndex();

        var text = this._textEditor.text();
        var range = this._textEditor.range();
        var regex = WebInspector.SourceFrame.createSearchRegex(query, "g");
        if (regex.__fromRegExpQuery)
            text = text.replace(regex, replacement);
        else
            text = text.replace(regex, function() { return replacement; });

        var ranges = this._collectRegexMatches(regex);
        if (!ranges.length)
            return;

        // Calculate the position of the end of the last range to be edited.
        var currentRangeIndex = insertionIndexForObjectInListSortedByFunction(this._textEditor.selection(), ranges, WebInspector.TextRange.comparator);
        var lastRangeIndex = mod(currentRangeIndex - 1, ranges.length);
        var lastRange = ranges[lastRangeIndex];
        var replacementLineEndings = replacement.lineEndings();
        var replacementLineCount = replacementLineEndings.length;
        var lastLineNumber = lastRange.startLine + replacementLineEndings.length - 1;
        var lastColumnNumber = lastRange.startColumn;
        if (replacementLineEndings.length > 1)
            lastColumnNumber = replacementLineEndings[replacementLineCount - 1] - replacementLineEndings[replacementLineCount - 2] - 1;

        this._isReplacing = true;
        this._textEditor.editRange(range, text);
        this._textEditor.revealPosition(lastLineNumber, lastColumnNumber);
        this._textEditor.setSelection(WebInspector.TextRange.createFromLocation(lastLineNumber, lastColumnNumber));
        delete this._isReplacing;
    },

    _collectRegexMatches: function(regexObject)
    {
        var ranges = [];
        for (var i = 0; i < this._textEditor.linesCount; ++i) {
            var line = this._textEditor.line(i);
            var offset = 0;
            do {
                var match = regexObject.exec(line);
                if (match) {
                    if (match[0].length)
                        ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length));
                    offset += match.index + 1;
                    line = line.substring(match.index + 1);
                }
            } while (match && line);
        }
        return ranges;
    },

    _addExistingMessagesToSource: function()
    {
        var length = this._messages.length;
        for (var i = 0; i < length; ++i)
            this.addMessageToSource(this._messages[i].line - 1, this._messages[i]);
    },

    /**
     * @param {number} lineNumber
     * @param {!WebInspector.ConsoleMessage} consoleMessage
     */
    addMessageToSource: function(lineNumber, consoleMessage)
    {
        if (lineNumber >= this._textEditor.linesCount)
            lineNumber = this._textEditor.linesCount - 1;
        if (lineNumber < 0)
            lineNumber = 0;

        if (!this._rowMessageBuckets[lineNumber])
            this._rowMessageBuckets[lineNumber] = new WebInspector.SourceFrame.RowMessageBucket(this, this._textEditor, lineNumber);
        var messageBucket = this._rowMessageBuckets[lineNumber];
        messageBucket.addMessage(consoleMessage);
    },

    /**
     * @param {number} lineNumber
     * @param {!WebInspector.ConsoleMessage} msg
     */
    removeMessageFromSource: function(lineNumber, msg)
    {
        if (lineNumber >= this._textEditor.linesCount)
            lineNumber = this._textEditor.linesCount - 1;
        if (lineNumber < 0)
            lineNumber = 0;

        var messageBucket = this._rowMessageBuckets[lineNumber];
        if (!messageBucket)
            return;
        messageBucket.removeMessage(msg);
        if (!messageBucket.uniqueMessagesCount()) {
            messageBucket.detachFromEditor();
            delete this._rowMessageBuckets[lineNumber];
        }
    },

    populateLineGutterContextMenu: function(contextMenu, lineNumber)
    {
    },

    populateTextAreaContextMenu: function(contextMenu, lineNumber)
    {
    },

    /**
     * @param {?WebInspector.TextRange} from
     * @param {?WebInspector.TextRange} to
     */
    onJumpToPosition: function(from, to)
    {
        this.dispatchEventToListeners(WebInspector.SourceFrame.Events.JumpHappened, {
            from: from,
            to: to
        });
    },

    inheritScrollPositions: function(sourceFrame)
    {
        this._textEditor.inheritScrollPositions(sourceFrame._textEditor);
    },

    /**
     * @return {boolean}
     */
    canEditSource: function()
    {
        return false;
    },

    /**
     * @param {!WebInspector.TextRange} textRange
     */
    selectionChanged: function(textRange)
    {
        this._updateSourcePosition();
        this.dispatchEventToListeners(WebInspector.SourceFrame.Events.SelectionChanged, textRange);
        WebInspector.notifications.dispatchEventToListeners(WebInspector.SourceFrame.Events.SelectionChanged, textRange);
    },

    _updateSourcePosition: function()
    {
        var selections = this._textEditor.selections();
        if (!selections.length)
            return;
        if (selections.length > 1) {
            this._sourcePosition.setText(WebInspector.UIString("%d selection regions", selections.length));
            return;
        }
        var textRange = selections[0];
        if (textRange.isEmpty()) {
            this._sourcePosition.setText(WebInspector.UIString("Line %d, Column %d", textRange.endLine + 1, textRange.endColumn + 1));
            return;
        }
        textRange = textRange.normalize();

        var selectedText = this._textEditor.copyRange(textRange);
        if (textRange.startLine === textRange.endLine)
            this._sourcePosition.setText(WebInspector.UIString("%d characters selected", selectedText.length));
        else
            this._sourcePosition.setText(WebInspector.UIString("%d lines, %d characters selected", textRange.endLine - textRange.startLine + 1, selectedText.length));
    },

    /**
     * @param {number} lineNumber
     */
    scrollChanged: function(lineNumber)
    {
        this.dispatchEventToListeners(WebInspector.SourceFrame.Events.ScrollChanged, lineNumber);
    },

    _handleKeyDown: function(e)
    {
        var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e);
        var handler = this._shortcuts[shortcutKey];
        if (handler && handler())
            e.consume(true);
    },

    __proto__: WebInspector.VBox.prototype
}

WebInspector.SourceFrame._iconClassPerLevel = {};
WebInspector.SourceFrame._iconClassPerLevel[WebInspector.ConsoleMessage.MessageLevel.Error] = "error-icon-small";
WebInspector.SourceFrame._iconClassPerLevel[WebInspector.ConsoleMessage.MessageLevel.Warning] = "warning-icon-small";

WebInspector.SourceFrame._lineClassPerLevel = {};
WebInspector.SourceFrame._lineClassPerLevel[WebInspector.ConsoleMessage.MessageLevel.Error] = "text-editor-line-with-error";
WebInspector.SourceFrame._lineClassPerLevel[WebInspector.ConsoleMessage.MessageLevel.Warning] = "text-editor-line-with-warning";

/**
 * @constructor
 * @param {!WebInspector.ConsoleMessage} consoleMessage
 */
WebInspector.SourceFrame.RowMessage = function(consoleMessage)
{
    this._consoleMessage = consoleMessage;
    this._repeatCount = 1;
    this.element = document.createElementWithClass("div", "text-editor-row-message");
    this._icon = this.element.createChild("span", "text-editor-row-message-icon");
    this._icon.classList.add(WebInspector.SourceFrame._iconClassPerLevel[consoleMessage.level]);
    this._repeatCountElement = this.element.createChild("span", "bubble-repeat-count hidden error");
    var linesContainer = this.element.createChild("div", "text-editor-row-message-lines");
    var lines = this._consoleMessage.messageText.split("\n");
    for (var i = 0; i < lines.length; ++i) {
        var messageLine = linesContainer.createChild("div");
        messageLine.textContent = lines[i];
    }
}

WebInspector.SourceFrame.RowMessage.prototype = {
    /**
     * @return {!WebInspector.ConsoleMessage}
     */
    consoleMessage: function()
    {
        return this._consoleMessage;
    },

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

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

    _updateMessageRepeatCount: function()
    {
        this._repeatCountElement.textContent = this._repeatCount;
        var showRepeatCount = this._repeatCount > 1;
        this._repeatCountElement.classList.toggle("hidden", !showRepeatCount);
        this._icon.classList.toggle("hidden", showRepeatCount);
    }
}

/**
 * @constructor
 * @param {!WebInspector.SourceFrame} sourceFrame
 * @param {!WebInspector.TextEditor} textEditor
 * @param {number} lineNumber
 */
WebInspector.SourceFrame.RowMessageBucket = function(sourceFrame, textEditor, lineNumber)
{
    this._sourceFrame = sourceFrame;
    this._textEditor = textEditor;
    this._lineHandle = textEditor.textEditorPositionHandle(lineNumber, 0);
    this._decoration = document.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("div", "text-editor-line-decoration-icon");

    this._textEditor.addDecoration(lineNumber, this._decoration);

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

    this._updateDecorationPosition();

    this._level = null;
}

WebInspector.SourceFrame.RowMessageBucket.prototype = {
    _updateDecorationPosition: function()
    {
        if (!this._sourceFrame._isEditorShowing())
            return;
        var position = this._lineHandle.resolve();
        if (!position)
            return;
        var lineNumber = position.lineNumber;
        var lineText = this._textEditor.line(lineNumber);
        var lineIndent = WebInspector.TextUtils.lineIndent(lineText).length;
        var base = this._textEditor.cursorPositionToCoordinates(lineNumber, 0);
        var start = this._textEditor.cursorPositionToCoordinates(lineNumber, lineIndent);
        var end = this._textEditor.cursorPositionToCoordinates(lineNumber, lineText.length);
        this._wave.style.left = (start.x - base.x) + "px";
        this._wave.style.width = (end.x - start.x) + "px";
    },

    /**
     * @return {!Element}
     */
    messagesDescription: function()
    {
        this._messagesDescriptionElement.removeChildren();
        for (var i = 0; i < this._messages.length; ++i) {
            this._messagesDescriptionElement.appendChild(this._messages[i].element);
        }
        return this._messagesDescriptionElement;
    },

    detachFromEditor: function()
    {
        var position = this._lineHandle.resolve();
        if (!position)
            return;
        var lineNumber = position.lineNumber;
        if (this._level)
            this._textEditor.toggleLineClass(lineNumber, WebInspector.SourceFrame._lineClassPerLevel[this._level], false);
        this._textEditor.removeDecoration(lineNumber, this._decoration);
    },

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

    /**
     * @param {!WebInspector.ConsoleMessage} consoleMessage
     */
    addMessage: function(consoleMessage)
    {
        for (var i = 0; i < this._messages.length; ++i) {
            var message = this._messages[i];
            if (message.consoleMessage().isEqual(consoleMessage)) {
                message.setRepeatCount(message.repeatCount() + 1);
                return;
            }
        }

        var rowMessage = new WebInspector.SourceFrame.RowMessage(consoleMessage);
        this._messages.push(rowMessage);
        this._updateBucketLevel();
    },

    /**
     * @param {!WebInspector.ConsoleMessage} consoleMessage
     */
    removeMessage: function(consoleMessage)
    {
        for (var i = 0; i < this._messages.length; ++i) {
            var rowMessage = this._messages[i];
            if (!rowMessage.consoleMessage().isEqual(consoleMessage))
                continue;
            rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
            if (!rowMessage.repeatCount())
                this._messages.splice(i, 1);
            this._updateBucketLevel();
            return;
        }
    },

    _updateBucketLevel: function()
    {
        if (!this._messages.length)
            return;
        var position = this._lineHandle.resolve();
        if (!position)
            return;

        var lineNumber = position.lineNumber;
        var maxMessage = null;
        for (var i = 0; i < this._messages.length; ++i) {
            var message = this._messages[i].consoleMessage();;
            if (!maxMessage || WebInspector.ConsoleMessage.messageLevelComparator(maxMessage, message) < 0)
                maxMessage = message;
        }

        if (this._level) {
            this._textEditor.toggleLineClass(lineNumber, WebInspector.SourceFrame._lineClassPerLevel[this._level], false);
            this._icon.classList.toggle(WebInspector.SourceFrame._iconClassPerLevel[this._level], false);
        }
        this._level = maxMessage.level;
        if (!this._level)
            return;
        this._textEditor.toggleLineClass(lineNumber, WebInspector.SourceFrame._lineClassPerLevel[this._level], true);
        this._icon.classList.toggle(WebInspector.SourceFrame._iconClassPerLevel[this._level], true);
    }
}

/**
 * @implements {WebInspector.TextEditorDelegate}
 * @constructor
 */
WebInspector.TextEditorDelegateForSourceFrame = function(sourceFrame)
{
    this._sourceFrame = sourceFrame;
}

WebInspector.TextEditorDelegateForSourceFrame.prototype = {
    onTextChanged: function(oldRange, newRange)
    {
        this._sourceFrame.onTextChanged(oldRange, newRange);
    },

    /**
     * @param {!WebInspector.TextRange} textRange
     */
    selectionChanged: function(textRange)
    {
        this._sourceFrame.selectionChanged(textRange);
    },

    /**
     * @param {number} lineNumber
     */
    scrollChanged: function(lineNumber)
    {
        this._sourceFrame.scrollChanged(lineNumber);
    },

    editorFocused: function()
    {
        this._sourceFrame._editorFocused();
    },

    populateLineGutterContextMenu: function(contextMenu, lineNumber)
    {
        this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber);
    },

    populateTextAreaContextMenu: function(contextMenu, lineNumber)
    {
        this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber);
    },

    /**
     * @param {string} hrefValue
     * @param {boolean} isExternal
     * @return {!Element}
     */
    createLink: function(hrefValue, isExternal)
    {
        var targetLocation = WebInspector.ParsedURL.completeURL(this._sourceFrame._url, hrefValue);
        return WebInspector.linkifyURLAsNode(targetLocation || hrefValue, hrefValue, undefined, isExternal);
    },

    /**
     * @param {?WebInspector.TextRange} from
     * @param {?WebInspector.TextRange} to
     */
    onJumpToPosition: function(from, to)
    {
        this._sourceFrame.onJumpToPosition(from, to);
    }
}
