/*
 * 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.SpreadsheetRulesStyleDetailsPanel = class SpreadsheetRulesStyleDetailsPanel extends WI.StyleDetailsPanel
{
    constructor(delegate)
    {
        const className = "rules";
        const identifier = "rules";
        const label = WI.UIString("Styles \u2014 Rules");
        super(delegate, className, identifier, label);

        // Make the styles sidebar always left-to-right since CSS is strictly an LTR language.
        this.element.dir = "ltr";

        this._headerMap = new Map;
        this._sections = [];
        this._newRuleSelector = null;
        this._ruleMediaAndInherticanceList = [];
        this._propertyToSelectAndHighlight = null;
        this._filterText = null;
        this._shouldRefreshSubviews = false;

        this._emptyFilterResultsElement = WI.createMessageTextView(WI.UIString("No Results Found"));
    }

    // Public

    refresh(significantChange)
    {
        // We only need to do a rebuild on significant changes. Other changes are handled
        // by the sections and text editors themselves.
        if (significantChange) {
            this._shouldRefreshSubviews = true;
            this.needsLayout();
        }

        super.refresh(significantChange);
    }

    hidden()
    {
        for (let section of this._sections)
            section.hidden();

        super.hidden();
    }

    scrollToSectionAndHighlightProperty(property)
    {
        if (!this._visible) {
            this._propertyToSelectAndHighlight = property;
            return;
        }

        for (let section of this._sections) {
            if (section.highlightProperty(property))
                return;
        }
    }

    nodeStylesRefreshed(event)
    {
        super.nodeStylesRefreshed(event);

        if (this._propertyToSelectAndHighlight) {
            this.scrollToSectionAndHighlightProperty(this._propertyToSelectAndHighlight);
            this._propertyToSelectAndHighlight = null;
        }
    }

    newRuleButtonClicked()
    {
        if (this.nodeStyles.node.isInUserAgentShadowTree())
            return;

        this._addNewRule();
    }

    newRuleButtonContextMenu(event)
    {
        if (this.nodeStyles.node.isInUserAgentShadowTree())
            return;

        let styleSheets = WI.cssManager.styleSheets.filter(styleSheet => styleSheet.hasInfo() && !styleSheet.isInlineStyleTag() && !styleSheet.isInlineStyleAttributeStyleSheet());
        if (!styleSheets.length)
            return;

        let contextMenu = WI.ContextMenu.createFromEvent(event);

        const handler = null;
        const disabled = true;
        contextMenu.appendItem(WI.UIString("Available Style Sheets"), handler, disabled);

        let [inspectorStyleSheets, regularStyleSheets] = styleSheets.partition(styleSheet => styleSheet.isInspectorStyleSheet());
        console.assert(inspectorStyleSheets.length <= 1, "There should never be more than one inspector style sheet");

        contextMenu.appendItem(WI.UIString("Inspector Style Sheet"), () => {
            this._addNewRule(inspectorStyleSheets.length ? inspectorStyleSheets[0].id : null);
        });

        for (let styleSheet of regularStyleSheets) {
            contextMenu.appendItem(styleSheet.displayName, () => {
                this._addNewRule(styleSheet.id);
            });
        }
    }

    applyFilter(filterText)
    {
        this._filterText = filterText;

        if (!this.didInitialLayout)
            return;

        if (this._filterText)
            this.element.classList.add("filter-non-matching");

        for (let header of this._headerMap.values())
            header.classList.add(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);

        for (let section of this._sections)
            section.applyFilter(this._filterText);
    }

    focusFirstSection()
    {
        this.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(null, 1);
    }

    focusLastSection()
    {
        this.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(null, -1);
    }

    // SpreadsheetCSSStyleDeclarationSection delegate

    spreadsheetCSSStyleDeclarationSectionSelectProperty(property)
    {
        this.scrollToSectionAndHighlightProperty(property);
    }

    spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(currentSection, delta)
    {
        console.assert(delta !== 0);

        let index = this._sections.indexOf(currentSection);
        if (index < 0) {
            if (delta < 0)
                index = this._sections.length;
            else if (delta > 0)
                index = -1;
        }
        index += delta;

        while (this._sections[index] !== currentSection) {
            if (index < 0) {
                if (this._delegate && this._delegate.styleDetailsPanelFocusLastPseudoClassCheckbox) {
                    this._delegate.styleDetailsPanelFocusLastPseudoClassCheckbox(this);
                    break;
                }

                index = this._sections.length - 1;
            } else if (index >= this._sections.length) {
                if (this._delegate && this._delegate.styleDetailsPanelFocusFilterBar) {
                    this._delegate.styleDetailsPanelFocusFilterBar(this);
                    break;
                }

                index = 0;
            }

            let section = this._sections[index];
            if (section.editable) {
                if (delta < 0)
                    section._propertiesEditor.startEditingLastProperty();
                else
                    section.startEditingRuleSelector();
                break;
            }

            index += delta;
        }
    }

    // Protected

    layout()
    {
        if (!this._shouldRefreshSubviews)
            return;

        this._shouldRefreshSubviews = false;

        let oldSections = this._sections.slice();
        let preservedSections = oldSections.filter((section) => {
            if (section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] !== this.nodeStyles.node) {
                section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] = null;
                section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] = -1;
            }
            return section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol];
        });

        if (preservedSections.length) {
            for (let section of oldSections) {
                if (!preservedSections.includes(section))
                    this.removeSubview(section);
            }
            for (let header of this._headerMap.values())
                header.remove();
        } else
            this.removeAllSubviews();

        let previousStyle = null;
        let currentHeader = null;
        this._headerMap.clear();
        this._sections = [];

        let addHeader = (text, nodeOrPseudoId) => {
            currentHeader = this.element.appendChild(document.createElement("h2"));
            currentHeader.classList.add("section-header");
            currentHeader.append(text);

            if (nodeOrPseudoId) {
                if (nodeOrPseudoId instanceof WI.DOMNode) {
                    currentHeader.append(" ", WI.linkifyNodeReference(nodeOrPseudoId, {
                        maxLength: 100,
                        excludeRevealElement: true,
                    }));
                } else
                    currentHeader.append(" ", WI.CSSManager.displayNameForPseudoId(nodeOrPseudoId));
            }
        };

        let addSection = (section) => {
            if (section.style.inherited && (!previousStyle || previousStyle.node !== section.style.node))
                addHeader(WI.UIString("Inherited From", "A section of CSS rules matching an ancestor DOM node"), section.style.node);

            if (!section.isDescendantOf(this)) {
                let referenceView = this.subviews[this._sections.length];
                if (!referenceView || referenceView[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] === this._sections.length)
                    this.addSubview(section);
                else
                    this.insertSubviewBefore(section, referenceView);
            }

            this._sections.push(section);
            section.needsLayout();

            if (currentHeader)
                this._headerMap.set(section.style, currentHeader);

            previousStyle = section.style;
        };

        let createSection = (style) => {
            let section = style[SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol];
            if (!section) {
                section = new WI.SpreadsheetCSSStyleDeclarationSection(this, style);
                section.addEventListener(WI.SpreadsheetCSSStyleDeclarationSection.Event.FilterApplied, this._handleSectionFilterApplied, this);
                section.addEventListener(WI.SpreadsheetCSSStyleDeclarationSection.Event.SelectorWillChange, this._handleSectionSelectorWillChange, this);
                style[SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol] = section;
            }

            if (this._newRuleSelector === style.selectorText && style.enabledProperties.length === 0)
                section.startEditingRuleSelector();

            addSection(section);

            let preservedSection = preservedSections.find((sectionToPreserve) => sectionToPreserve[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] === this._sections.length - 1);
            if (preservedSection)
                addSection(preservedSection);
        };

        for (let style of this.nodeStyles.uniqueOrderedStyles)
            createSection(style);

        let beforePseudoId = null;
        let afterPseudoId = null;
        if (InspectorBackend.domains.CSS.PseudoId) {
            beforePseudoId = InspectorBackend.domains.CSS.PseudoId.Before;
            afterPseudoId = InspectorBackend.domains.CSS.PseudoId.After;
        } else {
            // Compatibility (iOS 12.2): CSS.PseudoId did not exist.
            beforePseudoId = 4;
            afterPseudoId = 5;
        }

        for (let [pseudoId, pseudoElementInfo] of this.nodeStyles.pseudoElements) {
            let pseudoElement = null;
            if (pseudoId === beforePseudoId)
                pseudoElement = this.nodeStyles.node.beforePseudoElement();
            else if (pseudoId === afterPseudoId)
                pseudoElement = this.nodeStyles.node.afterPseudoElement();
            addHeader(WI.UIString("Pseudo-Element"), pseudoElement || pseudoId);

            for (let style of WI.DOMNodeStyles.uniqueOrderedStyles(pseudoElementInfo.orderedStyles))
                createSection(style);
        }

        this._newRuleSelector = null;

        this.element.append(this._emptyFilterResultsElement);

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

    filterDidChange(filterBar)
    {
        super.filterDidChange(filterBar);

        this.applyFilter(filterBar.filters.text);
    }

    // Private

    _handleSectionFilterApplied(event)
    {
        if (!event.data.matches)
            return;

        this.element.classList.remove("filter-non-matching");

        let header = this._headerMap.get(event.target.style);
        if (header)
            header.classList.remove(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);
    }

    _addNewRule(stylesheetId)
    {
        const justSelector = true;
        this._newRuleSelector = this.nodeStyles.node.appropriateSelectorFor(justSelector);

        const text = "";
        this.nodeStyles.addRule(this._newRuleSelector, text, stylesheetId);
    }

    _handleSectionSelectorWillChange(event)
    {
        let section = event.target;
        section[SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol] = this.nodeStyles.node;
        section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] = this._sections.indexOf(section);
        console.assert(section[SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol] >= 0);
    }
};

WI.SpreadsheetRulesStyleDetailsPanel.StyleSectionSymbol = Symbol("style-section");
WI.SpreadsheetRulesStyleDetailsPanel.SectionShowingForNodeSymbol = Symbol("style-showing-for-node");
WI.SpreadsheetRulesStyleDetailsPanel.SectionIndexSymbol = Symbol("style-index");
