/*
 * 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

    get supportsNewRule()
    {
        return this.nodeStyles && !this.nodeStyles.node.isInUserAgentShadowTree();
    }

    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()
    {
        this._addNewRule();
    }

    newRuleButtonContextMenu(event)
    {
        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;
        }
    }

    spreadsheetCSSStyleDeclarationSectionAddNewRule(section, selector, text)
    {
        this._newRuleSelector = selector;
        this.nodeStyles.addRule(this._newRuleSelector, text);
    }

    // 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);
        };

        let addedPseudoStyles = false;
        let addPseudoStyles = () => {
            if (addedPseudoStyles)
                return;

            // Add all pseudo styles before any inherited rules.
            let beforePseudoId = null;
            let afterPseudoId = null;
            if (InspectorBackend.Enum.CSS.PseudoId) {
                beforePseudoId = WI.CSSManager.PseudoSelectorNames.Before;
                afterPseudoId = WI.CSSManager.PseudoSelectorNames.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);
            }

            addedPseudoStyles = true;
        };

        for (let style of this.nodeStyles.uniqueOrderedStyles) {
            if (style.inherited)
                addPseudoStyles();
            createSection(style);
        }

        addPseudoStyles();

        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");
