/*
 * Copyright (C) 2012 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

/**
 * @constructor
 * @extends {WebInspector.DialogDelegate}
 * @implements {WebInspector.ViewportControl.Provider}
 * @param {!WebInspector.SelectionDialogContentProvider} delegate
 */
WebInspector.FilteredItemSelectionDialog = function(delegate)
{
    WebInspector.DialogDelegate.call(this);

    this.element.className = "filtered-item-list-dialog";
    this.element.addEventListener("keydown", this._onKeyDown.bind(this), false);
    this.element.appendChild(WebInspector.Widget.createStyleElement("sources/filteredItemSelectionDialog.css"));

    this._promptElement = this.element.createChild("input", "monospace");
    this._promptElement.addEventListener("input", this._onInput.bind(this), false);
    this._promptElement.type = "text";
    this._promptElement.setAttribute("spellcheck", "false");

    this._filteredItems = [];
    this._viewportControl = new WebInspector.ViewportControl(this);
    this._itemElementsContainer = this._viewportControl.element;
    this._itemElementsContainer.classList.add("container");
    this._itemElementsContainer.classList.add("monospace");
    this._itemElementsContainer.addEventListener("click", this._onClick.bind(this), false);
    this.element.appendChild(this._itemElementsContainer);

    this._delegate = delegate;
    this._delegate.setRefreshCallback(this._itemsLoaded.bind(this));
    this._itemsLoaded();
}

WebInspector.FilteredItemSelectionDialog.prototype = {
    /**
     * @override
     * @param {!Element} element
     * @param {!Element} container
     */
    position: function(element, container)
    {
        const shadow = 10;
        const shadowPadding = 20; // shadow + padding
        var preferredWidth = Math.max(container.offsetWidth * 2 / 3, 500);
        var width = Math.min(preferredWidth, container.offsetWidth - 2 * shadowPadding);
        var preferredHeight = Math.max(container.offsetHeight * 2 / 3, 204);
        var height = Math.min(preferredHeight, container.offsetHeight - 2 * shadowPadding);

        this.element.style.width = width + "px";
        var box = container.boxInWindow(window);
        var positionX = Math.max((box.width - width - 2 * shadowPadding) / 2, shadow);
        positionX = Math.max(shadow, Math.min(container.offsetWidth - width - 2 * shadowPadding, positionX));
        var positionY = Math.max((box.height - height - 2 * shadowPadding) / 2, shadow);
        positionY = Math.max(shadow, Math.min(container.offsetHeight - height - 2 * shadowPadding, positionY));
        element.positionAt(positionX, positionY, container);
        this._dialogHeight = height;

        this._updateShowMatchingItems();
        this._viewportControl.refresh();
    },

    focus: function()
    {
        WebInspector.setCurrentFocusElement(this._promptElement);
        if (this._filteredItems.length && this._viewportControl.lastVisibleIndex() === -1)
            this._viewportControl.refresh();
    },

    willHide: function()
    {
        if (this._isHiding)
            return;
        this._isHiding = true;
        this._delegate.dispose();
        if (this._filterTimer)
            clearTimeout(this._filterTimer);
    },

    renderAsTwoRows: function()
    {
        this._renderAsTwoRows = true;
    },

    onEnter: function()
    {
        if (!this._delegate.itemCount())
            return;
        var selectedIndex = this._shouldShowMatchingItems() && this._selectedIndexInFiltered < this._filteredItems.length ? this._filteredItems[this._selectedIndexInFiltered] : null;
        this._delegate.selectItem(selectedIndex, this._promptElement.value.trim());
    },

    _itemsLoaded: function()
    {

        if (this._loadTimeout)
            return;
        this._loadTimeout = setTimeout(this._updateAfterItemsLoaded.bind(this), 0);
    },

    _updateAfterItemsLoaded: function()
    {
        delete this._loadTimeout;
        this._filterItems();
    },

    /**
     * @param {number} index
     * @return {!Element}
     */
    _createItemElement: function(index)
    {
        var itemElement = createElement("div");
        itemElement.className = "filtered-item-list-dialog-item " + (this._renderAsTwoRows ? "two-rows" : "one-row");
        itemElement._titleElement = itemElement.createChild("div", "filtered-item-list-dialog-title");
        itemElement._subtitleElement = itemElement.createChild("div", "filtered-item-list-dialog-subtitle");
        itemElement._subtitleElement.textContent = "\u200B";
        itemElement._index = index;
        this._delegate.renderItem(index, this._promptElement.value.trim(), itemElement._titleElement, itemElement._subtitleElement);
        return itemElement;
    },

    /**
     * @param {string} query
     */
    setQuery: function(query)
    {
        this._promptElement.value = query;
        this._scheduleFilter();
    },

    _filterItems: function()
    {
        delete this._filterTimer;
        if (this._scoringTimer) {
            clearTimeout(this._scoringTimer);
            delete this._scoringTimer;
        }

        var query = this._delegate.rewriteQuery(this._promptElement.value.trim());
        this._query = query;
        var filterRegex = query ? WebInspector.FilePathScoreFunction.filterRegex(query) : null;

        var oldSelectedAbsoluteIndex = this._selectedIndexInFiltered ? this._filteredItems[this._selectedIndexInFiltered] : null;
        var filteredItems = [];
        this._selectedIndexInFiltered = 0;

        var bestScores = [];
        var bestItems = [];
        var bestItemsToCollect = 100;
        var minBestScore = 0;
        var overflowItems = [];

        scoreItems.call(this, 0);

        /**
         * @param {number} a
         * @param {number} b
         * @return {number}
         */
        function compareIntegers(a, b)
        {
            return b - a;
        }

        /**
         * @param {number} fromIndex
         * @this {WebInspector.FilteredItemSelectionDialog}
         */
        function scoreItems(fromIndex)
        {
            var maxWorkItems = 1000;
            var workDone = 0;
            for (var i = fromIndex; i < this._delegate.itemCount() && workDone < maxWorkItems; ++i) {
                // Filter out non-matching items quickly.
                if (filterRegex && !filterRegex.test(this._delegate.itemKeyAt(i)))
                    continue;

                // Score item.
                var score = this._delegate.itemScoreAt(i, query);
                if (query)
                    workDone++;

                // Find its index in the scores array (earlier elements have bigger scores).
                if (score > minBestScore || bestScores.length < bestItemsToCollect) {
                    var index = insertionIndexForObjectInListSortedByFunction(score, bestScores, compareIntegers, true);
                    bestScores.splice(index, 0, score);
                    bestItems.splice(index, 0, i);
                    if (bestScores.length > bestItemsToCollect) {
                        // Best list is too large -> drop last elements.
                        overflowItems.push(bestItems.peekLast());
                        bestScores.length = bestItemsToCollect;
                        bestItems.length = bestItemsToCollect;
                    }
                    minBestScore = bestScores.peekLast();
                } else
                    filteredItems.push(i);
            }

            // Process everything in chunks.
            if (i < this._delegate.itemCount()) {
                this._scoringTimer = setTimeout(scoreItems.bind(this, i), 0);
                return;
            }
            delete this._scoringTimer;

            this._filteredItems = bestItems.concat(overflowItems).concat(filteredItems);
            for (var i = 0; i < this._filteredItems.length; ++i) {
                if (this._filteredItems[i] === oldSelectedAbsoluteIndex) {
                    this._selectedIndexInFiltered = i;
                    break;
                }
            }
            this._viewportControl.invalidate();
            if (!query)
                this._selectedIndexInFiltered = 0;
            this._updateSelection(this._selectedIndexInFiltered, false);
        }
    },

    /**
     * @return {boolean}
     */
    _shouldShowMatchingItems: function()
    {
        return this._delegate.shouldShowMatchingItems(this._promptElement.value);
    },

    _onInput: function(event)
    {
        this._updateShowMatchingItems();
        this._scheduleFilter();
    },

    _updateShowMatchingItems: function()
    {
        var shouldShowMatchingItems = this._shouldShowMatchingItems();
        this._itemElementsContainer.classList.toggle("hidden", !shouldShowMatchingItems);
        this.element.style.height = shouldShowMatchingItems ? this._dialogHeight + "px" : "auto";
    },

    /**
     * @return {number}
     */
    _rowsPerViewport: function()
    {
        return Math.floor(this._viewportControl.element.clientHeight / this._rowHeight);
    },

    _onKeyDown: function(event)
    {
        var newSelectedIndex = this._selectedIndexInFiltered;

        switch (event.keyCode) {
        case WebInspector.KeyboardShortcut.Keys.Down.code:
            if (++newSelectedIndex >= this._filteredItems.length)
                newSelectedIndex = this._filteredItems.length - 1;
            this._updateSelection(newSelectedIndex, true);
            event.consume(true);
            break;
        case WebInspector.KeyboardShortcut.Keys.Up.code:
            if (--newSelectedIndex < 0)
                newSelectedIndex = 0;
            this._updateSelection(newSelectedIndex, false);
            event.consume(true);
            break;
        case WebInspector.KeyboardShortcut.Keys.PageDown.code:
            newSelectedIndex = Math.min(newSelectedIndex + this._rowsPerViewport(), this._filteredItems.length - 1);
            this._updateSelection(newSelectedIndex, true);
            event.consume(true);
            break;
        case WebInspector.KeyboardShortcut.Keys.PageUp.code:
            newSelectedIndex = Math.max(newSelectedIndex - this._rowsPerViewport(), 0);
            this._updateSelection(newSelectedIndex, false);
            event.consume(true);
            break;
        default:
        }
    },

    _scheduleFilter: function()
    {
        if (this._filterTimer)
            return;
        this._filterTimer = setTimeout(this._filterItems.bind(this), 0);
    },

    /**
     * @param {number} index
     * @param {boolean} makeLast
     */
    _updateSelection: function(index, makeLast)
    {
        if (!this._filteredItems.length)
            return;
        if (this._selectedElement)
            this._selectedElement.classList.remove("selected");
        this._viewportControl.scrollItemIntoView(index, makeLast);
        this._selectedIndexInFiltered = index;
        this._selectedElement = this._viewportControl.renderedElementAt(index);
        if (this._selectedElement)
            this._selectedElement.classList.add("selected");
    },

    _onClick: function(event)
    {
        var itemElement = event.target.enclosingNodeOrSelfWithClass("filtered-item-list-dialog-item");
        if (!itemElement)
            return;
        this._delegate.selectItem(itemElement._index, this._promptElement.value.trim());
        WebInspector.Dialog.hide();
    },

    /**
     * @override
     * @return {number}
     */
    itemCount: function()
    {
        return this._filteredItems.length;
    },

    /**
     * @override
     * @param {number} index
     * @return {number}
     */
    fastHeight: function(index)
    {
        if (!this._rowHeight) {
            var delegateIndex = this._filteredItems[index];
            var element = this._createItemElement(delegateIndex);
            this._rowHeight = WebInspector.measurePreferredSize(element, this._viewportControl.contentElement()).height;
        }
        return this._rowHeight;
    },

    /**
     * @override
     * @param {number} index
     * @return {!WebInspector.ViewportElement}
     */
    itemElement: function(index)
    {
        var delegateIndex = this._filteredItems[index];
        var element = this._createItemElement(delegateIndex);
        return new WebInspector.StaticViewportElement(element);
    },

    /**
     * @override
     * @return {number}
     */
    minimumRowHeight: function()
    {
        return this.fastHeight(0);
    },

    __proto__: WebInspector.DialogDelegate.prototype
}

/**
 * @constructor
 */
WebInspector.SelectionDialogContentProvider = function()
{
}

WebInspector.SelectionDialogContentProvider.prototype = {
    /**
     * @param {function():void} refreshCallback
     */
    setRefreshCallback: function(refreshCallback)
    {
        this._refreshCallback = refreshCallback;
    },

    /**
     * @param {string} query
     * @return {boolean}
     */
    shouldShowMatchingItems: function(query)
    {
        return true;
    },

    /**
     * @return {number}
     */
    itemCount: function()
    {
        return 0;
    },

    /**
     * @param {number} itemIndex
     * @return {string}
     */
    itemKeyAt: function(itemIndex)
    {
        return "";
    },

    /**
     * @param {number} itemIndex
     * @param {string} query
     * @return {number}
     */
    itemScoreAt: function(itemIndex, query)
    {
        return 1;
    },

    /**
     * @param {number} itemIndex
     * @param {string} query
     * @param {!Element} titleElement
     * @param {!Element} subtitleElement
     */
    renderItem: function(itemIndex, query, titleElement, subtitleElement)
    {
    },

    /**
     * @param {!Element} element
     * @param {string} query
     * @return {boolean}
     */
    highlightRanges: function(element, query)
    {
        if (!query)
            return false;

        /**
         * @param {string} text
         * @param {string} query
         * @return {?Array.<!WebInspector.SourceRange>}
         */
        function rangesForMatch(text, query)
        {
            var opcodes = WebInspector.Diff.charDiff(query, text);
            var offset = 0;
            var ranges = [];
            for (var i = 0; i < opcodes.length; ++i) {
                var opcode = opcodes[i];
                if (opcode[0] === WebInspector.Diff.Operation.Equal)
                    ranges.push(new WebInspector.SourceRange(offset, opcode[1].length));
                else if (opcode[0] !== WebInspector.Diff.Operation.Insert)
                    return null;
                offset += opcode[1].length;
            }
            return ranges;
        }

        var text = element.textContent;
        var ranges = rangesForMatch(text, query);
        if (!ranges)
            ranges = rangesForMatch(text.toUpperCase(), query.toUpperCase());
        if (ranges) {
            WebInspector.highlightRangesWithStyleClass(element, ranges, "highlight");
            return true;
        }
        return false;
    },

    /**
     * @param {number} itemIndex
     * @param {string} promptValue
     */
    selectItem: function(itemIndex, promptValue)
    {
    },

    refresh: function()
    {
        this._refreshCallback();
    },

    /**
     * @param {string} query
     * @return {string}
     */
    rewriteQuery: function(query)
    {
        return query;
    },

    dispose: function()
    {
    }
}

/**
 * @constructor
 * @extends {WebInspector.SelectionDialogContentProvider}
 * @param {!WebInspector.UISourceCode} uiSourceCode
 * @param {function(number, number)} selectItemCallback
 */
WebInspector.JavaScriptOutlineDialog = function(uiSourceCode, selectItemCallback)
{
    WebInspector.SelectionDialogContentProvider.call(this);

    this._functionItems = [];
    this._selectItemCallback = selectItemCallback;
    this._outlineWorker = new WorkerRuntime.Worker("script_formatter_worker");
    this._outlineWorker.onmessage = this._didBuildOutlineChunk.bind(this);
    this._outlineWorker.postMessage({ method: "javaScriptOutline", params: { content: uiSourceCode.workingCopy() } });
}

/**
 * @param {!WebInspector.UISourceCode} uiSourceCode
 * @param {function(number, number)} selectItemCallback
 */
WebInspector.JavaScriptOutlineDialog.show = function(uiSourceCode, selectItemCallback)
{
    if (WebInspector.Dialog.currentInstance())
        return;
    var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.JavaScriptOutlineDialog(uiSourceCode, selectItemCallback));
    WebInspector.Dialog.show(filteredItemSelectionDialog);
}

WebInspector.JavaScriptOutlineDialog.prototype = {
    /**
     * @param {!MessageEvent} event
     */
    _didBuildOutlineChunk: function(event)
    {
        var data = /** @type {!WebInspector.JavaScriptOutlineDialog.MessageEventData} */ (event.data);
        var chunk = data.chunk;
        for (var i = 0; i < chunk.length; ++i)
            this._functionItems.push(chunk[i]);

        if (data.isLastChunk)
            this.dispose();

        this.refresh();
    },

    /**
     * @override
     * @return {number}
     */
    itemCount: function()
    {
        return this._functionItems.length;
    },

    /**
     * @override
     * @param {number} itemIndex
     * @return {string}
     */
    itemKeyAt: function(itemIndex)
    {
        var item = this._functionItems[itemIndex];
        return item.name + (item.arguments ? item.arguments : "");
    },

    /**
     * @override
     * @param {number} itemIndex
     * @param {string} query
     * @return {number}
     */
    itemScoreAt: function(itemIndex, query)
    {
        var item = this._functionItems[itemIndex];
        return -item.line;
    },

    /**
     * @override
     * @param {number} itemIndex
     * @param {string} query
     * @param {!Element} titleElement
     * @param {!Element} subtitleElement
     */
    renderItem: function(itemIndex, query, titleElement, subtitleElement)
    {
        var item = this._functionItems[itemIndex];
        titleElement.textContent = item.name + (item.arguments ? item.arguments : "");
        this.highlightRanges(titleElement, query);
        subtitleElement.textContent = ":" + (item.line + 1);
    },

    /**
     * @override
     * @param {?number} itemIndex
     * @param {string} promptValue
     */
    selectItem: function(itemIndex, promptValue)
    {
        if (itemIndex === null)
            return;
        var lineNumber = this._functionItems[itemIndex].line;
        if (!isNaN(lineNumber) && lineNumber >= 0)
            this._selectItemCallback(lineNumber, this._functionItems[itemIndex].column);
    },

    dispose: function()
    {
        if (this._outlineWorker) {
            this._outlineWorker.terminate();
            delete this._outlineWorker;
        }
    },

    __proto__: WebInspector.SelectionDialogContentProvider.prototype
}

/**
 * @constructor
 * @extends {WebInspector.SelectionDialogContentProvider}
 * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
 */
WebInspector.SelectUISourceCodeDialog = function(defaultScores)
{
    WebInspector.SelectionDialogContentProvider.call(this);

    this._populate();
    this._defaultScores = defaultScores;
    this._scorer = new WebInspector.FilePathScoreFunction("");
    WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
}

WebInspector.SelectUISourceCodeDialog.prototype = {
    _projectRemoved: function(event)
    {
        var project = /** @type {!WebInspector.Project} */ (event.data);
        this._populate(project);
        this.refresh();
    },

    /**
     * @param {!WebInspector.Project=} skipProject
     */
    _populate: function(skipProject)
    {
        /** @type {!Array.<!WebInspector.UISourceCode>} */
        this._uiSourceCodes = [];
        var projects = WebInspector.workspace.projects().filter(this.filterProject.bind(this));
        for (var i = 0; i < projects.length; ++i) {
            if (skipProject && projects[i] === skipProject)
                continue;
            this._uiSourceCodes = this._uiSourceCodes.concat(projects[i].uiSourceCodes());
        }
    },

    /**
     * @param {?WebInspector.UISourceCode} uiSourceCode
     * @param {number=} lineNumber
     * @param {number=} columnNumber
     */
    uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
    {
        // Overridden by subclasses
    },

    /**
     * @param {!WebInspector.Project} project
     * @return {boolean}
     */
    filterProject: function(project)
    {
        return true;
        // Overridden by subclasses
    },

    /**
     * @override
     * @return {number}
     */
    itemCount: function()
    {
        return this._uiSourceCodes.length;
    },

    /**
     * @override
     * @param {number} itemIndex
     * @return {string}
     */
    itemKeyAt: function(itemIndex)
    {
        return this._uiSourceCodes[itemIndex].fullDisplayName();
    },

    /**
     * @override
     * @param {number} itemIndex
     * @param {string} query
     * @return {number}
     */
    itemScoreAt: function(itemIndex, query)
    {
        var uiSourceCode = this._uiSourceCodes[itemIndex];
        var score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
        if (!query || query.length < 2)
            return score;

        if (this._query !== query) {
            this._query = query;
            this._scorer = new WebInspector.FilePathScoreFunction(query);
        }

        var path = uiSourceCode.fullDisplayName();
        return score + 10 * this._scorer.score(path, null);
    },

    /**
     * @override
     * @param {number} itemIndex
     * @param {string} query
     * @param {!Element} titleElement
     * @param {!Element} subtitleElement
     */
    renderItem: function(itemIndex, query, titleElement, subtitleElement)
    {
        query = this.rewriteQuery(query);
        var uiSourceCode = this._uiSourceCodes[itemIndex];

        var fullDisplayName = uiSourceCode.fullDisplayName();
        var indexes = [];
        var score = new WebInspector.FilePathScoreFunction(query).score(fullDisplayName, indexes);
        var fileNameIndex = fullDisplayName.lastIndexOf("/");

        titleElement.textContent = uiSourceCode.displayName() + (this._queryLineNumberAndColumnNumber || "");
        subtitleElement.textContent = fullDisplayName.trimEnd(100);
        subtitleElement.title = fullDisplayName;
        var ranges = [];
        for (var i = 0; i < indexes.length; ++i)
            ranges.push({offset: indexes[i], length: 1});

        if (indexes[0] > fileNameIndex) {
            for (var i = 0; i < ranges.length; ++i)
                ranges[i].offset -= fileNameIndex + 1;
            WebInspector.highlightRangesWithStyleClass(titleElement, ranges, "highlight");
        } else {
            WebInspector.highlightRangesWithStyleClass(subtitleElement, ranges, "highlight");
        }
    },

    /**
     * @override
     * @param {?number} itemIndex
     * @param {string} promptValue
     */
    selectItem: function(itemIndex, promptValue)
    {
        var parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
        if (!parsedExpression)
            return;

        var lineNumber;
        var columnNumber;
        if (parsedExpression[2])
            lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
        if (parsedExpression[3])
            columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
        var uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
        this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
    },

    /**
     * @override
     * @param {string} query
     * @return {string}
     */
    rewriteQuery: function(query)
    {
        if (!query)
            return query;
        query = query.trim();
        var lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
        this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : "";
        return lineNumberMatch ? lineNumberMatch[1] : query;
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _uiSourceCodeAdded: function(event)
    {
        var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
        if (!this.filterProject(uiSourceCode.project()))
            return;
        this._uiSourceCodes.push(uiSourceCode);
        this.refresh();
    },

    dispose: function()
    {
        WebInspector.workspace.removeEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
        WebInspector.workspace.removeEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    },

    __proto__: WebInspector.SelectionDialogContentProvider.prototype
}

/**
 * @constructor
 * @extends {WebInspector.SelectUISourceCodeDialog}
 * @param {!WebInspector.SourcesView} sourcesView
 * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
 */
WebInspector.OpenResourceDialog = function(sourcesView, defaultScores)
{
    WebInspector.SelectUISourceCodeDialog.call(this, defaultScores);
    this._sourcesView = sourcesView;
}

WebInspector.OpenResourceDialog.prototype = {

    /**
     * @override
     * @param {?WebInspector.UISourceCode} uiSourceCode
     * @param {number=} lineNumber
     * @param {number=} columnNumber
     */
    uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
    {
        if (!uiSourceCode)
            uiSourceCode = this._sourcesView.currentUISourceCode();
        if (!uiSourceCode)
            return;
        this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
    },

    /**
     * @override
     * @param {string} query
     * @return {boolean}
     */
    shouldShowMatchingItems: function(query)
    {
        return !query.startsWith(":");
    },

    /**
     * @override
     * @param {!WebInspector.Project} project
     * @return {boolean}
     */
    filterProject: function(project)
    {
        return !project.isServiceProject();
    },

    __proto__: WebInspector.SelectUISourceCodeDialog.prototype
}

/**
 * @param {!WebInspector.SourcesView} sourcesView
 * @param {string=} query
 * @param {!Map.<!WebInspector.UISourceCode, number>=} defaultScores
 */
WebInspector.OpenResourceDialog.show = function(sourcesView, query, defaultScores)
{
    if (WebInspector.Dialog.currentInstance())
        return;

    var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.OpenResourceDialog(sourcesView, defaultScores));
    filteredItemSelectionDialog.renderAsTwoRows();
    WebInspector.Dialog.show(filteredItemSelectionDialog);
    if (query)
        filteredItemSelectionDialog.setQuery(query);
}

/**
 * @constructor
 * @extends {WebInspector.SelectUISourceCodeDialog}
 * @param {!Array.<string>} types
 * @param {function(?WebInspector.UISourceCode)} callback
 */
WebInspector.SelectUISourceCodeForProjectTypesDialog = function(types, callback)
{
    this._types = types;
    WebInspector.SelectUISourceCodeDialog.call(this);
    this._callback = callback;
}

WebInspector.SelectUISourceCodeForProjectTypesDialog.prototype = {
    /**
     * @override
     * @param {?WebInspector.UISourceCode} uiSourceCode
     * @param {number=} lineNumber
     * @param {number=} columnNumber
     */
    uiSourceCodeSelected: function(uiSourceCode, lineNumber, columnNumber)
    {
        this._callback(uiSourceCode);
    },

    /**
     * @override
     * @param {!WebInspector.Project} project
     * @return {boolean}
     */
    filterProject: function(project)
    {
        return this._types.indexOf(project.type()) !== -1;
    },

    __proto__: WebInspector.SelectUISourceCodeDialog.prototype
}

/**
 * @param {string} name
 * @param {!Array.<string>} types
 * @param {function(?WebInspector.UISourceCode)} callback
 */
WebInspector.SelectUISourceCodeForProjectTypesDialog.show = function(name, types, callback)
{
    if (WebInspector.Dialog.currentInstance())
        return;

    var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.SelectUISourceCodeForProjectTypesDialog(types, callback));
    filteredItemSelectionDialog.setQuery(name);
    filteredItemSelectionDialog.renderAsTwoRows();
    WebInspector.Dialog.show(filteredItemSelectionDialog);
}

/**
 * @typedef {{isLastChunk: boolean, chunk: !Array.<!{selectorText: string, lineNumber: number, columnNumber: number}>}}
 */
WebInspector.JavaScriptOutlineDialog.MessageEventData;
