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

WebInspector.CSSStyleDeclarationTextEditor = class CSSStyleDeclarationTextEditor extends WebInspector.View
{
    constructor(delegate, style)
    {
        super();

        this.element.classList.add(WebInspector.CSSStyleDeclarationTextEditor.StyleClassName);
        this.element.classList.add(WebInspector.SyntaxHighlightedStyleClassName);
        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this), true);
        this.element.addEventListener("mouseup", this._handleMouseUp.bind(this));

        this._mouseDownCursorPosition = null;

        this._propertyVisibilityMode = WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.ShowAll;
        this._showsImplicitProperties = true;
        this._alwaysShowPropertyNames = {};
        this._filterResultPropertyNames = null;
        this._sortProperties = false;
        this._hasActiveInlineSwatchEditor = false;

        this._linePrefixWhitespace = "";

        this._delegate = delegate || null;

        this._codeMirror = WebInspector.CodeMirrorEditor.create(this.element, {
            readOnly: true,
            lineWrapping: true,
            mode: "css-rule",
            electricChars: false,
            indentWithTabs: false,
            indentUnit: 4,
            smartIndent: false,
            matchBrackets: true,
            autoCloseBrackets: true
        });

        this._codeMirror.addKeyMap({
            "Enter": this._handleEnterKey.bind(this),
            "Shift-Enter": this._insertNewlineAfterCurrentLine.bind(this),
            "Shift-Tab": this._handleShiftTabKey.bind(this),
            "Tab": this._handleTabKey.bind(this)
        });

        this._completionController = new WebInspector.CodeMirrorCompletionController(this._codeMirror, this);
        this._tokenTrackingController = new WebInspector.CodeMirrorTokenTrackingController(this._codeMirror, this);

        this._completionController.noEndingSemicolon = true;

        this._jumpToSymbolTrackingModeEnabled = false;
        this._tokenTrackingController.classNameForHighlightedRange = WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
        this._tokenTrackingController.mouseOverDelayDuration = 0;
        this._tokenTrackingController.mouseOutReleaseDelayDuration = 0;
        this._tokenTrackingController.mode = WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;

        // Make sure CompletionController adds event listeners first.
        // Otherwise we end up in race conditions during complete or delete-complete phases.
        this._codeMirror.on("change", this._contentChanged.bind(this));
        this._codeMirror.on("blur", this._editorBlured.bind(this));
        this._codeMirror.on("beforeChange", this._handleBeforeChange.bind(this));

        if (typeof this._delegate.cssStyleDeclarationTextEditorFocused === "function")
            this._codeMirror.on("focus", this._editorFocused.bind(this));

        this.style = style;
        this._shownProperties = [];

        WebInspector.settings.stylesShowInlineWarnings.addEventListener(WebInspector.Setting.Event.Changed, this.refresh, this);
    }

    // Public

    get delegate() { return this._delegate; }
    set delegate(delegate)
    {
        this._delegate = delegate || null;
    }

    get style() { return this._style; }
    set style(style)
    {
        if (this._style === style)
            return;

        if (this._style) {
            this._style.removeEventListener(WebInspector.CSSStyleDeclaration.Event.PropertiesChanged, this._propertiesChanged, this);
            WebInspector.notifications.removeEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateJumpToSymbolTrackingMode, this);
        }

        this._style = style || null;

        if (this._style) {
            this._style.addEventListener(WebInspector.CSSStyleDeclaration.Event.PropertiesChanged, this._propertiesChanged, this);
            WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateJumpToSymbolTrackingMode, this);
        }

        this._updateJumpToSymbolTrackingMode();

        this._resetContent();
    }

    get shownProperties() { return this._shownProperties; }

    get focused()
    {
        return this._codeMirror.getWrapperElement().classList.contains("CodeMirror-focused");
    }

    get alwaysShowPropertyNames() {
        return Object.keys(this._alwaysShowPropertyNames);
    }

    set alwaysShowPropertyNames(alwaysShowPropertyNames)
    {
        this._alwaysShowPropertyNames = (alwaysShowPropertyNames || []).keySet();

        this._resetContent();
    }

    get propertyVisibilityMode() { return this._propertyVisibilityMode; }
    set propertyVisibilityMode(propertyVisibilityMode)
    {
        if (this._propertyVisibilityMode === propertyVisibilityMode)
            return;

        this._propertyVisibilityMode = propertyVisibilityMode;

        this._resetContent();
    }

    get showsImplicitProperties() { return this._showsImplicitProperties; }
    set showsImplicitProperties(showsImplicitProperties)
    {
        if (this._showsImplicitProperties === showsImplicitProperties)
            return;

        this._showsImplicitProperties = showsImplicitProperties;

        this._resetContent();
    }

    get sortProperties() { return this._sortProperties; }
    set sortProperties(sortProperties)
    {
        if (this._sortProperties === sortProperties)
            return;

        this._sortProperties = sortProperties;

        this._resetContent();
    }

    focus()
    {
        this._codeMirror.focus();
    }

    refresh()
    {
        this._resetContent();
    }

    highlightProperty(property)
    {
        function propertiesMatch(cssProperty)
        {
            if (cssProperty.enabled && !cssProperty.overridden) {
                if (cssProperty.canonicalName === property.canonicalName || hasMatchingLonghandProperty(cssProperty))
                    return true;
            }

            return false;
        }

        function hasMatchingLonghandProperty(cssProperty)
        {
            var cssProperties = cssProperty.relatedLonghandProperties;

            if (!cssProperties.length)
                return false;

            for (var property of cssProperties) {
                if (propertiesMatch(property))
                    return true;
            }

            return false;
        }

        for (var cssProperty of this.style.properties) {
            if (propertiesMatch(cssProperty)) {
                var selection = cssProperty.__propertyTextMarker.find();
                this._codeMirror.setSelection(selection.from, selection.to);
                this.focus();

                return true;
            }
        }

        return false;
    }

    clearSelection()
    {
        this._codeMirror.setCursor({line: 0, ch: 0});
    }

    findMatchingProperties(needle)
    {
        if (!needle) {
            this.resetFilteredProperties();
            return false;
        }

        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;
        var matchingProperties = [];

        for (var property of propertiesList)
            matchingProperties.push(property.text.includes(needle));

        if (!matchingProperties.includes(true)) {
            this.resetFilteredProperties();
            return false;
        }

        for (var i = 0; i < matchingProperties.length; ++i) {
            var property = propertiesList[i];

            if (matchingProperties[i])
                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
            else
                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName;

            this._updateTextMarkerForPropertyIfNeeded(property);
        }

        return true;
    }

    resetFilteredProperties()
    {
        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;

        for (var property of propertiesList) {
            if (property.__filterResultClassName) {
                property.__filterResultClassName = null;
                this._updateTextMarkerForPropertyIfNeeded(property);
            }
        }
    }

    removeNonMatchingProperties(needle)
    {
        this._filterResultPropertyNames = null;

        if (!needle) {
            this._resetContent();
            return false;
        }

        var matchingPropertyNames = [];

        for (var property of this._style.properties) {
            var indexesOfNeedle = property.text.getMatchingIndexes(needle);

            if (indexesOfNeedle.length) {
                matchingPropertyNames.push(property.name);
                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
                property.__filterResultNeedlePosition = {start: indexesOfNeedle, length: needle.length};
            }
        }

        this._filterResultPropertyNames = matchingPropertyNames.length ? matchingPropertyNames.keySet() : {};

        this._resetContent();

        return matchingPropertyNames.length > 0;
    }

    uncommentAllProperties()
    {
        function uncommentProperties(properties)
        {
            if (!properties.length)
                return false;

            for (var property of properties) {
                if (property._commentRange) {
                    this._uncommentRange(property._commentRange);
                    property._commentRange = null;
                }
            }

            return true;
        }

        return uncommentProperties.call(this, this._style.pendingProperties) || uncommentProperties.call(this, this._style.properties);
    }

    commentAllProperties()
    {
        if (!this._style.hasProperties())
            return false;

        for (var property of this._style.properties) {
            if (property.__propertyTextMarker)
                this._commentProperty(property);
        }

        return true;
    }

    selectFirstProperty()
    {
        var line = this._codeMirror.getLine(0);
        var trimmedLine = line.trimRight();

        if (!line || !trimmedLine.trimLeft().length)
            this.clearSelection();

        var index = line.indexOf(":");
        var cursor = {line: 0, ch: 0};

        this._codeMirror.setSelection(cursor, {line: 0, ch: index < 0 || this._textAtCursorIsComment(this._codeMirror, cursor) ? trimmedLine.length : index});
    }

    selectLastProperty()
    {
        var line = this._codeMirror.lineCount() - 1;
        var lineText = this._codeMirror.getLine(line);
        var trimmedLine = lineText.trimRight();

        var lastAnchor;
        var lastHead;

        if (this._textAtCursorIsComment(this._codeMirror, {line, ch: line.length})) {
            lastAnchor = 0;
            lastHead = line.length;
        } else {
            var colon = /(?::\s*)/.exec(lineText);
            lastAnchor = colon ? colon.index + colon[0].length : 0;
            lastHead = trimmedLine.length - trimmedLine.endsWith(";");
        }

        this._codeMirror.setSelection({line, ch: lastAnchor}, {line, ch: lastHead});
    }

    // Protected

    completionControllerCompletionsHidden(completionController)
    {
        var styleText = this._style.text;
        var currentText = this._formattedContent();

        // If the style text and the current editor text differ then we need to commit.
        // Otherwise we can just update the properties that got skipped because a completion
        // was pending the last time _propertiesChanged was called.
        if (styleText !== currentText)
            this._commitChanges();
        else
            this._propertiesChanged();
    }

    completionControllerCompletionsNeeded(completionController, prefix, defaultCompletions, base, suffix, forced)
    {
        let properties = this._style.nodeStyles.computedStyle.properties;
        let variables = properties.filter((property) => property.variable && property.name.startsWith(prefix));
        let variableNames = variables.map((property) => property.name);
        completionController.updateCompletions(defaultCompletions.concat(variableNames));
    }

    layout()
    {
        this._codeMirror.refresh();
    }

    // Private

    _textAtCursorIsComment(codeMirror, cursor)
    {
        var token = codeMirror.getTokenTypeAt(cursor);
        return token && token.includes("comment");
    }

    _highlightNextNameOrValue(codeMirror, cursor, text)
    {
        let range = this._rangeForNextNameOrValue(codeMirror, cursor, text);
        codeMirror.setSelection(range.from, range.to);
    }

    _rangeForNextNameOrValue(codeMirror, cursor, text)
    {
        let nextAnchor = 0;
        let nextHead = 0;

        if (this._textAtCursorIsComment(codeMirror, cursor))
            nextHead = text.length;
        else {
            let range = WebInspector.rangeForNextCSSNameOrValue(text, cursor.ch);
            nextAnchor = range.from;
            nextHead = range.to;
        }

        return {
            from: {line: cursor.line, ch: nextAnchor},
            to: {line: cursor.line, ch: nextHead},
        };
    }

    _handleMouseDown(event)
    {
        if (this._codeMirror.options.readOnly)
            return;

        let cursor = this._codeMirror.coordsChar({left: event.x, top: event.y});
        let line = this._codeMirror.getLine(cursor.line);
        if (!line.trim().length)
            return;

        this._mouseDownCursorPosition = cursor;
        this._mouseDownCursorPosition.previousRange = {from: this._codeMirror.getCursor("from"), to: this._codeMirror.getCursor("to")};
    }

    _handleMouseUp(event)
    {
        if (this._codeMirror.options.readOnly || !this._mouseDownCursorPosition)
            return;

        let cursor = this._codeMirror.coordsChar({left: event.x, top: event.y});

        let clickedBookmark = false;
        for (let marker of this._codeMirror.findMarksAt(cursor)) {
            if (marker.type !== "bookmark" || marker.replacedWith !== event.target)
                continue;

            let pos = marker.find();
            if (pos.line === cursor.line && Math.abs(pos.ch - cursor.ch) <= 1) {
                clickedBookmark = true;
                break;
            }
        }

        if (!clickedBookmark && this._mouseDownCursorPosition.line === cursor.line && this._mouseDownCursorPosition.ch === cursor.ch) {
            let line = this._codeMirror.getLine(cursor.line);
            if (cursor.ch === line.trimRight().length) {
                let nextLine = this._codeMirror.getLine(cursor.line + 1);
                if (WebInspector.settings.stylesInsertNewline.value && cursor.line < this._codeMirror.lineCount() - 1 && (!nextLine || !nextLine.trim().length)) {
                    this._codeMirror.setCursor({line: cursor.line + 1, ch: 0});
                } else {
                    let line = this._codeMirror.getLine(cursor.line);
                    let replacement = WebInspector.settings.stylesInsertNewline.value ? "\n" : "";
                    if (!line.trimRight().endsWith(";") && !this._textAtCursorIsComment(this._codeMirror, cursor))
                        replacement = ";" + replacement;

                    this._codeMirror.replaceRange(replacement, cursor);
                }
            } else if (WebInspector.settings.stylesSelectOnFirstClick.value && this._mouseDownCursorPosition.previousRange) {
                let range = this._rangeForNextNameOrValue(this._codeMirror, cursor, line);

                let clickedDifferentLine = this._mouseDownCursorPosition.previousRange.from.line !== cursor.line || this._mouseDownCursorPosition.previousRange.to.line !== cursor.line;
                let cursorInPreviousRange = cursor.ch >= this._mouseDownCursorPosition.previousRange.from.ch && cursor.ch <= this._mouseDownCursorPosition.previousRange.to.ch;
                let previousInNewRange = this._mouseDownCursorPosition.previousRange.from.ch >= range.from.ch && this._mouseDownCursorPosition.previousRange.to.ch <= range.to.ch;

                // Only select the new range if the editor is not focused, a new line is being clicked,
                // or the new cursor position is outside of the previous range and the previous range is
                // outside of the new range (meaning you're not clicking in the same area twice).
                if (!this._codeMirror.hasFocus() || clickedDifferentLine || (!cursorInPreviousRange && !previousInNewRange))
                    this._codeMirror.setSelection(range.from, range.to);
            }
        }

        this._mouseDownCursorPosition = null;
    }

    _handleBeforeChange(codeMirror, change)
    {
        if (change.origin !== "+delete" || this._completionController.isShowingCompletions())
            return CodeMirror.Pass;

        if (!change.to.line && !change.to.ch) {
            if (codeMirror.lineCount() === 1)
                return CodeMirror.Pass;

            var line = codeMirror.getLine(change.to.line);
            if (line && line.trim().length)
                return CodeMirror.Pass;

            codeMirror.execCommand("deleteLine");
            return;
        }

        var marks = codeMirror.findMarksAt(change.to);
        if (!marks.length)
            return CodeMirror.Pass;

        for (var mark of marks)
            mark.clear();
    }

    _handleEnterKey(codeMirror)
    {
        var cursor = codeMirror.getCursor();
        var line = codeMirror.getLine(cursor.line);
        var trimmedLine = line.trimRight();
        var hasEndingSemicolon = trimmedLine.endsWith(";");

        if (!trimmedLine.trimLeft().length)
            return CodeMirror.Pass;

        if (hasEndingSemicolon && cursor.ch === trimmedLine.length - 1)
            ++cursor.ch;

        if (cursor.ch === trimmedLine.length) {
            var replacement = "\n";

            if (!hasEndingSemicolon && !this._textAtCursorIsComment(this._codeMirror, cursor))
                replacement = ";" + replacement;

            this._codeMirror.replaceRange(replacement, cursor);
            return;
        }

        return CodeMirror.Pass;
    }

    _insertNewlineAfterCurrentLine(codeMirror)
    {
        var cursor = codeMirror.getCursor();
        var line = codeMirror.getLine(cursor.line);
        var trimmedLine = line.trimRight();

        cursor.ch = trimmedLine.length;

        if (cursor.ch) {
            var replacement = "\n";

            if (!trimmedLine.endsWith(";") && !this._textAtCursorIsComment(this._codeMirror, cursor))
                replacement = ";" + replacement;

            this._codeMirror.replaceRange(replacement, cursor);
            return;
        }

        return CodeMirror.Pass;
    }

    _handleShiftTabKey(codeMirror)
    {
        function switchRule()
        {
            if (this._delegate && typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === "function") {
                this._delegate.cssStyleDeclarationTextEditorSwitchRule(true);
                return;
            }

            return CodeMirror.Pass;
        }

        let cursor = codeMirror.getCursor();
        let line = codeMirror.getLine(cursor.line);
        let previousLine = codeMirror.getLine(cursor.line - 1);

        if (!line && !previousLine && !cursor.line)
            return switchRule.call(this);

        let trimmedPreviousLine = previousLine ? previousLine.trimRight() : "";
        let previousAnchor = 0;
        let previousHead = line.length;
        let isComment = this._textAtCursorIsComment(codeMirror, cursor);

        if (cursor.ch === line.indexOf(":") || line.indexOf(":") < 0 || isComment) {
            if (previousLine) {
                --cursor.line;
                previousHead = trimmedPreviousLine.length;

                if (!this._textAtCursorIsComment(codeMirror, cursor)) {
                    let colon = /(?::\s*)/.exec(previousLine);
                    previousAnchor = colon ? colon.index + colon[0].length : 0;
                    if (trimmedPreviousLine.includes(";"))
                        previousHead = trimmedPreviousLine.lastIndexOf(";");
                }

                codeMirror.setSelection({line: cursor.line, ch: previousAnchor}, {line: cursor.line, ch: previousHead});
                return;
            }

            if (cursor.line) {
                codeMirror.setCursor(cursor.line - 1, 0);
                return;
            }

            return switchRule.call(this);
        }

        if (!isComment) {
            let match = /(?:[^:;\s]\s*)+/.exec(line);
            previousAnchor = match.index;
            previousHead = previousAnchor + match[0].length;
        }

        codeMirror.setSelection({line: cursor.line, ch: previousAnchor}, {line: cursor.line, ch: previousHead});
    }

    _handleTabKey(codeMirror)
    {
        function switchRule() {
            if (this._delegate && typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === "function") {
                this._delegate.cssStyleDeclarationTextEditorSwitchRule();
                return;
            }

            return CodeMirror.Pass;
        }

        let cursor = codeMirror.getCursor();
        let line = codeMirror.getLine(cursor.line);
        let trimmedLine = line.trimRight();
        let lastLine = cursor.line === codeMirror.lineCount() - 1;
        let nextLine = codeMirror.getLine(cursor.line + 1);
        let trimmedNextLine = nextLine ? nextLine.trimRight() : "";

        if (!trimmedLine.trimLeft().length) {
            if (lastLine)
                return switchRule.call(this);

            if (!trimmedNextLine.trimLeft().length) {
                codeMirror.setCursor(cursor.line + 1, 0);
                return;
            }

            ++cursor.line;
            this._highlightNextNameOrValue(codeMirror, cursor, nextLine);
            return;
        }

        if (trimmedLine.endsWith(":")) {
            codeMirror.setCursor(cursor.line, line.length);
            this._completionController._completeAtCurrentPosition(true);
            return;
        }

        let hasEndingSemicolon = trimmedLine.endsWith(";");
        let pastLastSemicolon = line.includes(";") && cursor.ch >= line.lastIndexOf(";");

        if (cursor.ch >= line.trimRight().length - hasEndingSemicolon || pastLastSemicolon) {
            this._completionController.completeAtCurrentPositionIfNeeded().then(function(result) {
                if (result !== WebInspector.CodeMirrorCompletionController.UpdatePromise.NoCompletionsFound)
                    return;

                let replacement = "";

                if (!hasEndingSemicolon && !pastLastSemicolon && !this._textAtCursorIsComment(codeMirror, cursor))
                    replacement += ";";

                if (lastLine)
                    replacement += "\n";

                if (replacement.length)
                    codeMirror.replaceRange(replacement, {line: cursor.line, ch: trimmedLine.length});

                if (!nextLine) {
                    codeMirror.setCursor(cursor.line + 1, 0);
                    return;
                }

                this._highlightNextNameOrValue(codeMirror, {line: cursor.line + 1, ch: 0}, nextLine);
            }.bind(this));

            return;
        }

        this._highlightNextNameOrValue(codeMirror, cursor, line);
    }

    _clearRemoveEditingLineClassesTimeout()
    {
        if (!this._removeEditingLineClassesTimeout)
            return;

        clearTimeout(this._removeEditingLineClassesTimeout);
        delete this._removeEditingLineClassesTimeout;
    }

    _removeEditingLineClasses()
    {
        this._clearRemoveEditingLineClassesTimeout();

        function removeEditingLineClasses()
        {
            var lineCount = this._codeMirror.lineCount();
            for (var i = 0; i < lineCount; ++i)
                this._codeMirror.removeLineClass(i, "wrap", WebInspector.CSSStyleDeclarationTextEditor.EditingLineStyleClassName);
        }

        this._codeMirror.operation(removeEditingLineClasses.bind(this));
    }

    _removeEditingLineClassesSoon()
    {
        if (this._removeEditingLineClassesTimeout)
            return;
        this._removeEditingLineClassesTimeout = setTimeout(this._removeEditingLineClasses.bind(this), WebInspector.CSSStyleDeclarationTextEditor.RemoveEditingLineClassesDelay);
    }

    _formattedContent()
    {
        // Start with the prefix whitespace we stripped.
        var content = WebInspector.CSSStyleDeclarationTextEditor.PrefixWhitespace;

        // Get each line and add the line prefix whitespace and newlines.
        var lineCount = this._codeMirror.lineCount();
        for (var i = 0; i < lineCount; ++i) {
            var lineContent = this._codeMirror.getLine(i);
            content += this._linePrefixWhitespace + lineContent;
            if (i !== lineCount - 1)
                content += "\n";
        }

        // Add the suffix whitespace we stripped.
        content += WebInspector.CSSStyleDeclarationTextEditor.SuffixWhitespace;

        // This regular expression replacement removes extra newlines
        // in between properties while preserving leading whitespace
        return content.replace(/\s*\n\s*\n(\s*)/g, "\n$1");
    }

    _commitChanges()
    {
        if (this._commitChangesTimeout) {
            clearTimeout(this._commitChangesTimeout);
            delete this._commitChangesTimeout;
        }

        this._style.text = this._formattedContent();
    }

    _editorBlured(codeMirror)
    {
        // Clicking a suggestion causes the editor to blur. We don't want to reset content in this case.
        if (this._completionController.isHandlingClickEvent())
            return;

        // Reset the content on blur since we stop accepting external changes while the the editor is focused.
        // This causes us to pick up any change that was suppressed while the editor was focused.
        this._resetContent();
        this.dispatchEventToListeners(WebInspector.CSSStyleDeclarationTextEditor.Event.Blurred);
    }

    _editorFocused(codeMirror)
    {
        if (typeof this._delegate.cssStyleDeclarationTextEditorFocused === "function")
            this._delegate.cssStyleDeclarationTextEditorFocused();
    }

    _contentChanged(codeMirror, change)
    {
        // Return early if the style isn't editable. This still can be called when readOnly is set because
        // clicking on a color swatch modifies the text.
        if (!this._style || !this._style.editable || this._ignoreCodeMirrorContentDidChangeEvent)
            return;

        this._markLinesWithCheckboxPlaceholder();

        this._clearRemoveEditingLineClassesTimeout();
        this._codeMirror.addLineClass(change.from.line, "wrap", WebInspector.CSSStyleDeclarationTextEditor.EditingLineStyleClassName);

        // When the change is a completion change, create color swatches now since the changes
        // will not go through _propertiesChanged until completionControllerCompletionsHidden happens.
        // This way any auto completed colors get swatches right away.
        if (this._completionController.isCompletionChange(change))
            this._createInlineSwatches(false, change.from.line);

        // Use a short delay for user input to coalesce more changes before committing. Other actions like
        // undo, redo and paste are atomic and work better with a zero delay. CodeMirror identifies changes that
        // get coalesced in the undo stack with a "+" prefix on the origin. Use that to set the delay for our coalescing.
        var delay = change.origin && change.origin.charAt(0) === "+" ? WebInspector.CSSStyleDeclarationTextEditor.CommitCoalesceDelay : 0;

        // Reset the timeout so rapid changes coalesce after a short delay.
        if (this._commitChangesTimeout)
            clearTimeout(this._commitChangesTimeout);
        this._commitChangesTimeout = setTimeout(this._commitChanges.bind(this), delay);

        this.dispatchEventToListeners(WebInspector.CSSStyleDeclarationTextEditor.Event.ContentChanged);
    }

    _updateTextMarkers(nonatomic)
    {
        console.assert(!this._hasActiveInlineSwatchEditor, "We should never be recreating markers when we an active inline swatch editor.");

        function update()
        {
            this._clearTextMarkers(true);

            this._iterateOverProperties(true, function(property) {
                var styleTextRange = property.styleDeclarationTextRange;
                console.assert(styleTextRange);
                if (!styleTextRange)
                    return;

                var from = {line: styleTextRange.startLine, ch: styleTextRange.startColumn};
                var to = {line: styleTextRange.endLine, ch: styleTextRange.endColumn};

                // Adjust the line position for the missing prefix line.
                from.line--;
                to.line--;

                // Adjust the column for the stripped line prefix whitespace.
                from.ch -= this._linePrefixWhitespace.length;
                to.ch -= this._linePrefixWhitespace.length;

                this._createTextMarkerForPropertyIfNeeded(from, to, property);
            });

            if (!this._codeMirror.getOption("readOnly")) {
                // Look for comments that look like properties and add checkboxes in front of them.
                this._codeMirror.eachLine((lineHandler) => {
                    this._createCommentedCheckboxMarker(lineHandler);
                });
            }

            // Look for swatchable values and make inline swatches.
            this._createInlineSwatches(true);

            this._markLinesWithCheckboxPlaceholder();
        }

        if (nonatomic)
            update.call(this);
        else
            this._codeMirror.operation(update.bind(this));
    }

    _createCommentedCheckboxMarker(lineHandle)
    {
        var lineNumber = lineHandle.lineNo();

        // Since lineNumber can be 0, it is also necessary to check if it is a number before returning.
        if (!lineNumber && isNaN(lineNumber))
            return;

        // Matches a comment like: /* -webkit-foo: bar; */
        let commentedPropertyRegex = /\/\*\s*[-\w]+\s*\:\s*(?:(?:\".*\"|url\(.+\)|[^;])\s*)+;?\s*\*\//g;

        var match = commentedPropertyRegex.exec(lineHandle.text);
        if (!match)
            return;

        while (match) {
            var checkboxElement = document.createElement("input");
            checkboxElement.type = "checkbox";
            checkboxElement.checked = false;
            checkboxElement.addEventListener("change", this._propertyCommentCheckboxChanged.bind(this));

            var from = {line: lineNumber, ch: match.index};
            var to = {line: lineNumber, ch: match.index + match[0].length};

            var checkboxMarker = this._codeMirror.setUniqueBookmark(from, checkboxElement);
            checkboxMarker.__propertyCheckbox = true;

            var commentTextMarker = this._codeMirror.markText(from, to);

            checkboxElement.__commentTextMarker = commentTextMarker;

            match = commentedPropertyRegex.exec(lineHandle.text);
        }
    }

    _createInlineSwatches(nonatomic, lineNumber)
    {
        function createSwatch(swatch, marker, valueObject, valueString)
        {
            swatch.addEventListener(WebInspector.InlineSwatch.Event.ValueChanged, this._inlineSwatchValueChanged, this);
            swatch.addEventListener(WebInspector.InlineSwatch.Event.Activated, this._inlineSwatchActivated, this);
            swatch.addEventListener(WebInspector.InlineSwatch.Event.Deactivated, this._inlineSwatchDeactivated, this);

            let codeMirrorTextMarker = marker.codeMirrorTextMarker;
            let codeMirrorTextMarkerRange = codeMirrorTextMarker.find();
            this._codeMirror.setUniqueBookmark(codeMirrorTextMarkerRange.from, swatch.element);

            swatch.__textMarker = codeMirrorTextMarker;
            swatch.__textMarkerRange = codeMirrorTextMarkerRange;
        }

        function update()
        {
            let range = typeof lineNumber === "number" ? new WebInspector.TextRange(lineNumber, 0, lineNumber + 1, 0) : null;

            // Look for color strings and add swatches in front of them.
            createCodeMirrorColorTextMarkers(this._codeMirror, range, (marker, color, colorString) => {
                let swatch = new WebInspector.InlineSwatch(WebInspector.InlineSwatch.Type.Color, color, this._codeMirror.getOption("readOnly"));
                createSwatch.call(this, swatch, marker, color, colorString);
            });

            // Look for gradient strings and add swatches in front of them.
            createCodeMirrorGradientTextMarkers(this._codeMirror, range, (marker, gradient, gradientString) => {
                let swatch = new WebInspector.InlineSwatch(WebInspector.InlineSwatch.Type.Gradient, gradient, this._codeMirror.getOption("readOnly"));
                createSwatch.call(this, swatch, marker, gradient, gradientString);
            });

            // Look for cubic-bezier strings and add swatches in front of them.
            createCodeMirrorCubicBezierTextMarkers(this._codeMirror, range, (marker, bezier, bezierString) => {
                let swatch = new WebInspector.InlineSwatch(WebInspector.InlineSwatch.Type.Bezier, bezier, this._codeMirror.getOption("readOnly"));
                createSwatch.call(this, swatch, marker, bezier, bezierString);
            });

            // Look for spring strings and add swatches in front of them.
            createCodeMirrorSpringTextMarkers(this._codeMirror, range, (marker, spring, springString) => {
                let swatch = new WebInspector.InlineSwatch(WebInspector.InlineSwatch.Type.Spring, spring, this._codeMirror.getOption("readOnly"));
                createSwatch.call(this, swatch, marker, spring, springString);
            });

            // Look for CSS variables and add swatches in front of them.
            createCodeMirrorVariableTextMarkers(this._codeMirror, range, (marker, variable, variableString) => {
                const dontCreateIfMissing = true;
                let variableProperty = this._style.nodeStyles.computedStyle.propertyForName(variableString, dontCreateIfMissing);
                if (!variableProperty) {
                    let from = {line: marker.range.startLine, ch: marker.range.startColumn};
                    let to = {line: marker.range.endLine, ch: marker.range.endColumn};
                    this._codeMirror.markText(from, to, {className: "invalid"});

                    if (WebInspector.settings.stylesShowInlineWarnings.value) {
                        let invalidMarker = document.createElement("button");
                        invalidMarker.classList.add("invalid-warning-marker", "clickable");
                        invalidMarker.title = WebInspector.UIString("The variable “%s” does not exist.\nClick to delete and open autocomplete.").format(variableString);
                        invalidMarker.addEventListener("click", (event) => {
                            this._codeMirror.replaceRange("", from, to);
                            this._codeMirror.setCursor(from);
                            this._completionController.completeAtCurrentPositionIfNeeded(true);
                        });
                        this._codeMirror.setBookmark(from, invalidMarker);
                    }
                    return;
                }

                let trimmedValue = variableProperty.value.trim();
                let swatch = new WebInspector.InlineSwatch(WebInspector.InlineSwatch.Type.Variable, trimmedValue, this._codeMirror.getOption("readOnly"));
                createSwatch.call(this, swatch, marker, variableProperty, trimmedValue);
            });
        }

        if (nonatomic)
            update.call(this);
        else
            this._codeMirror.operation(update.bind(this));
    }

    _updateTextMarkerForPropertyIfNeeded(property)
    {
        var textMarker = property.__propertyTextMarker;
        console.assert(textMarker);
        if (!textMarker)
            return;

        var range = textMarker.find();
        console.assert(range);
        if (!range)
            return;

        this._createTextMarkerForPropertyIfNeeded(range.from, range.to, property);
    }

    _createTextMarkerForPropertyIfNeeded(from, to, property)
    {
        if (!this._codeMirror.getOption("readOnly")) {
            // Create a new checkbox element and marker.

            console.assert(property.enabled);

            var checkboxElement = document.createElement("input");
            checkboxElement.type = "checkbox";
            checkboxElement.checked = true;
            checkboxElement.addEventListener("change", this._propertyCheckboxChanged.bind(this));
            checkboxElement.__cssProperty = property;

            var checkboxMarker = this._codeMirror.setUniqueBookmark(from, checkboxElement);
            checkboxMarker.__propertyCheckbox = true;
        } else if (this._delegate.cssStyleDeclarationTextEditorShouldAddPropertyGoToArrows
                && !property.implicit && typeof this._delegate.cssStyleDeclarationTextEditorShowProperty === "function") {

            let arrowElement = WebInspector.createGoToArrowButton();
            arrowElement.title = WebInspector.UIString("Option-click to show source");

            let delegate = this._delegate;
            arrowElement.addEventListener("click", function(event) {
                delegate.cssStyleDeclarationTextEditorShowProperty(property, event.altKey);
            });

            this._codeMirror.setUniqueBookmark(to, arrowElement);
        }

        function duplicatePropertyExistsBelow(cssProperty)
        {
            var propertyFound = false;

            for (var property of this._style.properties) {
                if (property === cssProperty)
                    propertyFound = true;
                else if (property.name === cssProperty.name && propertyFound)
                    return true;
            }

            return false;
        }

        var propertyNameIsValid = false;
        if (WebInspector.CSSCompletions.cssNameCompletions)
            propertyNameIsValid = WebInspector.CSSCompletions.cssNameCompletions.isValidPropertyName(property.name);

        var classNames = ["css-style-declaration-property"];

        if (property.overridden)
            classNames.push("overridden");

        if (property.implicit)
            classNames.push("implicit");

        if (this._style.inherited && !property.inherited)
            classNames.push("not-inherited");

        if (!property.valid && property.hasOtherVendorNameOrKeyword())
            classNames.push("other-vendor");
        else if (!property.valid && (!propertyNameIsValid || duplicatePropertyExistsBelow.call(this, property)))
            classNames.push("invalid");

        if (!property.enabled)
            classNames.push("disabled");

        if (property.__filterResultClassName && !property.__filterResultNeedlePosition)
            classNames.push(property.__filterResultClassName);

        var classNamesString = classNames.join(" ");

        // If there is already a text marker and it's in the same document, then try to avoid recreating it.
        // FIXME: If there are multiple CSSStyleDeclarationTextEditors for the same style then this will cause
        // both editors to fight and always recreate their text markers. This isn't really common.
        if (property.__propertyTextMarker && property.__propertyTextMarker.doc.cm === this._codeMirror && property.__propertyTextMarker.find()) {
            // If the class name is the same then we don't need to make a new marker.
            if (property.__propertyTextMarker.className === classNamesString)
                return;

            property.__propertyTextMarker.clear();
        }

        var propertyTextMarker = this._codeMirror.markText(from, to, {className: classNamesString});

        propertyTextMarker.__cssProperty = property;
        property.__propertyTextMarker = propertyTextMarker;

        property.addEventListener(WebInspector.CSSProperty.Event.OverriddenStatusChanged, this._propertyOverriddenStatusChanged, this);

        this._removeCheckboxPlaceholder(from.line);

        if (property.__filterResultClassName && property.__filterResultNeedlePosition) {
            for (var needlePosition of property.__filterResultNeedlePosition.start) {
                var start = {line: from.line, ch: needlePosition};
                var end = {line: to.line, ch: start.ch + property.__filterResultNeedlePosition.length};

                this._codeMirror.markText(start, end, {className: property.__filterResultClassName});
            }
        }

        if (this._codeMirror.getOption("readOnly") || property.hasOtherVendorNameOrKeyword() || property.text.trim().endsWith(":") || !WebInspector.settings.stylesShowInlineWarnings.value)
            return;

        var propertyHasUnnecessaryPrefix = property.name.startsWith("-webkit-") && WebInspector.CSSCompletions.cssNameCompletions.isValidPropertyName(property.canonicalName);

        function generateInvalidMarker(options)
        {
            var invalidMarker = document.createElement("button");
            invalidMarker.className = "invalid-warning-marker";
            invalidMarker.title = options.title;

            if (typeof options.correction === "string") {
                // Allow for blank strings
                invalidMarker.classList.add("clickable");
                invalidMarker.addEventListener("click", function() {
                    this._codeMirror.replaceRange(options.correction, from, to);

                    if (options.autocomplete) {
                        this._codeMirror.setCursor(to);
                        this.focus();
                        this._completionController._completeAtCurrentPosition(true);
                    }
                }.bind(this));
            }

            this._codeMirror.setBookmark(options.position, invalidMarker);
        }

        function instancesOfProperty(propertyName)
        {
            var count = 0;

            for (var property of this._style.properties) {
                if (property.name === propertyName)
                    ++count;
            }

            return count;
        }

        // Number of times this property name is listed in the rule.
        var instances = instancesOfProperty.call(this, property.name);
        var invalidMarkerInfo;

        if (propertyHasUnnecessaryPrefix && !instancesOfProperty.call(this, property.canonicalName)) {
            // This property has a prefix and is valid without the prefix and the rule containing this property does not have the unprefixed version of the property.
            generateInvalidMarker.call(this, {
                position: from,
                title: WebInspector.UIString("The “webkit” prefix is not necessary.\nClick to insert a duplicate without the prefix."),
                correction: property.text + "\n" + property.text.replace("-webkit-", ""),
                autocomplete: false
            });
        } else if (instances > 1) {
            invalidMarkerInfo = {
                position: from,
                title: WebInspector.UIString("Duplicate property “%s”.\nClick to delete this property.").format(property.name),
                correction: "",
                autocomplete: false
            };
        }

        if (property.valid) {
            if (invalidMarkerInfo)
                generateInvalidMarker.call(this, invalidMarkerInfo);

            return;
        }

        if (propertyNameIsValid) {
            let start = {line: from.line, ch: from.ch + property.name.length + 2};
            let end = {line: to.line, ch: start.ch + property.value.length};

            this._codeMirror.markText(start, end, {className: "invalid"});

            if (/^(?:\d+)$/.test(property.value)) {
                invalidMarkerInfo = {
                    position: from,
                    title: WebInspector.UIString("The value “%s” needs units.\nClick to add “px” to the value.").format(property.value),
                    correction: property.name + ": " + property.value + "px;",
                    autocomplete: false
                };
            } else {
                var valueReplacement = property.value.length ? WebInspector.UIString("The value “%s” is not supported for this property.\nClick to delete and open autocomplete.").format(property.value) : WebInspector.UIString("This property needs a value.\nClick to open autocomplete.");

                invalidMarkerInfo = {
                    position: from,
                    title: valueReplacement,
                    correction: property.name + ": ",
                    autocomplete: true
                };
            }
        } else if (!instancesOfProperty.call(this, "-webkit-" + property.name) && WebInspector.CSSCompletions.cssNameCompletions.propertyRequiresWebkitPrefix(property.name)) {
            // The property is valid and exists in the rule while its prefixed version does not.
            invalidMarkerInfo = {
                position: from,
                title: WebInspector.UIString("The “webkit” prefix is needed for this property.\nClick to insert a duplicate with the prefix."),
                correction: "-webkit-" + property.text + "\n" + property.text,
                autocomplete: false
            };
        } else if (!propertyHasUnnecessaryPrefix && !WebInspector.CSSCompletions.cssNameCompletions.isValidPropertyName("-webkit-" + property.name)) {
            // The property either has no prefix and is invalid with a prefix or is invalid without a prefix.
            var closestPropertyName = WebInspector.CSSCompletions.cssNameCompletions.getClosestPropertyName(property.name);

            if (closestPropertyName) {
                // The property name has less than 3 other properties that have the same Levenshtein distance.
                invalidMarkerInfo = {
                    position: from,
                    title: WebInspector.UIString("Did you mean “%s”?\nClick to replace.").format(closestPropertyName),
                    correction: property.text.replace(property.name, closestPropertyName),
                    autocomplete: true
                };
            } else if (property.name.startsWith("-webkit-") && (closestPropertyName = WebInspector.CSSCompletions.cssNameCompletions.getClosestPropertyName(property.canonicalName))) {
                // The unprefixed property name has less than 3 other properties that have the same Levenshtein distance.
                invalidMarkerInfo = {
                    position: from,
                    title: WebInspector.UIString("Did you mean “%s”?\nClick to replace.").format("-webkit-" + closestPropertyName),
                    correction: property.text.replace(property.canonicalName, closestPropertyName),
                    autocomplete: true
                };
            } else {
                // The property name is so vague or nonsensical that there are more than 3 other properties that have the same Levenshtein value.
                invalidMarkerInfo = {
                    position: from,
                    title: WebInspector.UIString("Unsupported property “%s”").format(property.name),
                    correction: false,
                    autocomplete: false
                };
            }
        }

        if (!invalidMarkerInfo)
            return;

        generateInvalidMarker.call(this, invalidMarkerInfo);
    }

    _clearTextMarkers(nonatomic, all)
    {
        function clear()
        {
            var markers = this._codeMirror.getAllMarks();
            for (var i = 0; i < markers.length; ++i) {
                var textMarker = markers[i];

                if (!all && textMarker.__checkboxPlaceholder) {
                    var position = textMarker.find();

                    // Only keep checkbox placeholders if they are in the first column.
                    if (position && !position.ch)
                        continue;
                }

                if (textMarker.__cssProperty) {
                    textMarker.__cssProperty.removeEventListener(null, null, this);

                    delete textMarker.__cssProperty.__propertyTextMarker;
                    delete textMarker.__cssProperty;
                }

                textMarker.clear();
            }
        }

        if (nonatomic)
            clear.call(this);
        else
            this._codeMirror.operation(clear.bind(this));
    }

    _iterateOverProperties(onlyVisibleProperties, callback)
    {
        let properties = onlyVisibleProperties ? this._style.visibleProperties : this._style.properties;

        let filterFunction = (property) => property; // Identity function.
        if (this._filterResultPropertyNames) {
            filterFunction = (property) => {
                if (!property.variable && this._propertyVisibilityMode === WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.HideNonVariables)
                    return false;

                if (property.variable && this._propertyVisibilityMode === WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.HideVariables)
                    return false;

                if (property.implicit && !this._showsImplicitProperties)
                    return false;

                if (!(property.name in this._filterResultPropertyNames))
                    return false;

                return true;
            };
        } else if (!onlyVisibleProperties) {
            // Filter based on options only when all properties are used.
            filterFunction = (property) => {
                switch (this._propertyVisibilityMode) {
                case WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.HideNonVariables:
                    if (!property.variable)
                        return false;

                    break;
                case WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.HideVariables:
                    if (property.variable)
                        return false;

                    break;

                case WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode.ShowAll:
                    break;

                default:
                    console.error("Invalid property visibility mode");
                    break;
                }

                return !property.implicit || this._showsImplicitProperties || property.canonicalName in this._alwaysShowPropertyNames;
            };
        }

        properties = properties.filter(filterFunction);
        if (this._sortProperties)
            properties.sort((a, b) => a.name.extendedLocaleCompare(b.name));

        this._shownProperties = properties;

        for (var i = 0; i < properties.length; ++i) {
            if (callback.call(this, properties[i], i === properties.length - 1))
                break;
        }
    }

    _propertyCheckboxChanged(event)
    {
        var property = event.target.__cssProperty;
        console.assert(property);
        if (!property)
            return;

        this._commentProperty(property);
    }

    _commentProperty(property)
    {
        var textMarker = property.__propertyTextMarker;
        console.assert(textMarker);
        if (!textMarker)
            return;

        // Check if the property has been removed already, like from double-clicking
        // the checkbox and calling this event listener multiple times.
        var range = textMarker.find();
        if (!range)
            return;

        property._commentRange = range;
        property._commentRange.to.ch += 6; // Number of characters added by comments.

        var text = this._codeMirror.getRange(range.from, range.to);

        function update()
        {
            // Replace the text with a commented version.
            this._codeMirror.replaceRange("/* " + text + " */", range.from, range.to);

            // Update the line for any inline swatches that got removed.
            this._createInlineSwatches(true, range.from.line);
        }

        this._codeMirror.operation(update.bind(this));
    }

    _propertyCommentCheckboxChanged(event)
    {
        var commentTextMarker = event.target.__commentTextMarker;
        console.assert(commentTextMarker);
        if (!commentTextMarker)
            return;

        // Check if the comment has been removed already, like from double-clicking
        // the checkbox and calling event listener multiple times.
        var range = commentTextMarker.find();
        if (!range)
            return;

        this._uncommentRange(range);
    }

    _uncommentRange(range)
    {
        var text = this._codeMirror.getRange(range.from, range.to);

        // Remove the comment prefix and suffix.
        text = text.replace(/^\/\*\s*/, "").replace(/\s*\*\/$/, "");

        // Add a semicolon if there isn't one already.
        if (text.length && text.charAt(text.length - 1) !== ";")
            text += ";";

        function update()
        {
            this._codeMirror.addLineClass(range.from.line, "wrap", WebInspector.CSSStyleDeclarationTextEditor.EditingLineStyleClassName);
            this._codeMirror.replaceRange(text, range.from, range.to);

            // Update the line for any inline swatches that got removed.
            this._createInlineSwatches(true, range.from.line);
        }

        this._codeMirror.operation(update.bind(this));
    }

    _inlineSwatchValueChanged(event)
    {
        let swatch = event && event.target;
        console.assert(swatch);
        if (!swatch)
            return;

        let value = event.data && event.data.value && event.data.value.toString();
        console.assert(value);
        if (!value)
            return;

        let textMarker = swatch.__textMarker;
        let range = swatch.__textMarkerRange;
        console.assert(range);
        if (!range)
            return;

        function update()
        {
            // Sometimes we still might find a stale text marker with findMarksAt.
            range = textMarker.find();
            if (!range)
                return;

            textMarker.clear();

            this._codeMirror.replaceRange(value, range.from, range.to);

            // The value's text could have changed, so we need to update the "range"
            // variable to anticipate a different "range.to" property.
            range.to.ch = range.from.ch + value.length;

            textMarker = this._codeMirror.markText(range.from, range.to);

            swatch.__textMarker = textMarker;
        }

        this._codeMirror.operation(update.bind(this));
    }

    _inlineSwatchActivated()
    {
        this._hasActiveInlineSwatchEditor = true;
    }

    _inlineSwatchDeactivated()
    {
        this._hasActiveInlineSwatchEditor = false;
    }

    _propertyOverriddenStatusChanged(event)
    {
        this._updateTextMarkerForPropertyIfNeeded(event.target);
    }

    _propertiesChanged(event)
    {
        // Don't try to update the document while completions are showing. Doing so will clear
        // the completion hint and prevent further interaction with the completion.
        if (this._completionController.isShowingCompletions())
            return;

        if (this._hasActiveInlineSwatchEditor)
            return;

        // Don't try to update the document after just modifying a swatch.
        if (this._ignoreNextPropertiesChanged) {
            this._ignoreNextPropertiesChanged = false;
            return;
        }

        // Reset the content if the text is different and we are not focused.
        if (!this.focused && (!this._style.text || this._style.text !== this._formattedContent())) {
            this._resetContent();
            return;
        }

        this._removeEditingLineClassesSoon();

        this._updateTextMarkers();
    }

    _markLinesWithCheckboxPlaceholder()
    {
        if (this._codeMirror.getOption("readOnly"))
            return;

        var linesWithPropertyCheckboxes = {};
        var linesWithCheckboxPlaceholders = {};

        var markers = this._codeMirror.getAllMarks();
        for (var i = 0; i < markers.length; ++i) {
            var textMarker = markers[i];
            if (textMarker.__propertyCheckbox) {
                var position = textMarker.find();
                if (position)
                    linesWithPropertyCheckboxes[position.line] = true;
            } else if (textMarker.__checkboxPlaceholder) {
                var position = textMarker.find();
                if (position)
                    linesWithCheckboxPlaceholders[position.line] = true;
            }
        }

        var lineCount = this._codeMirror.lineCount();

        for (var i = 0; i < lineCount; ++i) {
            if (i in linesWithPropertyCheckboxes || i in linesWithCheckboxPlaceholders)
                continue;

            var position = {line: i, ch: 0};

            var placeholderElement = document.createElement("div");
            placeholderElement.className = WebInspector.CSSStyleDeclarationTextEditor.CheckboxPlaceholderElementStyleClassName;

            var placeholderMark = this._codeMirror.setUniqueBookmark(position, placeholderElement);
            placeholderMark.__checkboxPlaceholder = true;
        }
    }

    _removeCheckboxPlaceholder(lineNumber)
    {
        var marks = this._codeMirror.findMarksAt({line: lineNumber, ch: 0});
        for (var i = 0; i < marks.length; ++i) {
            var mark = marks[i];
            if (!mark.__checkboxPlaceholder)
                continue;

            mark.clear();
            return;
        }
    }

    _formattedContentFromEditor()
    {
        let indentString = WebInspector.indentString();
        let builder = new FormatterContentBuilder(indentString);
        let formatter = new WebInspector.Formatter(this._codeMirror, builder);
        let start = {line: 0, ch: 0};
        let end = {line: this._codeMirror.lineCount() - 1};
        formatter.format(start, end);

        return builder.formattedContent.trim();
    }

    _resetContent()
    {
        if (this._commitChangesTimeout) {
            clearTimeout(this._commitChangesTimeout);
            this._commitChangesTimeout = null;
        }

        this._removeEditingLineClasses();

        // Only allow editing if we have a style, it is editable and we have text range in the stylesheet.
        const readOnly = !this._style || !this._style.editable || !this._style.styleSheetTextRange;
        this._codeMirror.setOption("readOnly", readOnly);

        if (readOnly) {
            this.element.classList.add(WebInspector.CSSStyleDeclarationTextEditor.ReadOnlyStyleClassName);
            this._codeMirror.setOption("placeholder", WebInspector.UIString("No Properties"));
        } else {
            this.element.classList.remove(WebInspector.CSSStyleDeclarationTextEditor.ReadOnlyStyleClassName);
            this._codeMirror.setOption("placeholder", WebInspector.UIString("No Properties \u2014 Click to Edit"));
        }

        if (!this._style) {
            this._ignoreCodeMirrorContentDidChangeEvent = true;

            this._clearTextMarkers(false, true);
            this._codeMirror.setValue("");
            this._codeMirror.clearHistory();
            this._codeMirror.markClean();

            this._ignoreCodeMirrorContentDidChangeEvent = false;
            return;
        }

        function update()
        {
            // Remember the cursor position/selection.
            let isEditorReadOnly = this._codeMirror.getOption("readOnly");
            let styleText = this._style.text;
            let trimmedStyleText = styleText.trim();

            // We only need to format non-empty styles, but prepare checkbox placeholders
            // in any case because that will indent the cursor when the User starts typing.
            if (!trimmedStyleText && !isEditorReadOnly) {
                this._markLinesWithCheckboxPlaceholder();
                return;
            }

            // Generate formatted content for readonly editors by iterating properties.
            if (isEditorReadOnly) {
                this._codeMirror.setValue("");
                let lineNumber = 0;
                this._iterateOverProperties(false, function(property) {
                    let from = {line: lineNumber, ch: 0};
                    let to = {line: lineNumber};
                    // Readonly properties are pretty printed by `synthesizedText` and not the Formatter.
                    this._codeMirror.replaceRange((lineNumber ? "\n" : "") + property.synthesizedText, from);
                    this._createTextMarkerForPropertyIfNeeded(from, to, property);
                    lineNumber++;
                });
                return;
            }

            let selectionAnchor = this._codeMirror.getCursor("anchor");
            let selectionHead = this._codeMirror.getCursor("head");
            let whitespaceRegex = /\s+/g;

            this._linePrefixWhitespace = WebInspector.indentString();

            let styleTextPrefixWhitespace = styleText.match(/^\s*/);

            // If there is a match and the style text contains a newline, attempt to pull out the prefix whitespace
            // in front of the first line of CSS to use for every line.  If  there is no newline, we want to avoid
            // adding multiple spaces to a single line CSS rule and instead format it on multiple lines.
            if (styleTextPrefixWhitespace && trimmedStyleText.includes("\n")) {
                let linePrefixWhitespaceMatch = styleTextPrefixWhitespace[0].match(/[^\S\n]+$/);
                if (linePrefixWhitespaceMatch)
                    this._linePrefixWhitespace = linePrefixWhitespaceMatch[0];
            }

            // Set non-optimized, valid and invalid styles in preparation for the Formatter.
            this._codeMirror.setValue(trimmedStyleText);

            // Now the Formatter pretty prints the styles.
            this._codeMirror.setValue(this._formattedContentFromEditor());

            // We need to workaround the fact that...
            // 1) `this._style.properties` only holds valid CSSProperty instances but not
            // comments and invalid properties like `color;`.
            // 2) `_createTextMarkerForPropertyIfNeeded` relies on CSSProperty instances.
            let cssPropertiesMap = new Map();
            this._iterateOverProperties(false, function(cssProperty) {
                cssProperty.__refreshedAfterBlur = false;

                let propertyTextSansWhitespace = cssProperty.text.replace(whitespaceRegex, "");
                let existingProperties = cssPropertiesMap.get(propertyTextSansWhitespace) || [];
                existingProperties.push(cssProperty);

                cssPropertiesMap.set(propertyTextSansWhitespace, existingProperties);
            });

            // Go through the Editor line by line and create TextMarker when a
            // CSSProperty instance for that property exists. If not, then don't create a TextMarker.
            this._codeMirror.eachLine(function(lineHandler) {
                let lineNumber = lineHandler.lineNo();
                let lineContentSansWhitespace = lineHandler.text.replace(whitespaceRegex, "");
                let properties = cssPropertiesMap.get(lineContentSansWhitespace);
                if (!properties) {
                    this._createCommentedCheckboxMarker(lineHandler);
                    return;
                }

                for (let property of properties) {
                    if (property.__refreshedAfterBlur)
                        continue;

                    let from = {line: lineNumber, ch: 0};
                    let to = {line: lineNumber};
                    this._createTextMarkerForPropertyIfNeeded(from, to, property);
                    property.__refreshedAfterBlur = true;
                    break;
                }
            }.bind(this));

            // Look for swatchable values and make inline swatches.
            this._createInlineSwatches(true);

            // Restore the cursor position/selection.
            this._codeMirror.setSelection(selectionAnchor, selectionHead);

            // Reset undo history since undo past the reset is wrong when the content was empty before
            // or the content was representing a previous style object.
            this._codeMirror.clearHistory();

            // Mark the editor as clean (unedited state).
            this._codeMirror.markClean();

            this._markLinesWithCheckboxPlaceholder();
        }

        // This needs to be done first and as a separate operation to avoid an exception in CodeMirror.
        this._clearTextMarkers(false, true);

        this._ignoreCodeMirrorContentDidChangeEvent = true;
        this._codeMirror.operation(update.bind(this));
        this._ignoreCodeMirrorContentDidChangeEvent = false;
    }

    _updateJumpToSymbolTrackingMode()
    {
        var oldJumpToSymbolTrackingModeEnabled = this._jumpToSymbolTrackingModeEnabled;

        if (!this._style)
            this._jumpToSymbolTrackingModeEnabled = false;
        else
            this._jumpToSymbolTrackingModeEnabled = WebInspector.modifierKeys.altKey && !WebInspector.modifierKeys.metaKey && !WebInspector.modifierKeys.shiftKey;

        if (oldJumpToSymbolTrackingModeEnabled !== this._jumpToSymbolTrackingModeEnabled) {
            if (this._jumpToSymbolTrackingModeEnabled) {
                this._tokenTrackingController.highlightLastHoveredRange();
                this._tokenTrackingController.enabled = true;
            } else {
                this._tokenTrackingController.removeHighlightedRange();
                this._tokenTrackingController.enabled = false;
            }
        }
    }

    tokenTrackingControllerHighlightedRangeWasClicked(tokenTrackingController)
    {
        let candidate = tokenTrackingController.candidate;
        console.assert(candidate);
        if (!candidate)
            return;

        let sourceCodeLocation = null;
        if (this._style.ownerRule)
            sourceCodeLocation = this._style.ownerRule.sourceCodeLocation;

        let token = candidate.hoveredToken;

        const options = {
            ignoreNetworkTab: true,
            ignoreSearchTab: true,
        };

        // Special case option-clicking url(...) links.
        if (token && /\blink\b/.test(token.type)) {
            let url = token.string;
            let baseURL = sourceCodeLocation ? sourceCodeLocation.sourceCode.url : this._style.node.ownerDocument.documentURL;

            const frame = null;
            WebInspector.openURL(absoluteURL(url, baseURL), frame, options);
            return;
        }

        // Only allow other text to be clicked if there is a source code location.
        if (!this._style.ownerRule || !this._style.ownerRule.sourceCodeLocation)
            return;

        console.assert(sourceCodeLocation);
        if (!sourceCodeLocation)
            return;

        function showRangeInSourceCode(sourceCode, range)
        {
            if (!sourceCode || !range)
                return false;

            WebInspector.showSourceCodeLocation(sourceCode.createSourceCodeLocation(range.startLine, range.startColumn), options);
            return true;
        }

        // Special case option clicking CSS variables.
        if (token && /\bvariable-2\b/.test(token.type)) {
            let property = this._style.nodeStyles.effectivePropertyForName(token.string);
            if (property && showRangeInSourceCode(property.ownerStyle.ownerRule.sourceCodeLocation.sourceCode, property.styleSheetTextRange))
                return;
        }

        // Jump to the rule if we can't find a property.
        // Find a better source code location from the property that was clicked.
        let marks = this._codeMirror.findMarksAt(candidate.hoveredTokenRange.start);
        for (let mark of marks) {
            let property = mark.__cssProperty;
            if (property && showRangeInSourceCode(sourceCodeLocation.sourceCode, property.styleSheetTextRange))
                return;
        }
    }

    tokenTrackingControllerNewHighlightCandidate(tokenTrackingController, candidate)
    {
        // Do not highlight if the style has no source code location.
        if (!this._style.ownerRule || !this._style.ownerRule.sourceCodeLocation) {
            // Special case option-clicking url(...) links.
            if (!candidate.hoveredToken || !/\blink\b/.test(candidate.hoveredToken.type))
                return;
        }

        this._tokenTrackingController.highlightRange(candidate.hoveredTokenRange);
    }
};

WebInspector.CSSStyleDeclarationTextEditor.Event = {
    ContentChanged: "css-style-declaration-text-editor-content-changed",
    Blurred: "css-style-declaration-text-editor-blurred"
};

WebInspector.CSSStyleDeclarationTextEditor.PropertyVisibilityMode = {
    ShowAll: Symbol("variable-visibility-show-all"),
    HideVariables: Symbol("variable-visibility-hide-variables"),
    HideNonVariables: Symbol("variable-visibility-hide-non-variables"),
};

WebInspector.CSSStyleDeclarationTextEditor.PrefixWhitespace = "\n";
WebInspector.CSSStyleDeclarationTextEditor.SuffixWhitespace = "\n";
WebInspector.CSSStyleDeclarationTextEditor.StyleClassName = "css-style-text-editor";
WebInspector.CSSStyleDeclarationTextEditor.ReadOnlyStyleClassName = "read-only";
WebInspector.CSSStyleDeclarationTextEditor.CheckboxPlaceholderElementStyleClassName = "checkbox-placeholder";
WebInspector.CSSStyleDeclarationTextEditor.EditingLineStyleClassName = "editing-line";
WebInspector.CSSStyleDeclarationTextEditor.CommitCoalesceDelay = 250;
WebInspector.CSSStyleDeclarationTextEditor.RemoveEditingLineClassesDelay = 2000;
