/*
 * Copyright (C) 2016 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.OpenResourceDialog = class OpenResourceDialog extends WI.Dialog
{
    constructor(delegate)
    {
        super(delegate);

        this.element.classList.add("open-resource-dialog");

        let fieldElement = this.element.appendChild(document.createElement("div"));
        fieldElement.classList.add("field");

        this._inputElement = fieldElement.appendChild(document.createElement("input"));
        this._inputElement.type = "text";
        this._inputElement.placeholder = WI.UIString("File or Resource");
        this._inputElement.spellcheck = false;

        this._clearIconElement = fieldElement.appendChild(document.createElement("img"));

        this._inputElement.addEventListener("keydown", this._handleKeydownEvent.bind(this));
        this._inputElement.addEventListener("keyup", this._handleKeyupEvent.bind(this));
        this._inputElement.addEventListener("blur", this._handleBlurEvent.bind(this));
        this._clearIconElement.addEventListener("mousedown", this._handleMousedownEvent.bind(this));
        this._clearIconElement.addEventListener("click", this._handleClickEvent.bind(this));

        this._treeOutline = new WI.TreeOutline;
        this._treeOutline.allowsRepeatSelection = true;
        this._treeOutline.disclosureButtons = false;
        this._treeOutline.large = true;

        this._treeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
        this._treeOutline.element.addEventListener("focus", () => { this._inputElement.focus(); });

        this.element.appendChild(this._treeOutline.element);

        this._queryController = new WI.ResourceQueryController;
        this._filteredResults = [];
    }

    // Protected

    _populateResourceTreeOutline()
    {
        function createHighlightedTitleFragment(title, highlightTextRanges)
        {
            let titleFragment = document.createDocumentFragment();
            let lastIndex = 0;
            for (let textRange of highlightTextRanges) {
                if (textRange.startColumn > lastIndex)
                    titleFragment.append(title.substring(lastIndex, textRange.startColumn));

                let highlightSpan = document.createElement("span");
                highlightSpan.classList.add("highlighted");
                highlightSpan.append(title.substring(textRange.startColumn, textRange.endColumn));
                titleFragment.append(highlightSpan);
                lastIndex = textRange.endColumn;
            }

            if (lastIndex < title.length)
                titleFragment.append(title.substring(lastIndex, title.length));

            return titleFragment;
        }

        function createTreeElement(representedObject)
        {
            let treeElement = null;

            if (representedObject instanceof WI.SourceMapResource)
                treeElement = new WI.SourceMapResourceTreeElement(representedObject);
            else if (representedObject instanceof WI.Resource)
                treeElement = new WI.ResourceTreeElement(representedObject);
            else if (representedObject instanceof WI.Script)
                treeElement = new WI.ScriptTreeElement(representedObject);

            return treeElement;
        }

        for (let result of this._filteredResults) {
            let resource = result.resource;
            if (this._treeOutline.findTreeElement(resource))
                continue;

            let treeElement = createTreeElement(resource);
            if (!treeElement)
                continue;

            treeElement.mainTitle = createHighlightedTitleFragment(resource.displayName, result.matchingTextRanges);
            treeElement[WI.OpenResourceDialog.ResourceMatchCookieDataSymbol] = result.cookie;
            this._treeOutline.appendChild(treeElement);
        }

        if (this._treeOutline.children.length)
            this._treeOutline.children[0].select(true, false, true, true);
    }

    didDismissDialog()
    {
        WI.Frame.removeEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
        WI.Frame.removeEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this);
        WI.Target.removeEventListener(WI.Target.Event.ResourceAdded, this._resourceWasAdded, this);
        WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ScriptAdded, this._scriptAdded, this);

        this._queryController.reset();
    }

    didPresentDialog()
    {
        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
        WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this);
        WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._resourceWasAdded, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptAdded, this._scriptAdded, this);

        if (WI.frameResourceManager.mainFrame)
            this._addResourcesForFrame(WI.frameResourceManager.mainFrame);

        for (let target of WI.targets) {
            if (target !== WI.mainTarget)
                this._addResourcesForTarget(target);
        }

        this._updateFilter();

        this._inputElement.focus();
        this._clear();
    }

    // Private

    _handleKeydownEvent(event)
    {
        if (event.keyCode === WI.KeyboardShortcut.Key.Escape.keyCode) {
            if (this._inputElement.value === "")
                this.dismiss();
            else
                this._clear();

            event.preventDefault();
        } else if (event.keyCode === WI.KeyboardShortcut.Key.Enter.keyCode) {
            if (this._treeOutline.selectedTreeElement) {
                this.dismiss(this._treeOutline.selectedTreeElement.representedObject, this._treeOutline.selectedTreeElement[WI.OpenResourceDialog.ResourceMatchCookieDataSymbol]);
                event.preventDefault();
                return;
            }

            // ":<line>:<column>" jumps to a location for the current ContentView.
            if (/^:\d/.test(this._inputElement.value)) {
                let visibleContentView = WI.focusedOrVisibleContentView();
                let representedObject = visibleContentView ? visibleContentView.representedObject : null;
                if (representedObject && representedObject instanceof WI.SourceCode) {
                    let [, lineNumber, columnNumber] = this._inputElement.value.split(":");
                    lineNumber = lineNumber ? parseInt(lineNumber, 10) - 1 : 0;
                    columnNumber = columnNumber ? parseInt(columnNumber, 10) - 1 : 0;
                    this.dismiss(representedObject, {lineNumber, columnNumber});
                    event.preventDefault();
                    return;
                }
            }

            this._inputElement.select();
        } else if (event.keyCode === WI.KeyboardShortcut.Key.Up.keyCode || event.keyCode === WI.KeyboardShortcut.Key.Down.keyCode) {
            let treeElement = this._treeOutline.selectedTreeElement;
            if (!treeElement)
                return;

            let adjacentSiblingProperty = event.keyCode === WI.KeyboardShortcut.Key.Up.keyCode ? "previousSibling" : "nextSibling";
            treeElement = treeElement[adjacentSiblingProperty];
            if (treeElement)
                treeElement.revealAndSelect(true, false, true, true);

            event.preventDefault();
        }
    }

    _handleKeyupEvent(event)
    {
        if (event.keyCode === WI.KeyboardShortcut.Key.Up.keyCode || event.keyCode === WI.KeyboardShortcut.Key.Down.keyCode)
            return;

        this._updateFilter();
    }

    _handleBlurEvent(event)
    {
        // Prevent the dialog from being dismissed while handling a tree item click event.
        if (event.relatedTarget === this._treeOutline.element)
            return;

        this.dismiss();
    }

    _handleMousedownEvent(event)
    {
        this._inputElement.select();

        // This ensures we don't get a "blur" event triggered for the text field
        // that would cause the dialog to be dismissed.
        event.preventDefault();
    }

    _handleClickEvent(event)
    {
        this._clear();
    }

    _clear()
    {
        this._inputElement.value = "";
        this._updateFilter();
    }

    _updateFilter()
    {
        this._filteredResults = [];
        this._treeOutline.removeChildren();

        let filterText = this._inputElement.value.trim();
        if (filterText) {
            this._filteredResults = this._queryController.executeQuery(filterText);
            this._populateResourceTreeOutline();
        }

        this.element.classList.toggle("non-empty", this._inputElement.value !== "");
        this.element.classList.toggle("has-results", this._treeOutline.children.length);
    }

    _treeSelectionDidChange(event)
    {
        let treeElement = event.data.selectedElement;
        if (!treeElement)
            return;

        if (!event.data.selectedByUser)
            return;

        this.dismiss(treeElement.representedObject, treeElement[WI.OpenResourceDialog.ResourceMatchCookieDataSymbol]);
    }

    _addResource(resource, suppressFilterUpdate)
    {
        if (!this.representedObjectIsValid(resource))
            return;

        // Recurse on source maps if any exist.
        for (let sourceMap of resource.sourceMaps) {
            for (let sourceMapResource of sourceMap.resources)
                this._addResource(sourceMapResource, suppressFilterUpdate);
        }

        this._queryController.addResource(resource);
        if (suppressFilterUpdate)
            return;

        this._updateFilter();
    }

    _addResourcesForFrame(frame)
    {
        const suppressFilterUpdate = true;

        let frames = [frame];
        while (frames.length) {
            let currentFrame = frames.shift();
            let resources = [currentFrame.mainResource].concat(Array.from(currentFrame.resourceCollection.items));
            for (let resource of resources)
                this._addResource(resource, suppressFilterUpdate);

            frames = frames.concat(currentFrame.childFrameCollection.toArray());
        }
    }

    _addResourcesForTarget(target)
    {
        const suppressFilterUpdate = true;

        this._addResource(target.mainResource);

        for (let resource of target.resourceCollection.items)
            this._addResource(resource, suppressFilterUpdate);

        let targetData = WI.debuggerManager.dataForTarget(target);
        for (let script of targetData.scripts) {
            if (script.resource)
                continue;
            if (isWebKitInternalScript(script.sourceURL) || isWebInspectorConsoleEvaluationScript(script.sourceURL))
                continue;
            this._addResource(script, suppressFilterUpdate);
        }
    }

    _mainResourceDidChange(event)
    {
        if (event.target.isMainFrame())
            this._queryController.reset();

        this._addResource(event.target.mainResource);
    }

    _resourceWasAdded(event)
    {
        this._addResource(event.data.resource);
    }

    _scriptAdded(event)
    {
        let script = event.data.script;
        if (script.resource)
            return;

        if (script.target === WI.mainTarget)
            return;

        this._addResource(script);
    }
};

WI.OpenResourceDialog.ResourceMatchCookieDataSymbol = Symbol("open-resource-dialog-resource-match-cookie-data");
