/*
 * Copyright (C) 2013 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.
 */

// FIXME: CSSManager lacks advanced multi-target support. (Stylesheets per-target)

WI.CSSManager = class CSSManager extends WI.Object
{
    constructor()
    {
        super();

        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
        WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceAdded, this);
        WI.Resource.addEventListener(WI.SourceCode.Event.ContentDidChange, this._resourceContentDidChange, this);
        WI.Resource.addEventListener(WI.Resource.Event.TypeDidChange, this._resourceTypeDidChange, this);

        WI.DOMNode.addEventListener(WI.DOMNode.Event.AttributeModified, this._nodeAttributesDidChange, this);
        WI.DOMNode.addEventListener(WI.DOMNode.Event.AttributeRemoved, this._nodeAttributesDidChange, this);
        WI.DOMNode.addEventListener(WI.DOMNode.Event.EnabledPseudoClassesChanged, this._nodePseudoClassesDidChange, this);

        this._colorFormatSetting = new WI.Setting("default-color-format", WI.Color.Format.Original);

        this._styleSheetIdentifierMap = new Map;
        this._styleSheetFrameURLMap = new Map;
        this._nodeStylesMap = {};
        this._modifiedStyles = new Map;
        this._defaultAppearance = null;
        this._forcedAppearance = null;
    }

    // Target

    initializeTarget(target)
    {
        if (target.hasDomain("CSS"))
            target.CSSAgent.enable();
    }

    // Static

    static supportsInspectorStyleSheet()
    {
        return InspectorBackend.hasCommand("CSS.createStyleSheet");
    }

    static protocolStyleSheetOriginToEnum(origin)
    {
        switch (origin) {
        case InspectorBackend.Enum.CSS.StyleSheetOrigin.User:
            return WI.CSSStyleSheet.Type.User;

        case InspectorBackend.Enum.CSS.StyleSheetOrigin.UserAgent:
            return WI.CSSStyleSheet.Type.UserAgent;

        case InspectorBackend.Enum.CSS.StyleSheetOrigin.Inspector:
            return WI.CSSStyleSheet.Type.Inspector;
        }

        // COMPATIBILITY (iOS 14): CSS.StyleSheetOrigin.Regular was replaced with CSS.StyleSheetOrigin.Author.
        console.assert(!InspectorBackend.Enum.CSS.StyleSheetOrigin.Author || origin === InspectorBackend.Enum.CSS.StyleSheetOrigin.Author);
        console.assert(!InspectorBackend.Enum.CSS.StyleSheetOrigin.Regular || origin === InspectorBackend.Enum.CSS.StyleSheetOrigin.Regular);
        return WI.CSSStyleSheet.Type.Author;
    }

    static protocolGroupingTypeToEnum(type)
    {
        // COMPATIBILITY (iOS 13): CSS.Grouping did not exist yet.
        if (!InspectorBackend.Enum.CSS.Grouping) {
            switch (type) {
            case "mediaRule":
                return WI.CSSGrouping.Type.MediaRule;
            case "importRule":
                return WI.CSSGrouping.Type.MediaImportRule;
            case "linkedSheet":
                return WI.CSSGrouping.Type.MediaLinkNode;
            case "inlineSheet":
                return WI.CSSGrouping.Type.MediaStyleNode;
            }
        }
        return type;
    }

    static displayNameForPseudoId(pseudoId)
    {
        // Compatibility (iOS 12.2): CSS.PseudoId did not exist.
        if (!InspectorBackend.Enum.CSS.PseudoId) {
            switch (pseudoId) {
            case 1: // PseudoId.FirstLine
                return WI.unlocalizedString("::first-line");
            case 2: // PseudoId.FirstLetter
                return WI.unlocalizedString("::first-letter");
            case 3: // PseudoId.Marker
                return WI.unlocalizedString("::marker");
            case 4: // PseudoId.Before
                return WI.unlocalizedString("::before");
            case 5: // PseudoId.After
                return WI.unlocalizedString("::after");
            case 6: // PseudoId.Selection
                return WI.unlocalizedString("::selection");
            case 7: // PseudoId.Scrollbar
                return WI.unlocalizedString("::scrollbar");
            case 8: // PseudoId.ScrollbarThumb
                return WI.unlocalizedString("::scrollbar-thumb");
            case 9: // PseudoId.ScrollbarButton
                return WI.unlocalizedString("::scrollbar-button");
            case 10: // PseudoId.ScrollbarTrack
                return WI.unlocalizedString("::scrollbar-track");
            case 11: // PseudoId.ScrollbarTrackPiece
                return WI.unlocalizedString("::scrollbar-track-piece");
            case 12: // PseudoId.ScrollbarCorner
                return WI.unlocalizedString("::scrollbar-corner");
            case 13: // PseudoId.Resizer
                return WI.unlocalizedString("::resizer");

            default:
                console.error("Unknown pseudo id", pseudoId);
                return "";
            }
        }

        switch (pseudoId) {
        case CSSManager.PseudoSelectorNames.FirstLine:
            return WI.unlocalizedString("::first-line");
        case CSSManager.PseudoSelectorNames.FirstLetter:
            return WI.unlocalizedString("::first-letter");
        case CSSManager.PseudoSelectorNames.Highlight:
            return WI.unlocalizedString("::highlight");
        case CSSManager.PseudoSelectorNames.Marker:
            return WI.unlocalizedString("::marker");
        case CSSManager.PseudoSelectorNames.Before:
            return WI.unlocalizedString("::before");
        case CSSManager.PseudoSelectorNames.After:
            return WI.unlocalizedString("::after");
        case CSSManager.PseudoSelectorNames.Selection:
            return WI.unlocalizedString("::selection");
        case CSSManager.PseudoSelectorNames.Scrollbar:
            return WI.unlocalizedString("::scrollbar");
        case CSSManager.PseudoSelectorNames.ScrollbarThumb:
            return WI.unlocalizedString("::scrollbar-thumb");
        case CSSManager.PseudoSelectorNames.ScrollbarButton:
            return WI.unlocalizedString("::scrollbar-button");
        case CSSManager.PseudoSelectorNames.ScrollbarTrack:
            return WI.unlocalizedString("::scrollbar-track");
        case CSSManager.PseudoSelectorNames.ScrollbarTrackPiece:
            return WI.unlocalizedString("::scrollbar-track-piece");
        case CSSManager.PseudoSelectorNames.ScrollbarCorner:
            return WI.unlocalizedString("::scrollbar-corner");
        case CSSManager.PseudoSelectorNames.Resizer:
            return WI.unlocalizedString("::resizer");

        default:
            console.error("Unknown pseudo id", pseudoId);
            return "";
        }
    }

    // Public

    get preferredColorFormat()
    {
        return this._colorFormatSetting.value;
    }

    get styleSheets()
    {
        return Array.from(this._styleSheetIdentifierMap.values());
    }

    get defaultAppearance()
    {
        return this._defaultAppearance;
    }

    get forcedAppearance()
    {
        return this._forcedAppearance;
    }

    set forcedAppearance(name)
    {
        if (!this.canForceAppearance())
            return;

        let protocolName = "";

        switch (name) {
        case WI.CSSManager.Appearance.Light:
            protocolName = InspectorBackend.Enum.Page.Appearance.Light;
            break;

        case WI.CSSManager.Appearance.Dark:
            protocolName = InspectorBackend.Enum.Page.Appearance.Dark;
            break;

        case null:
        case undefined:
        case "":
            protocolName = "";
            break;

        default:
            // Abort for unknown values.
            return;
        }

        this._forcedAppearance = name || null;

        let target = WI.assumingMainTarget();
        target.PageAgent.setForcedAppearance(protocolName).then(() => {
            this.mediaQueryResultChanged();
            this.dispatchEventToListeners(WI.CSSManager.Event.ForcedAppearanceDidChange, {appearance: this._forcedAppearance});
        });
    }

    canForceAppearance()
    {
        return InspectorBackend.hasCommand("Page.setForcedAppearance") && this._defaultAppearance;
    }

    canForcePseudoClasses()
    {
        return InspectorBackend.hasCommand("CSS.forcePseudoState");
    }

    propertyNameHasOtherVendorPrefix(name)
    {
        if (!name || name.length < 4 || name.charAt(0) !== "-")
            return false;

        var match = name.match(/^(?:-moz-|-ms-|-o-|-epub-)/);
        if (!match)
            return false;

        return true;
    }

    propertyValueHasOtherVendorKeyword(value)
    {
        var match = value.match(/(?:-moz-|-ms-|-o-|-epub-)[-\w]+/);
        if (!match)
            return false;

        return true;
    }

    canonicalNameForPropertyName(name)
    {
        if (!name || name.length < 8 || name.charAt(0) !== "-")
            return name;

        var match = name.match(/^(?:-webkit-|-khtml-|-apple-)(.+)/);
        if (!match)
            return name;

        return match[1];
    }

    styleSheetForIdentifier(id)
    {
        let styleSheet = this._styleSheetIdentifierMap.get(id);
        if (styleSheet)
            return styleSheet;

        styleSheet = new WI.CSSStyleSheet(id);
        this._styleSheetIdentifierMap.set(id, styleSheet);
        return styleSheet;
    }

    stylesForNode(node)
    {
        if (node.id in this._nodeStylesMap)
            return this._nodeStylesMap[node.id];

        var styles = new WI.DOMNodeStyles(node);
        this._nodeStylesMap[node.id] = styles;
        return styles;
    }

    inspectorStyleSheetsForFrame(frame)
    {
        return this.styleSheets.filter((styleSheet) => styleSheet.isInspectorStyleSheet() && styleSheet.parentFrame === frame);
    }

    preferredInspectorStyleSheetForFrame(frame, callback)
    {
        var inspectorStyleSheets = this.inspectorStyleSheetsForFrame(frame);
        for (let styleSheet of inspectorStyleSheets) {
            if (styleSheet[WI.CSSManager.PreferredInspectorStyleSheetSymbol]) {
                callback(styleSheet);
                return;
            }
        }

        let target = WI.assumingMainTarget();
        target.CSSAgent.createStyleSheet(frame.id, function(error, styleSheetId) {
            if (error || !styleSheetId) {
                WI.reportInternalError(error || styleSheetId);
                return;
            }

            const url = null;
            let styleSheet = WI.cssManager.styleSheetForIdentifier(styleSheetId);
            styleSheet.updateInfo(url, frame, styleSheet.origin, styleSheet.isInlineStyleTag(), styleSheet.startLineNumber, styleSheet.startColumnNumber);
            styleSheet[WI.CSSManager.PreferredInspectorStyleSheetSymbol] = true;
            callback(styleSheet);
        });
    }

    mediaTypeChanged()
    {
        // Act the same as if media queries changed.
        this.mediaQueryResultChanged();
    }

    get modifiedStyles()
    {
        return Array.from(this._modifiedStyles.values());
    }

    addModifiedStyle(style)
    {
        this._modifiedStyles.set(style.stringId, style);
    }

    getModifiedStyle(style)
    {
        return this._modifiedStyles.get(style.stringId);
    }

    removeModifiedStyle(style)
    {
        this._modifiedStyles.delete(style.stringId);
    }

    // PageObserver

    defaultAppearanceDidChange(protocolName)
    {
        let appearance = null;

        switch (protocolName) {
        case InspectorBackend.Enum.Page.Appearance.Light:
            appearance = WI.CSSManager.Appearance.Light;
            break;

        case InspectorBackend.Enum.Page.Appearance.Dark:
            appearance = WI.CSSManager.Appearance.Dark;
            break;

        default:
            console.error("Unknown default appearance name:", protocolName);
            break;
        }

        this._defaultAppearance = appearance;

        this.mediaQueryResultChanged();

        this.dispatchEventToListeners(WI.CSSManager.Event.DefaultAppearanceDidChange, {appearance});
    }

    // CSSObserver

    mediaQueryResultChanged()
    {
        for (var key in this._nodeStylesMap)
            this._nodeStylesMap[key].mediaQueryResultDidChange();
    }

    styleSheetChanged(styleSheetIdentifier)
    {
        var styleSheet = this.styleSheetForIdentifier(styleSheetIdentifier);
        console.assert(styleSheet);

        // Do not observe inline styles
        if (styleSheet.isInlineStyleAttributeStyleSheet())
            return;

        if (!styleSheet.noteContentDidChange())
            return;

        this._updateResourceContent(styleSheet);
    }

    styleSheetAdded(styleSheetInfo)
    {
        console.assert(!this._styleSheetIdentifierMap.has(styleSheetInfo.styleSheetId), "Attempted to add a CSSStyleSheet but identifier was already in use");
        let styleSheet = this.styleSheetForIdentifier(styleSheetInfo.styleSheetId);
        let parentFrame = WI.networkManager.frameForIdentifier(styleSheetInfo.frameId);
        let origin = WI.CSSManager.protocolStyleSheetOriginToEnum(styleSheetInfo.origin);
        styleSheet.updateInfo(styleSheetInfo.sourceURL, parentFrame, origin, styleSheetInfo.isInline, styleSheetInfo.startLine, styleSheetInfo.startColumn);

        this.dispatchEventToListeners(WI.CSSManager.Event.StyleSheetAdded, {styleSheet});
    }

    styleSheetRemoved(styleSheetIdentifier)
    {
        let styleSheet = this._styleSheetIdentifierMap.get(styleSheetIdentifier);
        console.assert(styleSheet, "Attempted to remove a CSSStyleSheet that was not tracked");
        if (!styleSheet)
            return;

        this._styleSheetIdentifierMap.delete(styleSheetIdentifier);

        this.dispatchEventToListeners(WI.CSSManager.Event.StyleSheetRemoved, {styleSheet});
    }

    // Private

    _nodePseudoClassesDidChange(event)
    {
        var node = event.target;

        for (var key in this._nodeStylesMap) {
            var nodeStyles = this._nodeStylesMap[key];
            if (nodeStyles.node !== node && !nodeStyles.node.isDescendant(node))
                continue;
            nodeStyles.pseudoClassesDidChange(node);
        }
    }

    _nodeAttributesDidChange(event)
    {
        var node = event.target;

        for (var key in this._nodeStylesMap) {
            var nodeStyles = this._nodeStylesMap[key];
            if (nodeStyles.node !== node && !nodeStyles.node.isDescendant(node))
                continue;
            nodeStyles.attributeDidChange(node, event.data.name);
        }
    }

    _mainResourceDidChange(event)
    {
        console.assert(event.target instanceof WI.Frame);

        if (!event.target.isMainFrame())
            return;

        // Clear our maps when the main frame navigates.

        this._styleSheetIdentifierMap.clear();
        this._styleSheetFrameURLMap.clear();
        this._modifiedStyles.clear();
        this._forcedAppearance = null;

        this._nodeStylesMap = {};
    }

    _resourceAdded(event)
    {
        console.assert(event.target instanceof WI.Frame);

        var resource = event.data.resource;
        console.assert(resource);

        if (resource.type !== WI.Resource.Type.StyleSheet)
            return;

        this._clearStyleSheetsForResource(resource);
    }

    _resourceTypeDidChange(event)
    {
        console.assert(event.target instanceof WI.Resource);

        var resource = event.target;
        if (resource.type !== WI.Resource.Type.StyleSheet)
            return;

        this._clearStyleSheetsForResource(resource);
    }

    _clearStyleSheetsForResource(resource)
    {
        // Clear known stylesheets for this URL and frame. This will cause the style sheets to
        // be updated next time _fetchInfoForAllStyleSheets is called.
        this._styleSheetIdentifierMap.delete(this._frameURLMapKey(resource.parentFrame, resource.url));
    }

    _frameURLMapKey(frame, url)
    {
        return frame.id + ":" + url;
    }

    _lookupStyleSheetForResource(resource, callback)
    {
        this._lookupStyleSheet(resource.parentFrame, resource.url, callback);
    }

    _lookupStyleSheet(frame, url, callback)
    {
        console.assert(frame instanceof WI.Frame);

        let key = this._frameURLMapKey(frame, url);

        function styleSheetsFetched()
        {
            callback(this._styleSheetFrameURLMap.get(key) || null);
        }

        let styleSheet = this._styleSheetFrameURLMap.get(key) || null;
        if (styleSheet)
            callback(styleSheet);
        else
            this._fetchInfoForAllStyleSheets(styleSheetsFetched.bind(this));
    }

    _fetchInfoForAllStyleSheets(callback)
    {
        console.assert(typeof callback === "function");

        function processStyleSheets(error, styleSheets)
        {
            this._styleSheetFrameURLMap.clear();

            if (error) {
                callback();
                return;
            }

            for (let styleSheetInfo of styleSheets) {
                let parentFrame = WI.networkManager.frameForIdentifier(styleSheetInfo.frameId);
                let origin = WI.CSSManager.protocolStyleSheetOriginToEnum(styleSheetInfo.origin);

                let styleSheet = this.styleSheetForIdentifier(styleSheetInfo.styleSheetId);
                styleSheet.updateInfo(styleSheetInfo.sourceURL, parentFrame, origin, styleSheetInfo.isInline, styleSheetInfo.startLine, styleSheetInfo.startColumn);

                let key = this._frameURLMapKey(parentFrame, styleSheetInfo.sourceURL);
                this._styleSheetFrameURLMap.set(key, styleSheet);
            }

            callback();
        }

        let target = WI.assumingMainTarget();
        target.CSSAgent.getAllStyleSheets(processStyleSheets.bind(this));
    }

    _resourceContentDidChange(event)
    {
        var resource = event.target;
        if (resource === this._ignoreResourceContentDidChangeEventForResource)
            return;

        // Ignore changes to resource overrides, those are not live on the page.
        if (resource.isLocalResourceOverride)
            return;

        // Ignore if it isn't a CSS style sheet.
        if (resource.type !== WI.Resource.Type.StyleSheet || resource.syntheticMIMEType !== "text/css")
            return;

        function applyStyleSheetChanges()
        {
            function styleSheetFound(styleSheet)
            {
                resource.__pendingChangeTimeout.cancel();

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

                // To prevent updating a TextEditor's content while the user is typing in it we want to
                // ignore the next _updateResourceContent call.
                resource.__ignoreNextUpdateResourceContent = true;

                let revision = styleSheet.editableRevision;
                revision.updateRevisionContent(resource.content);
            }

            this._lookupStyleSheetForResource(resource, styleSheetFound.bind(this));
        }

        if (!resource.__pendingChangeTimeout)
            resource.__pendingChangeTimeout = new Throttler(applyStyleSheetChanges.bind(this), 100);
        resource.__pendingChangeTimeout.fire();
    }

    _updateResourceContent(styleSheet)
    {
        console.assert(styleSheet);

        function fetchedStyleSheetContent(parameters)
        {
            styleSheet.__pendingChangeTimeout.cancel();

            let representedObject = parameters.sourceCode;

            console.assert(representedObject.url);
            if (!representedObject.url)
                return;

            if (!styleSheet.isInspectorStyleSheet()) {
                // Only try to update stylesheet resources. Other resources, like documents, can contain
                // multiple stylesheets and we don't have the source ranges to update those.
                representedObject = representedObject.parentFrame.resourcesForURL(representedObject.url).find((resource) => resource.type === WI.Resource.Type.StyleSheet);
                if (!representedObject)
                    return;
            }

            if (representedObject.__ignoreNextUpdateResourceContent) {
                representedObject.__ignoreNextUpdateResourceContent = false;
                return;
            }

            this._ignoreResourceContentDidChangeEventForResource = representedObject;

            let revision = representedObject.editableRevision;
            if (styleSheet.isInspectorStyleSheet()) {
                revision.updateRevisionContent(representedObject.content);
                styleSheet.dispatchEventToListeners(WI.SourceCode.Event.ContentDidChange);
            } else
                revision.updateRevisionContent(parameters.content);

            this._ignoreResourceContentDidChangeEventForResource = null;
        }

        function styleSheetReady()
        {
            styleSheet.requestContent().then(fetchedStyleSheetContent.bind(this));
        }

        function applyStyleSheetChanges()
        {
            if (styleSheet.url)
                styleSheetReady.call(this);
            else
                this._fetchInfoForAllStyleSheets(styleSheetReady.bind(this));
        }

        if (!styleSheet.__pendingChangeTimeout)
            styleSheet.__pendingChangeTimeout = new Throttler(applyStyleSheetChanges.bind(this), 100);
        styleSheet.__pendingChangeTimeout.fire();
    }
};

WI.CSSManager.Event = {
    StyleSheetAdded: "css-manager-style-sheet-added",
    StyleSheetRemoved: "css-manager-style-sheet-removed",
    DefaultAppearanceDidChange: "css-manager-default-appearance-did-change",
    ForcedAppearanceDidChange: "css-manager-forced-appearance-did-change",
};

WI.CSSManager.Appearance = {
    Light: Symbol("light"),
    Dark: Symbol("dark"),
};

WI.CSSManager.PseudoSelectorNames = {
    After: "after",
    Before: "before",
    FirstLetter: "first-letter",
    FirstLine: "first-line",
    Highlight: "highlight",
    Marker: "marker",
    Resizer: "resizer",
    Scrollbar: "scrollbar",
    ScrollbarButton: "scrollbar-button",
    ScrollbarCorner: "scrollbar-corner",
    ScrollbarThumb: "scrollbar-thumb",
    ScrollbarTrack: "scrollbar-track",
    ScrollbarTrackPiece: "scrollbar-track-piece",
    Selection: "selection",
};

WI.CSSManager.PseudoElementNames = ["before", "after"];
WI.CSSManager.ForceablePseudoClasses = ["active", "focus", "hover", "visited"];
WI.CSSManager.PreferredInspectorStyleSheetSymbol = Symbol("css-manager-preferred-inspector-style-sheet");
