/*
 * Copyright (C) 2013, 2015 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.NavigationSidebarPanel = class NavigationSidebarPanel extends WI.SidebarPanel
{
    constructor(identifier, displayName, shouldAutoPruneStaleTopLevelResourceTreeElements, wantsTopOverflowShadow)
    {
        super(identifier, displayName);

        this.element.classList.add("navigation");

        this._updateContentOverflowShadowVisibilityDebouncer = new Debouncer(() => {
            this._updateContentOverflowShadowVisibility();
        });
        this._boundUpdateContentOverflowShadowVisibilitySoon = (event) => {
            this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
        };

        this.contentView.element.addEventListener("scroll", this._boundUpdateContentOverflowShadowVisibilitySoon);

        this._contentTreeOutlineGroup = new WI.TreeOutlineGroup;
        this._contentTreeOutline = this.createContentTreeOutline();

        this._filterBar = new WI.FilterBar;
        this._filterBar.addEventListener(WI.FilterBar.Event.FilterDidChange, this._filterDidChange, this);
        this.element.appendChild(this._filterBar.element);

        this._bottomOverflowShadowElement = document.createElement("div");
        this._bottomOverflowShadowElement.className = WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName;
        this.element.appendChild(this._bottomOverflowShadowElement);

        if (wantsTopOverflowShadow) {
            this._topOverflowShadowElement = this.element.appendChild(document.createElement("div"));
            this._topOverflowShadowElement.classList.add(WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName, "top");
        }

        window.addEventListener("resize", this._boundUpdateContentOverflowShadowVisibilitySoon);

        this._filtersSetting = new WI.Setting(identifier + "-navigation-sidebar-filters", {});
        this._filterBar.filters = this._filtersSetting.value;

        this._emptyContentPlaceholderElements = new Map;
        this._emptyFilterResults = new Set;

        this._shouldAutoPruneStaleTopLevelResourceTreeElements = shouldAutoPruneStaleTopLevelResourceTreeElements || false;

        if (this._shouldAutoPruneStaleTopLevelResourceTreeElements) {
            WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._checkForStaleResources, this);
            WI.Frame.addEventListener(WI.Frame.Event.ChildFrameWasRemoved, this._checkForStaleResources, this);
            WI.Frame.addEventListener(WI.Frame.Event.ResourceWasRemoved, this._checkForStaleResources, this);
        }

        this._pendingViewStateCookie = null;
        this._restoringState = false;
    }

    // Public

    get filterBar() { return this._filterBar; }
    get hasActiveFilters() { return this._filterBar.hasActiveFilters(); }

    closed()
    {
        window.removeEventListener("resize", this._boundUpdateContentOverflowShadowVisibilitySoon);
        WI.Frame.removeEventListener(null, null, this);
    }

    get contentBrowser()
    {
        return this._contentBrowser;
    }

    set contentBrowser(contentBrowser)
    {
        this._contentBrowser = contentBrowser || null;
    }

    get contentTreeOutline()
    {
        return this._contentTreeOutline;
    }

    get contentTreeOutlines()
    {
        return Array.from(this._contentTreeOutlineGroup);
    }

    get currentRepresentedObject()
    {
        if (!this._contentBrowser)
            return null;

        return this._contentBrowser.currentRepresentedObjects[0] || null;
    }

    get restoringState()
    {
        return this._restoringState;
    }

    cancelRestoringState()
    {
        this._pendingViewStateCookie = null;
        if (!this._finalAttemptToRestoreViewStateTimeout)
            return;

        clearTimeout(this._finalAttemptToRestoreViewStateTimeout);
        this._finalAttemptToRestoreViewStateTimeout = undefined;
    }

    createContentTreeOutline({ignoreCookieRestoration, suppressFiltering} = {})
    {
        let contentTreeOutline = new WI.TreeOutline;
        contentTreeOutline.allowsRepeatSelection = true;
        contentTreeOutline.element.classList.add(WI.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName);

        this._contentTreeOutlineGroup.add(contentTreeOutline);

        this.contentView.element.appendChild(contentTreeOutline.element);

        if (!suppressFiltering) {
            contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._treeElementAddedOrChanged, this);
            contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementDidChange, this._treeElementAddedOrChanged, this);
            contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange, this);
        }

        contentTreeOutline[WI.NavigationSidebarPanel.IgnoreCookieRestoration] = ignoreCookieRestoration;
        contentTreeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol] = suppressFiltering;

        return contentTreeOutline;
    }

    suppressFilteringOnTreeElements(treeElements)
    {
        console.assert(Array.isArray(treeElements), "TreeElements should be an array.");

        for (let treeElement of treeElements)
            treeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol] = true;

        this.updateFilter();
    }

    treeElementForRepresentedObject(representedObject)
    {
        let treeElement = null;
        for (let treeOutline of this.contentTreeOutlines) {
            treeElement = treeOutline.getCachedTreeElement(representedObject);
            if (treeElement)
                break;
        }

        return treeElement;
    }

    showDefaultContentView()
    {
        // Implemented by subclasses if needed to show a content view when no existing tree element is selected.
    }

    showDefaultContentViewForTreeElement(treeElement)
    {
        console.assert(treeElement);
        console.assert(treeElement.representedObject);
        if (!treeElement || !treeElement.representedObject)
            return false;

        // FIXME: <https://webkit.org/b/153634> Web Inspector: some background tabs think they are the foreground tab and do unnecessary work
        // Do not steal a content view if we are not the active tab/sidebar.
        if (!this.selected) {
            let contentView = this.contentBrowser.contentViewForRepresentedObject(treeElement.representedObject);
            if (contentView && contentView.parentContainer && contentView.parentContainer !== this.contentBrowser.contentViewContainer)
                return false;

            // contentView.parentContainer may be null. Check for selected tab, too.
            let selectedTabContentView = WI.tabBrowser.selectedTabContentView;
            if (selectedTabContentView && selectedTabContentView.contentBrowser !== this.contentBrowser)
                return false;
        }

        let contentView = this.contentBrowser.showContentViewForRepresentedObject(treeElement.representedObject);
        if (!contentView)
            return false;

        treeElement.revealAndSelect(true, false, true);
        return true;
    }

    canShowRepresentedObject(representedObject)
    {
        let selectedTabContentView = WI.tabBrowser.selectedTabContentView;
        console.assert(selectedTabContentView instanceof WI.TabContentView, "Missing TabContentView for NavigationSidebarPanel.");
        return selectedTabContentView && selectedTabContentView.canShowRepresentedObject(representedObject);
    }

    saveStateToCookie(cookie)
    {
        console.assert(cookie);

        if (!this._contentBrowser)
            return;

        let representedObject = this.currentRepresentedObject;
        if (!representedObject)
            return;

        cookie[WI.TypeIdentifierCookieKey] = representedObject.constructor.TypeIdentifier;

        if (representedObject.saveIdentityToCookie) {
            representedObject.saveIdentityToCookie(cookie);
            return;
        }

        console.error("NavigationSidebarPanel representedObject is missing a saveIdentityToCookie implementation.", representedObject);
    }

    // This can be supplemented by subclasses that admit a simpler strategy for static tree elements.
    restoreStateFromCookie(cookie, relaxedMatchDelay)
    {
        this._pendingViewStateCookie = cookie;
        this._restoringState = true;

        // Check if any existing tree elements in any outline match the cookie.
        this._checkOutlinesForPendingViewStateCookie();

        if (this._finalAttemptToRestoreViewStateTimeout)
            clearTimeout(this._finalAttemptToRestoreViewStateTimeout);

        if (relaxedMatchDelay === 0)
            return;

        function finalAttemptToRestoreViewStateFromCookie()
        {
            this._finalAttemptToRestoreViewStateTimeout = undefined;

            this._checkOutlinesForPendingViewStateCookie(true);

            this._pendingViewStateCookie = null;
            this._restoringState = false;
        }

        // If the specific tree element wasn't found, we may need to wait for the resources
        // to be registered. We try one last time (match type only) after an arbitrary amount of timeout.
        this._finalAttemptToRestoreViewStateTimeout = setTimeout(finalAttemptToRestoreViewStateFromCookie.bind(this), relaxedMatchDelay);
    }

    showEmptyContentPlaceholder(message, treeOutline)
    {
        console.assert(message);

        treeOutline = treeOutline || this._contentTreeOutline;

        let emptyContentPlaceholderElement = this._emptyContentPlaceholderElements.get(treeOutline);
        if (emptyContentPlaceholderElement)
            emptyContentPlaceholderElement.remove();

        emptyContentPlaceholderElement = message instanceof Node ? message : WI.createMessageTextView(message);
        this._emptyContentPlaceholderElements.set(treeOutline, emptyContentPlaceholderElement);

        let emptyContentPlaceholderParentElement = treeOutline.element.parentNode;
        emptyContentPlaceholderParentElement.appendChild(emptyContentPlaceholderElement);

        this._updateContentOverflowShadowVisibilityDebouncer.force();

        return emptyContentPlaceholderElement;
    }

    hideEmptyContentPlaceholder(treeOutline)
    {
        treeOutline = treeOutline || this._contentTreeOutline;

        let emptyContentPlaceholderElement = this._emptyContentPlaceholderElements.get(treeOutline);
        if (!emptyContentPlaceholderElement || !emptyContentPlaceholderElement.parentNode)
            return;

        emptyContentPlaceholderElement.remove();
        this._emptyContentPlaceholderElements.delete(treeOutline);

        this._updateContentOverflowShadowVisibilityDebouncer.force();
    }

    updateEmptyContentPlaceholder(message, treeOutline)
    {
        treeOutline = treeOutline || this._contentTreeOutline;

        if (!treeOutline.children.length) {
            // No tree elements, so no results.
            this.showEmptyContentPlaceholder(message, treeOutline);
        } else if (!this._emptyFilterResults.has(treeOutline)) {
            // There are tree elements, and not all of them are hidden by the filter.
            this.hideEmptyContentPlaceholder(treeOutline);
        }
    }

    updateFilter()
    {
        let selectedTreeElement;
        for (let treeOutline of this.contentTreeOutlines) {
            if (treeOutline.hidden || treeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol])
                continue;

            selectedTreeElement = treeOutline.selectedTreeElement;
            if (selectedTreeElement)
                break;
        }

        let filters = this._filterBar.filters;
        this._textFilterRegex = simpleGlobStringToRegExp(filters.text, "i");
        this._filtersSetting.value = filters;
        this._filterFunctions = filters.functions;

        // Don't populate if we don't have any active filters.
        // We only need to populate when a filter needs to reveal.
        let dontPopulate = !this._filterBar.hasActiveFilters() && !this.shouldFilterPopulate();

        // Update all trees that allow filtering.
        for (let treeOutline of this.contentTreeOutlines) {
            if (treeOutline.hidden || treeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol])
                continue;

            let currentTreeElement = treeOutline.children[0];
            while (currentTreeElement && !currentTreeElement.root) {
                if (!currentTreeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol]) {
                    const currentTreeElementWasHidden = currentTreeElement.hidden;
                    this.applyFiltersToTreeElement(currentTreeElement);
                    if (currentTreeElementWasHidden !== currentTreeElement.hidden)
                        this._treeElementWasFiltered(currentTreeElement);
                }

                currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, dontPopulate);
            }
        }

        this._checkForEmptyFilterResults();
        this._updateContentOverflowShadowVisibilityDebouncer.force();
    }

    resetFilter()
    {
        this._filterBar.clear();
    }

    shouldFilterPopulate()
    {
        // Overridden by subclasses if needed.
        return this.hasCustomFilters();
    }

    hasCustomFilters()
    {
        // Implemented by subclasses if needed.
        return false;
    }

    matchTreeElementAgainstCustomFilters(treeElement)
    {
        // Implemented by subclasses if needed.
        return true;
    }

    matchTreeElementAgainstFilterFunctions(treeElement)
    {
        if (!this._filterFunctions || !this._filterFunctions.length)
            return true;

        for (var filterFunction of this._filterFunctions) {
            if (filterFunction(treeElement))
                return true;
        }

        return false;
    }

    applyFiltersToTreeElement(treeElement)
    {
        if (!this._filterBar.hasActiveFilters() && !this.hasCustomFilters()) {
            // No filters, so make everything visible.
            treeElement.hidden = false;

            // If this tree element was expanded during filtering, collapse it again.
            if (treeElement.expanded && treeElement[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) {
                treeElement[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol] = false;
                treeElement.collapse();
            }

            return;
        }

        var filterableData = treeElement.filterableData || {};

        var flags = {expandTreeElement: false};
        var filterRegex = this._textFilterRegex;

        function matchTextFilter(inputs)
        {
            if (!inputs || !filterRegex)
                return true;

            console.assert(inputs instanceof Array, "filterableData.text should be an array of text inputs");

            // Loop over all the inputs and try to match them.
            for (var input of inputs) {
                if (!input)
                    continue;
                if (filterRegex.test(input)) {
                    flags.expandTreeElement = true;
                    return true;
                }
            }

            // No inputs matched.
            return false;
        }

        function makeVisible()
        {
            // Make this element visible.
            treeElement.hidden = false;

            // Make the ancestors visible and expand them.
            var currentAncestor = treeElement.parent;
            while (currentAncestor && !currentAncestor.root) {
                currentAncestor.hidden = false;

                // Only expand if the built-in filters matched, not custom filters.
                if (flags.expandTreeElement && !currentAncestor.expanded) {
                    currentAncestor.__wasExpandedDuringFiltering = true;
                    currentAncestor.expand();
                }

                currentAncestor = currentAncestor.parent;
            }
        }

        let suppressFiltering = treeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol];

        if (suppressFiltering || (matchTextFilter(filterableData.text) && this.matchTreeElementAgainstFilterFunctions(treeElement, flags) && this.matchTreeElementAgainstCustomFilters(treeElement, flags))) {
            // Make this element visible since it matches.
            makeVisible();

            // If this tree element didn't match a built-in filter and was expanded earlier during filtering, collapse it again.
            if (!flags.expandTreeElement && treeElement.expanded && treeElement[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) {
                treeElement[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol] = false;
                treeElement.collapse();
            }

            return;
        }

        // Make this element invisible since it does not match.
        treeElement.hidden = true;
    }

    shown()
    {
        super.shown();

        this._updateContentOverflowShadowVisibilityDebouncer.force();
    }

    // Protected

    pruneStaleResourceTreeElements()
    {
        if (this._checkForStaleResourcesTimeoutIdentifier) {
            clearTimeout(this._checkForStaleResourcesTimeoutIdentifier);
            this._checkForStaleResourcesTimeoutIdentifier = undefined;
        }

        for (let contentTreeOutline of this.contentTreeOutlines) {
            // Check all the ResourceTreeElements at the top level to make sure their Resource still has a parentFrame in the frame hierarchy.
            // If the parentFrame is no longer in the frame hierarchy we know it was removed due to a navigation or some other page change and
            // we should remove the issues for that resource.
            for (let i = contentTreeOutline.children.length - 1; i >= 0; --i) {
                let treeElement = contentTreeOutline.children[i];
                if (!(treeElement instanceof WI.ResourceTreeElement))
                    continue;

                // Local Overrides are never stale resources.
                let resource = treeElement.resource;
                if (resource.isLocalResourceOverride)
                    continue;

                if (!resource.parentFrame || resource.parentFrame.isDetached())
                    contentTreeOutline.removeChildAtIndex(i, true, true);
            }
        }
    }

    // Private

    _updateContentOverflowShadowVisibility()
    {
        if (!this.visible)
            return;

        let scrollHeight = this.contentView.element.scrollHeight;
        let offsetHeight = this.contentView.element.offsetHeight;

        if (scrollHeight < offsetHeight) {
            if (this._topOverflowShadowElement)
                this._topOverflowShadowElement.style.opacity = 0;
            this._bottomOverflowShadowElement.style.opacity = 0;
            return;
        }

        let edgeThreshold = 1;
        let scrollTop = this.contentView.element.scrollTop;

        let topCoverage = Math.min(scrollTop, edgeThreshold);
        let bottomCoverage = Math.max(0, (offsetHeight + scrollTop) - (scrollHeight - edgeThreshold));

        if (this._topOverflowShadowElement)
            this._topOverflowShadowElement.style.opacity = (topCoverage / edgeThreshold).toFixed(1);
        this._bottomOverflowShadowElement.style.opacity = (1 - (bottomCoverage / edgeThreshold)).toFixed(1);
    }

    _checkForEmptyFilterResults()
    {
        function checkTreeOutlineForEmptyFilterResults(treeOutline)
        {
            // No tree elements, so don't touch the empty content placeholder.
            if (!treeOutline.children.length)
                return;

            // Iterate over all the top level tree elements. If any filterable elements are visible, return early.
            let filterableTreeElementFound = false;
            let unfilteredTreeElementFound = false;
            let currentTreeElement = treeOutline.children[0];
            while (currentTreeElement) {
                let suppressFilteringForTreeElement = currentTreeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol];
                if (!suppressFilteringForTreeElement) {
                    filterableTreeElementFound = true;

                    if (!currentTreeElement.hidden) {
                        unfilteredTreeElementFound = true;
                        break;
                    }
                }

                currentTreeElement = currentTreeElement.nextSibling;
            }

            if (unfilteredTreeElementFound || !filterableTreeElementFound) {
                this.hideEmptyContentPlaceholder(treeOutline);
                this._emptyFilterResults.delete(treeOutline);
                return;
            }

            let message = WI.createMessageTextView(WI.UIString("No Filter Results"));

            let buttonElement = message.appendChild(document.createElement("button"));
            buttonElement.textContent = WI.UIString("Clear Filters");
            buttonElement.addEventListener("click", () => {
                this.resetFilter();
            });

            // All top level tree elements are hidden, so filtering hid everything. Show a message.
            this.showEmptyContentPlaceholder(message, treeOutline);
            this._emptyFilterResults.add(treeOutline);
        }

        for (let treeOutline of this.contentTreeOutlines) {
            if (treeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol])
                continue;

            checkTreeOutlineForEmptyFilterResults.call(this, treeOutline);
        }
    }

    _filterDidChange()
    {
        this.updateFilter();
    }

    _treeElementAddedOrChanged(event)
    {
        // Don't populate if we don't have any active filters.
        // We only need to populate when a filter needs to reveal.
        var dontPopulate = !this._filterBar.hasActiveFilters() && !this.shouldFilterPopulate();

        // Apply the filters to the tree element and its descendants.
        let treeElement = event.data.element;
        let currentTreeElement = treeElement;
        while (currentTreeElement && !currentTreeElement.root) {
            if (!currentTreeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol]) {
                const currentTreeElementWasHidden = currentTreeElement.hidden;
                this.applyFiltersToTreeElement(currentTreeElement);
                if (currentTreeElementWasHidden !== currentTreeElement.hidden)
                    this._treeElementWasFiltered(currentTreeElement);
            }

            currentTreeElement = currentTreeElement.traverseNextTreeElement(false, treeElement, dontPopulate);
        }

        this._checkForEmptyFilterResults();

        if (this.visible)
            this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);

        if (this.selected && !treeElement.treeOutline[WI.NavigationSidebarPanel.IgnoreCookieRestoration])
            this._checkElementsForPendingViewStateCookie([treeElement]);
    }

    _treeElementDisclosureDidChange(event)
    {
        this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
    }

    _checkForStaleResourcesIfNeeded()
    {
        if (!this._checkForStaleResourcesTimeoutIdentifier || !this._shouldAutoPruneStaleTopLevelResourceTreeElements)
            return;
        this.pruneStaleResourceTreeElements();
    }

    _checkForStaleResources(event)
    {
        console.assert(this._shouldAutoPruneStaleTopLevelResourceTreeElements);

        if (this._checkForStaleResourcesTimeoutIdentifier)
            return;

        // Check on a delay to coalesce multiple calls to _checkForStaleResources.
        this._checkForStaleResourcesTimeoutIdentifier = setTimeout(this.pruneStaleResourceTreeElements.bind(this));
    }

    _isTreeElementWithoutRepresentedObject(treeElement)
    {
        return treeElement instanceof WI.FolderTreeElement
            || treeElement instanceof WI.DatabaseHostTreeElement
            || treeElement instanceof WI.IndexedDatabaseHostTreeElement
            || treeElement instanceof WI.ApplicationCacheManifestTreeElement
            || treeElement instanceof WI.ThreadTreeElement
            || treeElement instanceof WI.IdleTreeElement
            || treeElement instanceof WI.DOMBreakpointTreeElement
            || treeElement instanceof WI.EventBreakpointTreeElement
            || treeElement instanceof WI.URLBreakpointTreeElement
            || treeElement instanceof WI.CSSStyleSheetTreeElement
            || typeof treeElement.representedObject === "string"
            || treeElement.representedObject instanceof String;
    }

    _checkOutlinesForPendingViewStateCookie(matchTypeOnly)
    {
        if (!this._pendingViewStateCookie)
            return;

        this._checkForStaleResourcesIfNeeded();

        var visibleTreeElements = [];
        this.contentTreeOutlines.forEach(function(outline) {
            if (outline[WI.NavigationSidebarPanel.IgnoreCookieRestoration])
                return;

            var currentTreeElement = outline.hasChildren ? outline.children[0] : null;
            while (currentTreeElement) {
                visibleTreeElements.push(currentTreeElement);
                currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, false);
            }
        });

        this._checkElementsForPendingViewStateCookie(visibleTreeElements, matchTypeOnly);
    }

    _checkElementsForPendingViewStateCookie(treeElements, matchTypeOnly)
    {
        if (!this._pendingViewStateCookie)
            return;

        var cookie = this._pendingViewStateCookie;

        function treeElementMatchesCookie(treeElement)
        {
            if (this._isTreeElementWithoutRepresentedObject(treeElement))
                return false;

            var representedObject = treeElement.representedObject;
            if (!representedObject)
                return false;

            var typeIdentifier = cookie[WI.TypeIdentifierCookieKey];
            if (typeIdentifier !== representedObject.constructor.TypeIdentifier)
                return false;

            if (matchTypeOnly)
                return true;

            var candidateObjectCookie = {};
            if (representedObject.saveIdentityToCookie)
                representedObject.saveIdentityToCookie(candidateObjectCookie);

            var candidateCookieKeys = Object.keys(candidateObjectCookie);
            return candidateCookieKeys.length && candidateCookieKeys.every((key) => candidateObjectCookie[key] === cookie[key]);
        }

        var matchedElement = null;
        treeElements.some((element) => {
            if (treeElementMatchesCookie.call(this, element)) {
                matchedElement = element;
                return true;
            }
            return false;
        });

        if (matchedElement) {
            let didShowContentView = this.showDefaultContentViewForTreeElement(matchedElement);
            if (!didShowContentView)
                return;

            this._pendingViewStateCookie = null;

            // Delay clearing the restoringState flag until the next runloop so listeners
            // checking for it in this runloop still know state was being restored.
            setTimeout(() => {
                this._restoringState = false;
            }, 0);

            if (this._finalAttemptToRestoreViewStateTimeout) {
                clearTimeout(this._finalAttemptToRestoreViewStateTimeout);
                this._finalAttemptToRestoreViewStateTimeout = undefined;
            }
        }
    }

    _treeElementWasFiltered(treeElement)
    {
        if (treeElement.selected || treeElement.hidden)
            return;

        let representedObject = this.currentRepresentedObject;
        if (!representedObject || treeElement.representedObject !== representedObject)
            return;

        const omitFocus = true;
        const selectedByUser = false;
        const suppressNotification = true;
        treeElement.revealAndSelect(omitFocus, selectedByUser, suppressNotification);
    }
};

WI.NavigationSidebarPanel.IgnoreCookieRestoration = Symbol("ignore-cookie-restoration");
WI.NavigationSidebarPanel.SuppressFilteringSymbol = Symbol("suppress-filtering");
WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering");

WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName = "overflow-shadow";
WI.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName = "navigation-sidebar-panel-content-tree-outline";
