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

WI.SpreadsheetCSSStyleDeclarationSection = class SpreadsheetCSSStyleDeclarationSection extends WI.View
{
    constructor(delegate, style)
    {
        console.assert(style instanceof WI.CSSStyleDeclaration, style);

        let element = document.createElement("section");
        element.classList.add("spreadsheet-css-declaration");

        super(element);

        this._delegate = delegate || null;
        this._style = style;
        this._propertiesEditor = null;
        this._selectorElements = [];
        this._groupingElements = [];
        this._filterText = null;
        this._shouldFocusSelectorElement = false;
        this._wasEditing = false;

        this._isMousePressed = false;
        this._mouseDownIndex = NaN;
        this._mouseDownPoint = null;
        this._boundHandleWindowMouseMove = null;
    }

    // Public

    get style() { return this._style; }

    get editable()
    {
        return this._style.editable;
    }

    set propertyVisibilityMode(propertyVisibilityMode)
    {
        this._propertiesEditor.propertyVisibilityMode = propertyVisibilityMode;
    }

    initialLayout()
    {
        super.initialLayout();

        let iconClassName = null;
        switch (this._style.type) {
        case WI.CSSStyleDeclaration.Type.Rule:
            console.assert(this._style.ownerRule);
            if (this._style.inherited) {
                iconClassName = "inherited-style-rule-icon";
                break;
            }

            switch (this._style.ownerRule.type) {
            case WI.CSSStyleSheet.Type.Author:
                iconClassName = "author-style-rule-icon";
                break;
            case WI.CSSStyleSheet.Type.User:
                iconClassName = "user-style-rule-icon";
                break;
            case WI.CSSStyleSheet.Type.UserAgent:
                iconClassName = "user-agent-style-rule-icon";
                break;
            case WI.CSSStyleSheet.Type.Inspector:
                iconClassName = "inspector-style-rule-icon";
                break;
            }
            break;
        case WI.CSSStyleDeclaration.Type.Inline:
        case WI.CSSStyleDeclaration.Type.Attribute:
            if (this._style.inherited)
                iconClassName = "inherited-element-style-rule-icon";
            else
                iconClassName = WI.DOMTreeElementPathComponent.DOMElementIconStyleClassName;
            break;
        }
        console.assert(iconClassName);
        this._element.classList.add("has-icon", iconClassName);

        let groupings = this._style.groupings.filter((grouping) => !grouping.isMedia || grouping.text !== "all").reverse();
        if (groupings.length) {
            let groupingsElement = this.element.appendChild(document.createElement("div"));
            groupingsElement.classList.add("header-groupings");

            let currentGroupingType = null;
            let currentGroupingHadText = false;
            let groupingTypeElement = null;
            this._groupingElements = groupings.map((grouping) => {
                if (grouping.type !== currentGroupingType || !grouping.text || !currentGroupingHadText) {
                    groupingTypeElement = groupingsElement.appendChild(document.createElement("div"));
                    groupingTypeElement.classList.add("grouping");
                    groupingTypeElement.textContent = grouping.prefix + " ";
                    currentGroupingType = grouping.type;
                } else
                    groupingTypeElement.append(grouping.isLayer && grouping.text ? "." : ", ");

                currentGroupingHadText = !!grouping.text;
                let span = groupingTypeElement.appendChild(document.createElement("span"));
                span.textContent = grouping.text ?? "";
                return span;
            });
        }

        this._headerElement = this._element.appendChild(document.createElement("div"));
        this._headerElement.classList.add("header");

        this._styleOriginView = new WI.StyleOriginView();
        this._headerElement.append(this._styleOriginView.element);

        this._selectorElement = document.createElement("span");
        this._selectorElement.classList.add("selector");
        this._selectorElement.addEventListener("mouseenter", this._highlightNodesWithSelector.bind(this));
        this._selectorElement.addEventListener("mouseleave", this._hideDOMNodeHighlight.bind(this));
        this._headerElement.append(this._selectorElement);

        this._openBrace = document.createElement("span");
        this._openBrace.classList.add("open-brace");
        this._openBrace.textContent = " {";
        this._headerElement.append(this._openBrace);

        if (this._style.selectorEditable) {
            this._selectorTextField = new WI.SpreadsheetSelectorField(this, this._selectorElement);
            this._selectorTextField.addEventListener(WI.SpreadsheetSelectorField.Event.StartedEditing, function(event) {
                this._headerElement.classList.add("editing-selector");
            }, this);
            this._selectorTextField.addEventListener(WI.SpreadsheetSelectorField.Event.StoppedEditing, function(event) {
                this._headerElement.classList.remove("editing-selector");
            }, this);

            this._selectorElement.tabIndex = 0;
        }

        this._propertiesEditor = new WI.SpreadsheetCSSStyleDeclarationEditor(this, this._style);
        this._propertiesEditor.element.classList.add("properties");
        this._propertiesEditor.addEventListener(WI.SpreadsheetCSSStyleDeclarationEditor.Event.FilterApplied, this._handleEditorFilterApplied, this);

        this._closeBrace = document.createElement("span");
        this._closeBrace.classList.add("close-brace");
        this._closeBrace.textContent = "}";


        this.addSubview(this._propertiesEditor);
        this._propertiesEditor.needsLayout();
        this._element.append(this._closeBrace);

        if (!this._style.editable)
            this._element.classList.add("locked");
        else if (!this._style.ownerRule)
            this._element.classList.add("selector-locked");

        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this));

        if (this._style.editable) {
            this.element.addEventListener("click", this._handleClick.bind(this));

            if (WI.FileUtilities.canSave(WI.FileUtilities.SaveMode.SingleFile)) {
                new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, "S", this._save.bind(this), this._element);
                new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "S", this._save.bind(this), this._element);
            }
        }
    }

    layout()
    {
        super.layout();

        this._styleOriginView.update(this._style);
        this._renderSelector();

        if (this._shouldFocusSelectorElement)
            this.startEditingRuleSelector();
    }

    startEditingRuleSelector()
    {
        if (!this._selectorElement) {
            this._shouldFocusSelectorElement = true;
            return;
        }

        this._shouldFocusSelectorElement = false;

        if (this._style.selectorEditable)
            this._selectorTextField.startEditing();
        else
            this._propertiesEditor.startEditingFirstProperty();
    }

    highlightProperty(property)
    {
        // When navigating from the Computed panel to the Styles panel, the latter
        // could be empty. Layout all properties so they can be highlighted.
        if (!this.didInitialLayout)
            this.updateLayout();

        if (this._propertiesEditor.highlightProperty(property)) {
            this._element.scrollIntoView();
            return true;
        }

        return false;
    }

    // SpreadsheetSelectorField delegate

    spreadsheetSelectorFieldDidCommit(changed)
    {
        let selectorText = this._selectorElement.textContent.trim();
        if (selectorText && changed) {
            this.dispatchEventToListeners(WI.SpreadsheetCSSStyleDeclarationSection.Event.SelectorWillChange);
            this._style.ownerRule.setSelectorText(selectorText).finally(this._renderSelector.bind(this));
        } else
            this._discardSelectorChange();
    }

    spreadsheetSelectorFieldWillNavigate(direction)
    {
        console.assert(direction);
        if (direction === "forward")
            this._propertiesEditor.startEditingFirstProperty();
        else if (direction === "backward") {
            if (this._delegate.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule) {
                const delta = -1;
                this._delegate.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(this, delta);
            } else
                this._propertiesEditor.startEditingLastProperty();
        }
    }

    spreadsheetSelectorFieldDidDiscard()
    {
        this._discardSelectorChange();
    }

    // SpreadsheetCSSStyleDeclarationEditor delegate

    spreadsheetCSSStyleDeclarationEditorStartEditingRuleSelector()
    {
        this.startEditingRuleSelector();
    }

    spreadsheetCSSStyleDeclarationEditorStartEditingAdjacentRule(propertiesEditor, delta)
    {
        if (!this._delegate)
            return;

        if (this._delegate.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule)
            this._delegate.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(this, delta);
    }

    spreadsheetCSSStyleDeclarationEditorPropertyBlur(event, property)
    {
        if (!this._isMousePressed)
            this._propertiesEditor.deselectProperties();
    }

    spreadsheetCSSStyleDeclarationEditorPropertyMouseEnter(event, property)
    {
        if (this._isMousePressed) {
            let index = parseInt(property.element.dataset.propertyIndex);
            this._propertiesEditor.selectProperties(this._mouseDownIndex, index);
        }
    }

    spreadsheetCSSStyleDeclarationEditorSelectProperty(property)
    {
        if (this._delegate && this._delegate.spreadsheetCSSStyleDeclarationSectionSelectProperty)
            this._delegate.spreadsheetCSSStyleDeclarationSectionSelectProperty(property);
    }

    spreadsheetCSSStyleDeclarationEditorSetAllPropertyVisibilityMode(editor, propertyVisibilityMode)
    {
        this._delegate?.spreadsheetCSSStyleDeclarationSectionSetAllPropertyVisibilityMode?.(this, propertyVisibilityMode);
    }

    applyFilter(filterText)
    {
        this._filterText = filterText;

        if (!this.didInitialLayout)
            return;

        this._element.classList.remove(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);

        this._propertiesEditor.applyFilter(this._filterText);
    }

    // Private

    _discardSelectorChange()
    {
        // Re-render selector for syntax highlighting.
        this._renderSelector();
    }

    _renderSelector()
    {
        this._selectorElement.removeChildren();
        this._selectorElements = [];

        let appendSelector = (selector, matched) => {
            console.assert(selector instanceof WI.CSSSelector);

            let selectorElement = this._selectorElement.appendChild(document.createElement("span"));
            selectorElement.textContent = selector.text;

            if (matched)
                selectorElement.classList.add(WI.SpreadsheetCSSStyleDeclarationSection.MatchedSelectorElementStyleClassName);

            if (selector.specificity) {
                let specificity = selector.specificity.map((number) => number.toLocaleString());
                let tooltip = WI.UIString("Specificity: (%d, %d, %d)").format(...specificity);
                if (selector.dynamic) {
                    tooltip += "\n";
                    if (this._style.inherited)
                        tooltip += WI.UIString("Dynamically calculated for the parent element");
                    else
                        tooltip += WI.UIString("Dynamically calculated for the selected element");
                }
                selectorElement.title = tooltip;
            } else if (selector.dynamic) {
                let tooltip = WI.UIString("Specificity: No value for selected element");
                tooltip += "\n";
                tooltip += WI.UIString("Dynamically calculated for the selected element and did not match");
                selectorElement.title = tooltip;
            }

            this._selectorElements.push(selectorElement);
        };

        let appendSelectorTextKnownToMatch = (selectorText) => {
            let selectorElement = this._selectorElement.appendChild(document.createElement("span"));
            selectorElement.textContent = selectorText;
            selectorElement.classList.add(WI.SpreadsheetCSSStyleDeclarationSection.MatchedSelectorElementStyleClassName);
        };

        if (!this._iconElement) {
            this._iconElement = document.createElement("img");
            this._iconElement.classList.add("icon");
            WI.addMouseDownContextMenuHandlers(this._iconElement, this._populateIconElementContextMenu.bind(this));
        }
        this._selectorElement.appendChild(this._iconElement);

        switch (this._style.type) {
        case WI.CSSStyleDeclaration.Type.Rule:
            console.assert(this._style.ownerRule);

            var hasMatchingPseudoSelector = false;

            var selectors = this._style.ownerRule.selectors;
            if (selectors.length) {
                for (let i = 0; i < selectors.length; ++i) {
                    let matched = this._style.ownerRule.matchedSelectorIndices.includes(i);
                    if (matched && selectors[i].isPseudoSelector())
                        hasMatchingPseudoSelector = true;

                    appendSelector(selectors[i], matched);
                    if (i < selectors.length - 1)
                        this._selectorElement.append(", ");
                }
            } else
                appendSelectorTextKnownToMatch(this._style.ownerRule.selectorText);

            this._element.classList.toggle("pseudo-selector", hasMatchingPseudoSelector);
            break;

        case WI.CSSStyleDeclaration.Type.Inline: {
            this._selectorElement.classList.add("style-attribute");
            let wrapper = this._selectorElement.appendChild(document.createElement("span"));
            wrapper.textContent = WI.UIString("Style Attribute", "CSS properties defined via HTML style attribute");
            break;
        }

        case WI.CSSStyleDeclaration.Type.Attribute:
            appendSelectorTextKnownToMatch(this._style.node.displayName);
            break;
        }

        if (this._filterText)
            this.applyFilter(this._filterText);
    }

    _save(event)
    {
        event.stop();

        if (this._style.type !== WI.CSSStyleDeclaration.Type.Rule) {
            // FIXME: Can't save CSS inside <style></style> <https://webkit.org/b/150357>
            InspectorFrontendHost.beep();
            return;
        }

        console.assert(this._style.ownerRule instanceof WI.CSSRule);
        console.assert(this._style.ownerRule.sourceCodeLocation instanceof WI.SourceCodeLocation);

        let sourceCode = this._style.ownerRule.sourceCodeLocation.sourceCode;
        if (sourceCode.type !== WI.Resource.Type.StyleSheet) {
            // FIXME: Can't save CSS inside style="" <https://webkit.org/b/150357>
            InspectorFrontendHost.beep();
            return;
        }

        let url;
        if (sourceCode.urlComponents.scheme === "data") {
            let mainResource = WI.networkManager.mainFrame.mainResource;
            if (mainResource.urlComponents.lastPathComponent.endsWith(".html"))
                url = mainResource.url.replace(/\.html$/, "-data.css");
            else {
                let pathDirectory = mainResource.url.slice(0, -mainResource.urlComponents.lastPathComponent.length);
                url = pathDirectory + "data.css";
            }
        } else
            url = sourceCode.url;

        let forceSaveAs = event.shiftKey;
        WI.FileUtilities.save(WI.FileUtilities.SaveMode.SingleFile, {url, content: sourceCode.content}, forceSaveAs);
    }

    _handleMouseDown(event)
    {
        if (event.button !== 0)
            return;

        this._wasEditing = this._propertiesEditor.editing || document.activeElement === this._selectorElement;

        let propertyElement = event.target.closest(".property");
        if (!propertyElement)
            return;

        this._isMousePressed = true;

        // Disable text selection on mousemove.
        event.preventDefault();

        // Canceling mousedown event prevents blur event from firing on the previously focused element.
        if (this._wasEditing && document.activeElement)
            document.activeElement.blur();

        // Prevent name/value fields from editing when properties selected.
        window.addEventListener("click", this._handleWindowClick.bind(this), {capture: true, once: true});

        let propertyIndex = parseInt(propertyElement.dataset.propertyIndex);
        if (event.shiftKey && this._propertiesEditor.hasSelectedProperties())
            this._propertiesEditor.extendSelectedProperties(propertyIndex);
        else {
            this._propertiesEditor.deselectProperties();
            this._mouseDownPoint = WI.Point.fromEvent(event);
            if (!this._boundHandleWindowMouseMove)
                this._boundHandleWindowMouseMove = this._handleWindowMouseMove.bind(this);
            window.addEventListener("mousemove", this._boundHandleWindowMouseMove);
        }

        if (propertyElement.parentNode) {
            this._mouseDownIndex = propertyIndex;
            this._element.classList.add("selecting");
        } else
            this._stopSelection();
    }

    _populateIconElementContextMenu(contextMenu)
    {
        contextMenu.appendItem(WI.UIString("Copy Rule"), () => {
            InspectorFrontendHost.copyText(this._style.generateFormattedText({includeGroupingsAndSelectors: true, multiline: true}));
        });

        if (this._style.editable && this._style.properties.length) {
            let shouldDisable = this._style.properties.some((property) => property.enabled);
            contextMenu.appendItem(shouldDisable ? WI.UIString("Disable Rule") : WI.UIString("Enable Rule"), () => {
                for (let property of this._style.properties)
                    property.commentOut(shouldDisable);
            });
        }

        if (!this._style.inherited && InspectorBackend.hasCommand("CSS.addRule")) {
            let generateSelector = () => {
                if (this._style.type === WI.CSSStyleDeclaration.Type.Attribute)
                    return this._style.node.displayName;
                return this._style.selectorText;
            };

            let createNewRule = (selector, text) => {
                if (this._delegate && this._delegate.spreadsheetCSSStyleDeclarationSectionAddNewRule)
                    this._delegate.spreadsheetCSSStyleDeclarationSectionAddNewRule(this, selector, text);
                else
                    this._style.nodeStyles.addRule(selector, text);
            };

            contextMenu.appendSeparator();

            contextMenu.appendItem(WI.UIString("Duplicate Selector"), () => {
                createNewRule(generateSelector());
            });

            if (!WI.CSSManager.PseudoElementNames.some((className) => this._style.selectorText.includes(":" + className))) {
                let addPseudoRule = (pseudoSelector, text) => {
                    let selector = null;
                    if (this._style.ownerRule)
                        selector = this._style.ownerRule.selectors.map((selector) => selector.text + pseudoSelector).join(", ");
                    else
                        selector = generateSelector() + pseudoSelector;
                    createNewRule(selector, text);
                };

                if (WI.cssManager.canForcePseudoClass() && Object.values(WI.CSSManager.ForceablePseudoClass).every((className) => !this._style.selectorText.includes(":" + className))) {
                    contextMenu.appendSeparator();

                    for (let pseudoClass of Object.values(WI.CSSManager.ForceablePseudoClass)) {
                        if (!WI.cssManager.canForcePseudoClass(pseudoClass))
                            continue;

                        if (pseudoClass === WI.CSSManager.ForceablePseudoClass.Visited && this._style.node.nodeName() !== "A")
                            continue;

                        let pseudoClassSelector = ":" + pseudoClass;
                        contextMenu.appendItem(WI.UIString("Add %s Rule").format(pseudoClassSelector), () => {
                            this._style.node.setPseudoClassEnabled(pseudoClass, true);

                            addPseudoRule(pseudoClassSelector);
                        });
                    }
                }

                if (this._style.type === WI.CSSStyleDeclaration.Type.Rule) {
                    contextMenu.appendSeparator();

                    for (let pseudoElement of WI.CSSManager.PseudoElementNames) {
                        let pseudoElementSelector = "::" + pseudoElement;
                        contextMenu.appendItem(WI.UIString("Create %s Rule").format(pseudoElementSelector), () => {
                            addPseudoRule(pseudoElementSelector, "content: \"\";");
                        });
                    }
                }
            }
        }

        if (this._style.ownerRule && this._style.ownerRule.sourceCodeLocation) {
            contextMenu.appendSeparator();

            let label = null;
            let sourceCode = this._style.ownerRule.sourceCodeLocation.displaySourceCode;
            if (sourceCode instanceof WI.CSSStyleSheet || (sourceCode instanceof WI.Resource && sourceCode.type === WI.Resource.Type.StyleSheet))
                label = WI.UIString("Reveal in Style Sheet");
            else
                label = WI.UIString("Reveal in Sources Tab");
            contextMenu.appendItem(label, () => {
                WI.showSourceCodeLocation(this._style.ownerRule.sourceCodeLocation, {
                    ignoreNetworkTab: true,
                    ignoreSearchTab: true,
                    initiatorHint: WI.TabBrowser.TabNavigationInitiator.ContextMenu,
                });
            });
        }
    }

    _handleWindowClick(event)
    {
        if (this._propertiesEditor.hasSelectedProperties()) {
            // Don't start editing name/value if there's selection.
            event.stop();
        }
        this._stopSelection();
    }

    _handleWindowMouseMove(event)
    {
        console.assert(this._mouseDownPoint);

        if (this._mouseDownPoint.distance(WI.Point.fromEvent(event)) < 8)
            return;

        if (!this._propertiesEditor.hasSelectedProperties()) {
            console.assert(!isNaN(this._mouseDownIndex));
            this._propertiesEditor.selectProperties(this._mouseDownIndex, this._mouseDownIndex);
        }

        window.removeEventListener("mousemove", this._boundHandleWindowMouseMove);
        this._mouseDownPoint = null;
    }

    _handleClick(event)
    {
        this._stopSelection();

        if (this._wasEditing || this._propertiesEditor.hasSelectedProperties())
            return;

        if (window.getSelection().type === "Range")
            return;

        event.stop();

        if (event.target.classList.contains(WI.SpreadsheetStyleProperty.StyleClassName)) {
            let propertyIndex = parseInt(event.target.dataset.propertyIndex);
            this._propertiesEditor.addBlankProperty(propertyIndex + 1);
            return;
        }

        if (event.target === this._headerElement || event.target === this._openBrace) {
            this._propertiesEditor.addBlankProperty(0);
            return;
        }

        if (event.target === this._element || event.target === this._closeBrace) {
            const appendAfterLast = -1;
            this._propertiesEditor.addBlankProperty(appendAfterLast);
        }
    }

    _stopSelection()
    {
        this._isMousePressed = false;
        this._mouseDownIndex = NaN;
        this._element.classList.remove("selecting");

        // "copy" and "cut" events won't fire on SpreadsheetCSSStyleDeclarationEditor unless it has text selected.
        // Placing a text caret inside of a property has no visible effects but it allows the events to fire.
        this._propertiesEditor.placeTextCaretInFocusedProperty();

        window.removeEventListener("mousemove", this._boundHandleWindowMouseMove);
        this._mouseDownPoint = null;
    }

    _highlightNodesWithSelector()
    {
        let node = this._style.node;

        if (!this._style.ownerRule) {
            node.highlight();
            return;
        }

        let selectorText = this._selectorElement.textContent.trim();
        if (node.frame)
            WI.domManager.highlightSelector(selectorText, node.frame.id);
        else
            WI.domManager.highlightSelector(selectorText);
    }

    _hideDOMNodeHighlight()
    {
        WI.domManager.hideDOMNodeHighlight();
    }

    _handleEditorFilterApplied(event)
    {
        let matchesGrouping = false;
        for (let groupingElement of this._groupingElements) {
            groupingElement.classList.remove(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);

            if (groupingElement.textContent.includes(this._filterText)) {
                groupingElement.classList.add(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);
                matchesGrouping = true;
            }
        }

        let matchesSelector = false;
        for (let selectorElement of this._selectorElements) {
            selectorElement.classList.remove(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);

            if (selectorElement.textContent.includes(this._filterText)) {
                selectorElement.classList.add(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);
                matchesSelector = true;
            }
        }

        let matches = event.data.matches || matchesGrouping || matchesSelector;
        if (!matches)
            this._element.classList.add(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);

        this.dispatchEventToListeners(WI.SpreadsheetCSSStyleDeclarationSection.Event.FilterApplied, {matches});
    }
};

WI.SpreadsheetCSSStyleDeclarationSection.Event = {
    FilterApplied: "spreadsheet-css-style-declaration-section-filter-applied",
    SelectorWillChange: "spreadsheet-css-style-declaration-section-selector-will-change",
};

WI.SpreadsheetCSSStyleDeclarationSection.MatchedSelectorElementStyleClassName = "matched";
