/*
 * 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._mediaElements = [];
        this._filterText = null;
        this._shouldFocusSelectorElement = false;
        this._wasEditing = false;
    }

    // Public

    get style() { return this._style; }

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

    initialLayout()
    {
        super.initialLayout();

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

        this._originElement = document.createElement("span");
        this._originElement.classList.add("origin");
        this._headerElement.append(this._originElement);

        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._selectorElement.tabIndex = 0;
            this._selectorElement.addEventListener("focus", () => this._headerElement.classList.add("editing-selector"));
            this._selectorElement.addEventListener("blur", () => this._headerElement.classList.remove("editing-selector"));
        }

        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._element.append(this._createMediaHeader(), this._headerElement);
        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");

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

            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._renderOrigin();
        this._renderSelector();

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

    hidden()
    {
        this._propertiesEditor.hidden();
    }

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

        this._selectorElement.focus();
        this._shouldFocusSelectorElement = false;
    }

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

    cssStyleDeclarationTextEditorStartEditingRuleSelector()
    {
        this.startEditingRuleSelector();
    }

    // SpreadsheetSelectorField delegate

    spreadsheetSelectorFieldDidChange(direction)
    {
        let selectorText = this._selectorElement.textContent.trim();

        if (!selectorText || selectorText === this._style.ownerRule.selectorText)
            this._discardSelectorChange();
        else {
            this._style.ownerRule.singleFireEventListener(WI.CSSRule.Event.SelectorChanged, this._renderSelector, this);
            this._style.ownerRule.selectorText = selectorText;
        }

        if (!direction) {
            // Don't do anything when it's a blur event.
            return;
        }

        if (direction === "forward")
            this._propertiesEditor.startEditingFirstProperty();
        else if (direction === "backward") {
            if (typeof this._delegate.cssStyleDeclarationSectionStartEditingPreviousRule === "function")
                this._delegate.cssStyleDeclarationSectionStartEditingPreviousRule(this);
        }
    }

    spreadsheetSelectorFieldDidDiscard()
    {
        this._discardSelectorChange();
    }

    // SpreadsheetCSSStyleDeclarationEditor delegate

    cssStyleDeclarationEditorStartEditingAdjacentRule(toPreviousRule)
    {
        if (!this._delegate)
            return;

        if (toPreviousRule && typeof this._delegate.cssStyleDeclarationSectionStartEditingPreviousRule === "function")
            this._delegate.cssStyleDeclarationSectionStartEditingPreviousRule(this);
        else if (!toPreviousRule && typeof this._delegate.cssStyleDeclarationSectionStartEditingNextRule === "function")
            this._delegate.cssStyleDeclarationSectionStartEditingNextRule(this);
    }

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

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

            var selectors = this._style.ownerRule.selectors;
            var matchedSelectorIndices = this._style.ownerRule.matchedSelectorIndices;
            var alwaysMatch = !matchedSelectorIndices.length;
            if (selectors.length) {
                let hasMatchingPseudoElementSelector = false;
                for (let i = 0; i < selectors.length; ++i) {
                    appendSelector(selectors[i], alwaysMatch || matchedSelectorIndices.includes(i));
                    if (i < selectors.length - 1)
                        this._selectorElement.append(", ");

                    if (matchedSelectorIndices.includes(i) && selectors[i].isPseudoElementSelector())
                        hasMatchingPseudoElementSelector = true;
                }
                this._element.classList.toggle("pseudo-element-selector", hasMatchingPseudoElementSelector);
            } else
                appendSelectorTextKnownToMatch(this._style.ownerRule.selectorText);

            break;

        case WI.CSSStyleDeclaration.Type.Inline:
            this._selectorElement.textContent = WI.UIString("Style Attribute");
            this._selectorElement.classList.add("style-attribute");
            break;

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

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

    _renderOrigin()
    {
        this._originElement.removeChildren();

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

            if (this._style.ownerRule.sourceCodeLocation) {
                let options = {
                    dontFloat: true,
                    ignoreNetworkTab: true,
                    ignoreSearchTab: true,
                };

                if (this._style.ownerStyleSheet.isInspectorStyleSheet()) {
                    options.nameStyle = WI.SourceCodeLocation.NameStyle.None;
                    options.prefix = WI.UIString("Inspector Style Sheet") + ":";
                }

                let sourceCodeLink = WI.createSourceCodeLocationLink(this._style.ownerRule.sourceCodeLocation, options);
                this._originElement.appendChild(sourceCodeLink);
            } else {
                let originString = "";

                switch (this._style.ownerRule.type) {
                case WI.CSSStyleSheet.Type.Author:
                    originString = WI.UIString("Author Stylesheet");
                    break;

                case WI.CSSStyleSheet.Type.User:
                    originString = WI.UIString("User Stylesheet");
                    break;

                case WI.CSSStyleSheet.Type.UserAgent:
                    originString = WI.UIString("User Agent Stylesheet");
                    break;

                case WI.CSSStyleSheet.Type.Inspector:
                    originString = WI.UIString("Web Inspector");
                    break;
                }

                console.assert(originString);
                if (originString)
                    this._originElement.append(originString);

                if (!this._style.editable) {
                    let styleTitle = "";
                    if (this._style.ownerRule && this._style.ownerRule.type === WI.CSSStyleSheet.Type.UserAgent)
                        styleTitle = WI.UIString("User Agent Stylesheet");
                    else
                        styleTitle = WI.UIString("Style rule");

                    this._originElement.title = WI.UIString("%s cannot be modified").format(styleTitle);
                }
            }
            break;

        case WI.CSSStyleDeclaration.Type.Attribute:
            this._originElement.append(WI.UIString("HTML Attributes"));
            break;
        }
    }

    _createMediaHeader()
    {
        let mediaList = this._style.mediaList;
        if (!mediaList.length || (mediaList.length === 1 && (mediaList[0].text === "all" || mediaList[0].text === "screen")))
            return "";

        let mediaElement = document.createElement("div");
        mediaElement.classList.add("header-media");

        let mediaLabel = mediaElement.appendChild(document.createElement("div"));
        mediaLabel.className = "media-label";
        mediaLabel.append("@media ");

        this._mediaElements = mediaList.map((media, i) => {
            if (i)
                mediaLabel.append(", ");

            let span = mediaLabel.appendChild(document.createElement("span"));
            span.textContent = media.text;
            return span;
        });

        return mediaElement;
    }

    _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.frameResourceManager.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;

        const saveAs = event.shiftKey;
        WI.saveDataToFile({url: url, content: sourceCode.content}, saveAs);
    }

    _handleMouseDown(event)
    {
        this._wasEditing = this._propertiesEditor.editing || document.activeElement === this._selectorElement;
    }

    _handleClick(event)
    {
        if (this._wasEditing)
            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);
        }
    }

    _highlightNodesWithSelector()
    {
        if (!this._style.ownerRule) {
            WI.domTreeManager.highlightDOMNode(this._style.node.id);
            return;
        }

        let selectorText = this._selectorElement.textContent.trim();
        WI.domTreeManager.highlightSelector(selectorText, this._style.node.ownerDocument.frameIdentifier);
    }

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

    _handleEditorFilterApplied(event)
    {
        let matchesMedia = false;
        for (let mediaElement of this._mediaElements) {
            mediaElement.classList.remove(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);

            if (mediaElement.textContent.includes(this._filterText)) {
                mediaElement.classList.add(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName);
                matchesMedia = 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 || matchesMedia || 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",
};

WI.SpreadsheetCSSStyleDeclarationSection.MatchedSelectorElementStyleClassName = "matched";
