/*
 * Copyright (C) 2020-2021 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.WebInspectorExtensionController = class WebInspectorExtensionController extends WI.Object
{
    constructor()
    {
        super();

        this._extensionForExtensionIDMap = new Map;
        this._extensionTabContentViewForExtensionTabIDMap = new Map;
        this._tabIDsForExtensionIDMap = new Multimap;
        this._nextExtensionTabID = 1;

        this._extensionTabPositions = null;
        this._saveTabPositionsDebouncer = null;

        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleMainResourceDidChange, this);
    }

    // Static

    static get extensionTabPositionsObjectStoreKey()
    {
        return "extension-tab-positions";
    }

    // Public

    get registeredExtensionIDs()
    {
        return new Set(this._extensionForExtensionIDMap.keys());
    }

    registerExtension(extensionID, extensionBundleIdentifier, displayName)
    {
        if (this._extensionForExtensionIDMap.has(extensionID)) {
            WI.reportInternalError("Unable to register extension, it's already registered: " + extensionID);
            return WI.WebInspectorExtension.ErrorCode.RegistrationFailed;
        }

        if (!this._extensionForExtensionIDMap.size) {
            WI.tabBrowser.tabBar.addEventListener(WI.TabBar.Event.TabBarItemAdded, this._saveExtensionTabPositions, this);
            WI.tabBrowser.tabBar.addEventListener(WI.TabBar.Event.TabBarItemRemoved, this._saveExtensionTabPositions, this);
            WI.tabBrowser.tabBar.addEventListener(WI.TabBar.Event.TabBarItemsReordered, this._saveExtensionTabPositions, this);
        }

        let extension = new WI.WebInspectorExtension(extensionID, extensionBundleIdentifier, displayName);
        this._extensionForExtensionIDMap.set(extensionID, extension);

        this.dispatchEventToListeners(WI.WebInspectorExtensionController.Event.ExtensionAdded, {extension});
    }

    unregisterExtension(extensionID)
    {
        let extension = this._extensionForExtensionIDMap.take(extensionID);
        if (!extension) {
            WI.reportInternalError("Unable to unregister extension with unknown ID: " + extensionID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        if (!this._extensionForExtensionIDMap.size) {
            WI.tabBrowser.tabBar.removeEventListener(WI.TabBar.Event.TabBarItemAdded, this._saveExtensionTabPositions, this);
            WI.tabBrowser.tabBar.removeEventListener(WI.TabBar.Event.TabBarItemRemoved, this._saveExtensionTabPositions, this);
            WI.tabBrowser.tabBar.removeEventListener(WI.TabBar.Event.TabBarItemsReordered, this._saveExtensionTabPositions, this);
        }

        let extensionTabIDsToRemove = this._tabIDsForExtensionIDMap.take(extensionID) || [];
        for (let extensionTabID of extensionTabIDsToRemove) {
            let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.take(extensionTabID);

            // Ensure that the iframe is actually detached and does not leak.
            WI.tabBrowser.closeTabForContentView(tabContentView, {suppressAnimations: true});
            tabContentView.dispose();
        }

        this.dispatchEventToListeners(WI.WebInspectorExtensionController.Event.ExtensionRemoved, {extension});
    }

    async createTabForExtension(extensionID, tabName, tabIconURL, sourceURL)
    {
        let extension = this._extensionForExtensionIDMap.get(extensionID);
        if (!extension) {
            WI.reportInternalError("Unable to create tab for extension with unknown ID: " + extensionID + " sourceURL: " + sourceURL);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        let extensionTabID = `WebExtensionTab-${extensionID}-${this._nextExtensionTabID++}`;
        let tabContentView = new WI.WebInspectorExtensionTabContentView(extension, extensionTabID, tabName, tabIconURL, sourceURL);

        this._tabIDsForExtensionIDMap.add(extensionID, extensionTabID);
        this._extensionTabContentViewForExtensionTabIDMap.set(extensionTabID, tabContentView);

        if (!this._extensionTabPositions)
            await this._loadExtensionTabPositions();

        WI.tabBrowser.addTabForContentView(tabContentView, {
            suppressAnimations: true,
            insertionIndex: this._insertionIndexForExtensionTab(tabContentView),
        });

        // The calling convention is to return an error string or a result object.
        return {"result": extensionTabID};
    }

    evaluateScriptForExtension(extensionID, scriptSource, {frameURL, contextSecurityOrigin, useContentScriptContext} = {})
    {
        let extension = this._extensionForExtensionIDMap.get(extensionID);
        if (!extension) {
            WI.reportInternalError("Unable to evaluate script for extension with unknown ID: " + extensionID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        let frame = this._frameForFrameURL(frameURL);
        if (!frame) {
            WI.reportInternalError("evaluateScriptForExtension: No frame matched provided frameURL: " + frameURL);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        if (contextSecurityOrigin) {
            WI.reportInternalError("evaluateScriptForExtension: the 'contextSecurityOrigin' option is not yet implemented.");
            return WI.WebInspectorExtension.ErrorCode.NotImplemented;
        }

        if (useContentScriptContext) {
            WI.reportInternalError("evaluateScriptForExtension: the 'useContentScriptContext' option is not yet implemented.");
            return WI.WebInspectorExtension.ErrorCode.NotImplemented;
        }

        let evaluationContext = frame.pageExecutionContext;
        if (!evaluationContext) {
            WI.reportInternalError("evaluateScriptForExtension: No 'pageExecutionContext' was present for frame with URL: " + frame.url);
            return WI.WebInspectorExtension.ErrorCode.ContextDestroyed;
        }

        return evaluationContext.target.RuntimeAgent.evaluate.invoke({
            expression: scriptSource,
            objectGroup: "extension-evaluation",
            includeCommandLineAPI: true,
            returnByValue: true,
            generatePreview: false,
            saveResult: false,
            contextId: evaluationContext.id,
        }).then((payload) => {
            let resultOrError = payload.result;
            let wasThrown = payload.wasThrown;
            let {type, value} = resultOrError;
            return wasThrown ? {"error": resultOrError.description} : {"result": value};
        }).catch((error) => error.description);
    }

    reloadForExtension(extensionID, {ignoreCache, userAgent, injectedScript} = {})
    {
        let extension = this._extensionForExtensionIDMap.get(extensionID);
        if (!extension) {
            WI.reportInternalError("Unable to evaluate script for extension with unknown ID: " + extensionID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        // FIXME: <webkit.org/b/222328> Implement `userAgent` and `injectedScript` options for `devtools.inspectedWindow.reload` command
        if (userAgent) {
            WI.reportInternalError("reloadForExtension: the 'userAgent' option is not yet implemented.");
            return WI.WebInspectorExtension.ErrorCode.NotImplemented;
        }

        if (injectedScript) {
            WI.reportInternalError("reloadForExtension: the 'injectedScript' option is not yet implemented.");
            return WI.WebInspectorExtension.ErrorCode.NotImplemented;
        }

        let target = WI.assumingMainTarget();
        if (!target.hasCommand("Page.reload"))
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;

        return target.PageAgent.reload.invoke({ignoreCache});
    }

    showExtensionTab(extensionTabID, options = {})
    {
        let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.get(extensionTabID);
        if (!tabContentView) {
            WI.reportInternalError("Unable to show extension tab with unknown extensionTabID: " + extensionTabID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        tabContentView.visible = true;
        let success = WI.tabBrowser.showTabForContentView(tabContentView, {
            ...options,
            insertionIndex: this._insertionIndexForExtensionTab(tabContentView),
            initiatorHint: WI.TabBrowser.TabNavigationInitiator.FrontendAPI,
        });

        if (!success) {
            WI.reportInternalError("Unable to show extension tab with extensionTabID: " + extensionTabID);
            return WI.WebInspectorExtension.ErrorCode.InternalError;
        }

        tabContentView.visible = true;

        // Clients expect to be able to use evaluateScriptInExtensionTab() when this method
        // returns, so wait for the extension tab to finish its loading sequence. Wrap the result.
        return tabContentView.whenPageAvailable().then((sourceURL) => { return {"result": sourceURL}; });
    }

    hideExtensionTab(extensionTabID, options = {})
    {
        let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.get(extensionTabID);
        if (!tabContentView) {
            WI.reportInternalError("Unable to show extension tab with unknown extensionTabID: " + extensionTabID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        tabContentView.visible = false;
        WI.tabBrowser.closeTabForContentView(tabContentView, options);

        console.assert(!tabContentView.visible);
        console.assert(!tabContentView.isClosed);
    }

    addContextMenuItemsForClosedExtensionTabs(contextMenu)
    {
        contextMenu.appendSeparator();

        for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) {
            // If the extension tab has been unchecked in the TabBar context menu, then the tabBarItem
            // for the extension tab will not be connected to a parent TabBar.
            let shouldIncludeTab = !tabContentView.visible || !tabContentView.tabBarItem.parentTabBar;
            if (!shouldIncludeTab)
                continue;

            contextMenu.appendItem(tabContentView.tabInfo().displayName, () => {
                this.showExtensionTab(tabContentView.extensionTabID);
            });
        }
    }

    addContextMenuItemsForAllExtensionTabs(contextMenu)
    {
        contextMenu.appendSeparator();

        for (let tabContentView of this._extensionTabContentViewForExtensionTabIDMap.values()) {
            let checked = tabContentView.visible || !!tabContentView.tabBarItem.parentTabBar;
            contextMenu.appendCheckboxItem(tabContentView.tabInfo().displayName, () => {
                if (!checked)
                    this.showExtensionTab(tabContentView.extensionTabID);
                else
                    this.hideExtensionTab(tabContentView.extensionTabID);
            }, checked);
        }
    }

    activeExtensionTabContentViews()
    {
        return Array.from(this._extensionTabContentViewForExtensionTabIDMap.values()).filter((tab) => tab.visible || tab.tabBarItem.parentTabBar);
    }

    evaluateScriptInExtensionTab(extensionTabID, scriptSource)
    {
        let tabContentView = this._extensionTabContentViewForExtensionTabIDMap.get(extensionTabID);
        if (!tabContentView) {
            WI.reportInternalError("Unable to evaluate with unknown extensionTabID: " + extensionTabID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        let iframe = tabContentView.iframeElement;
        if (!(iframe instanceof HTMLIFrameElement)) {
            WI.reportInternalError("Unable to evaluate without an <iframe> for extensionTabID: " + extensionTabID);
            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
        }

        return new Promise((resolve, reject) => {
            try {
                // If `result` is a promise, then it came from a different frame and `instanceof Promise` won't work.
                let result = InspectorFrontendHost.evaluateScriptInExtensionTab(iframe, scriptSource);
                if (result?.then) {
                    result.then((resolvedValue) => resolve({result: resolvedValue}), (errorValue) => reject({error: errorValue}));
                    return;
                }

                resolve({result});
            } catch (error) {
                // Include more context in the stringification of the error.
                const stackIndent = "  ";
                let stackLines = (error.stack?.split("\n") || []).map((line) => `${stackIndent}${line}`);
                let formattedMessage = [
                    `Caught Exception: ${error.name}`,
                    `at ${error.sourceURL || "(unknown)"}:${error.line || 0}:${error.column || 0}:`,
                    error.message,
                    "",
                    "Backtrace:",
                    ...stackLines,
                ].join("\n");
                reject({error: formattedMessage});
            }
        });
    }

    // Private

    async _loadExtensionTabPositions()
    {
        let savedTabPositions = await WI.objectStores.general.get(WebInspectorExtensionController.extensionTabPositionsObjectStoreKey);
        this._extensionTabPositions = savedTabPositions || {};
    }

    _saveExtensionTabPositions()
    {
        if (!this._extensionTabPositions)
            return;

        this._saveTabPositionsDebouncer ||= new Debouncer(() => {
            for (let tabBarItem of WI.tabBrowser.tabBar.visibleTabBarItemsFromLeftToRight) {
                if (!(tabBarItem.representedObject instanceof WI.WebInspectorExtensionTabContentView))
                    continue;

                let {anchorTabType, anchorTabIndex, distanceFromAnchorTab} = this._computeIndicesForExtensionTab(tabBarItem.representedObject, {recomputePositions: true});
                this._extensionTabPositions[tabBarItem.representedObject.savedTabPositionKey] = {anchorTabType, distanceFromAnchorTab};
            }

            WI.objectStores.general.put(this._extensionTabPositions, WebInspectorExtensionController.extensionTabPositionsObjectStoreKey);
        });
        this._saveTabPositionsDebouncer.delayForTime(5000);
    }

    _insertionIndexForExtensionTab(tabContentView, options = {})
    {
        let {anchorTabType, anchorTabIndex, distanceFromAnchorTab} = this._computeIndicesForExtensionTab(tabContentView, options);
        return anchorTabIndex + distanceFromAnchorTab + 1;
    }

    _computeIndicesForExtensionTab(tabContentView, {recomputePositions} = {})
    {
        // Note: pinned tabs always appear on the trailing edge, so we can ignore them
        // for the purposes of computing an `insertionIndex`` for `tabContentView`.
        let anchorTabIndex = 0;
        let savedPositions = this._extensionTabPositions[tabContentView.savedTabPositionKey] || {};
        let anchorTabType = (recomputePositions && savedPositions.anchorTabType) || null;
        let distanceFromAnchorTab = (recomputePositions && savedPositions.distanceFromAnchorTab) || 0;

        let visibleTabBarItems = WI.tabBrowser.tabBar.visibleTabBarItemsFromLeftToRight;
        for (let i = 0; i < visibleTabBarItems.length; ++i) {
            let visibleTab = visibleTabBarItems[i].representedObject;
            if (!visibleTab)
                continue;

            if (visibleTab === tabContentView)
                break;

            if (visibleTab instanceof WI.WebInspectorExtensionTabContentView)
                continue;

            if (recomputePositions) {
                anchorTabType = visibleTab.type || null;
                continue;
            }

            if (visibleTab.type !== anchorTabType)
                continue;

            anchorTabIndex = i;
            break;
        }

        // Find the count of extension tabs after the anchor tab to compute the real distanceFromAnchorTab.
        // Adding `distanceFromAnchorTab` to `anchorTabIndex` should not insert the tab after a different anchor tab.
        for (let i = 1; i < visibleTabBarItems.length - anchorTabIndex; ++i) {
            if (visibleTabBarItems[anchorTabIndex + i].representedObject?.constructor?.shouldSaveTab?.()) {
                distanceFromAnchorTab = Number.constrain(distanceFromAnchorTab, 0, Math.max(0, i - 1));
                return {anchorTabType, anchorTabIndex, distanceFromAnchorTab};
            }
        }

        // If the anchor tab is now hidden upon restoring, place the extension at the end.
        // This could happen if a smaller set of tabs are enabled for the inspection target.
        anchorTabIndex = visibleTabBarItems.length - 1;
        return {anchorTabType, anchorTabIndex, distanceFromAnchorTab};
    }

    _frameForFrameURL(frameURL)
    {
        if (!frameURL)
            return WI.networkManager.mainFrame;

        function findFrame(frameURL, adjustKnownFrameURL) {
            return WI.networkManager.frames.find((knownFrame) => {
                let knownFrameURL = new URL(knownFrame.url);
                adjustKnownFrameURL?.(knownFrameURL);
                return knownFrameURL.toString() === frameURL;
            });
        }

        let frame = findFrame(frameURL);
        if (frame)
            return frame;

        let frameURLParts = new URL(frameURL);
        if (frameURLParts.hash.length)
            return null;

        frame = findFrame(frameURL, (knownFrameURL) => {
            knownFrameURL.hash = "";
        });
        if (frame)
            return frame;

        if (frameURLParts.search.length)
            return null;

        return findFrame(frameURL, (knownFrameURL) => {
            knownFrameURL.hash = "";
            knownFrameURL.search = "";
        });
    }

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

        // Don't fire the event unless one or more extensions are registered.
        if (!this._extensionForExtensionIDMap.size)
            return;

        InspectorFrontendHost.inspectedPageDidNavigate(WI.networkManager.mainFrame.url);
    }
};

WI.WebInspectorExtensionController.Event = {
    ExtensionAdded: "extension-added",
    ExtensionRemoved: "extension-removed",
};
