/*
 * Copyright (C) 2016 Devin Rousso <webkit@devinrousso.com>. 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.appendContextMenuItemsForSourceCode = function(contextMenu, sourceCodeOrLocation)
{
    console.assert(contextMenu instanceof WI.ContextMenu);
    if (!(contextMenu instanceof WI.ContextMenu))
        return;

    let sourceCode = sourceCodeOrLocation;
    let location = null;
    if (sourceCodeOrLocation instanceof WI.SourceCodeLocation) {
        sourceCode = sourceCodeOrLocation.sourceCode;
        location = sourceCodeOrLocation;
    }

    console.assert(sourceCode instanceof WI.SourceCode);
    if (!(sourceCode instanceof WI.SourceCode))
        return;

    contextMenu.appendSeparator();

    WI.appendContextMenuItemsForURL(contextMenu, sourceCode.url, {sourceCode, location});

    if (sourceCode instanceof WI.Resource) {
        if (sourceCode.urlComponents.scheme !== "data") {
            contextMenu.appendItem(WI.UIString("Copy as cURL"), () => {
                InspectorFrontendHost.copyText(sourceCode.generateCURLCommand());
            });

            contextMenu.appendSeparator();

            contextMenu.appendItem(WI.UIString("Copy HTTP Request"), () => {
                InspectorFrontendHost.copyText(sourceCode.stringifyHTTPRequest());
            });

            if (sourceCode.hasResponse()) {
                contextMenu.appendItem(WI.UIString("Copy HTTP Response"), () => {
                    InspectorFrontendHost.copyText(sourceCode.stringifyHTTPResponse());
                });
            }

            contextMenu.appendSeparator();
        }
    }

    contextMenu.appendItem(WI.UIString("Save File"), () => {
        sourceCode.requestContent().then(() => {
            const forceSaveAs = true;
            WI.FileUtilities.save({
                url: sourceCode.url || "",
                content: sourceCode.content
            }, forceSaveAs);
        });
    });

    contextMenu.appendSeparator();

    if (location && (sourceCode instanceof WI.Script || (sourceCode instanceof WI.Resource && sourceCode.type === WI.Resource.Type.Script))) {
        let existingBreakpoint = WI.debuggerManager.breakpointForSourceCodeLocation(location);
        if (existingBreakpoint) {
            contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => {
                WI.debuggerManager.removeBreakpoint(existingBreakpoint);
            });
        } else {
            contextMenu.appendItem(WI.UIString("Add Breakpoint"), () => {
                WI.debuggerManager.addBreakpoint(new WI.Breakpoint(location));
            });
        }

        contextMenu.appendSeparator();
    }
};

WI.appendContextMenuItemsForURL = function(contextMenu, url, options = {})
{
    if (!url)
        return;

    function showResourceWithOptions(options) {
        if (options.location)
            WI.showSourceCodeLocation(options.location, options);
        else if (options.sourceCode)
            WI.showSourceCode(options.sourceCode, options);
        else
            WI.openURL(url, options.frame, options);
    }

    if (!url.startsWith("javascript:") && !url.startsWith("data:")) {
        contextMenu.appendItem(WI.UIString("Open in New Tab"), () => {
            const frame = null;
            WI.openURL(url, frame, {alwaysOpenExternally: true});
        });
    }

    if (WI.networkManager.resourceForURL(url)) {
        if (WI.settings.experimentalEnableSourcesTab.value) {
            if (!WI.isShowingSourcesTab()) {
                contextMenu.appendItem(WI.UIString("Reveal in Sources Tab"), () => {
                    showResourceWithOptions({preferredTabType: WI.SourcesTabContentView.Type});
                });
            }
        } else {
            if (!WI.isShowingResourcesTab()) {
                contextMenu.appendItem(WI.UIString("Reveal in Resources Tab"), () => {
                    showResourceWithOptions({preferredTabType: WI.ResourcesTabContentView.Type});
                });
            }
        }
        if (!WI.isShowingNetworkTab()) {
            contextMenu.appendItem(WI.UIString("Reveal in Network Tab"), () => {
                showResourceWithOptions({preferredTabType: WI.NetworkTabContentView.Type});
            });
        }
    }

    contextMenu.appendSeparator();

    contextMenu.appendItem(WI.UIString("Copy Link"), () => {
        InspectorFrontendHost.copyText(url);
    });
};

WI.appendContextMenuItemsForDOMNode = function(contextMenu, domNode, options = {})
{
    console.assert(contextMenu instanceof WI.ContextMenu);
    if (!(contextMenu instanceof WI.ContextMenu))
        return;

    console.assert(domNode instanceof WI.DOMNode);
    if (!(domNode instanceof WI.DOMNode))
        return;

    let copySubMenu = options.copySubMenu || contextMenu.appendSubMenuItem(WI.UIString("Copy"));

    let isElement = domNode.nodeType() === Node.ELEMENT_NODE;
    let attached = domNode.attached;

    if (isElement && attached) {
        copySubMenu.appendItem(WI.UIString("Selector Path"), () => {
            let cssPath = WI.cssPath(domNode);
            InspectorFrontendHost.copyText(cssPath);
        });
    }

    if (!domNode.isPseudoElement() && attached) {
        copySubMenu.appendItem(WI.UIString("XPath"), () => {
            let xpath = WI.xpath(domNode);
            InspectorFrontendHost.copyText(xpath);
        });
    }

    contextMenu.appendSeparator();

    if (domNode.isCustomElement()) {
        contextMenu.appendItem(WI.UIString("Jump to Definition"), () => {
            function didGetFunctionDetails(error, response) {
                if (error)
                    return;

                let location = response.location;
                let sourceCode = WI.debuggerManager.scriptForIdentifier(location.scriptId, WI.mainTarget);
                if (!sourceCode)
                    return;

                let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber || 0);
                WI.showSourceCodeLocation(sourceCodeLocation, {
                    ignoreNetworkTab: true,
                    ignoreSearchTab: true,
                });
            }

            WI.RemoteObject.resolveNode(domNode).then((remoteObject) => {
                remoteObject.getProperty("constructor", (error, result, wasThrown) => {
                    if (error)
                        return;
                    if (result.type === "function")
                        remoteObject.target.DebuggerAgent.getFunctionDetails(result.objectId, didGetFunctionDetails);
                    result.release();
                });
                remoteObject.release();
            });
        });

        contextMenu.appendSeparator();
    }

    if (WI.cssManager.canForcePseudoClasses() && domNode.attached) {
        contextMenu.appendSeparator();

        let pseudoSubMenu = contextMenu.appendSubMenuItem(WI.UIString("Forced Pseudo-Classes", "A context menu item to force (override) a DOM node's pseudo-classes"));

        let enabledPseudoClasses = domNode.enabledPseudoClasses;
        WI.CSSManager.ForceablePseudoClasses.forEach((pseudoClass) => {
            let enabled = enabledPseudoClasses.includes(pseudoClass);
            pseudoSubMenu.appendCheckboxItem(pseudoClass.capitalize(), () => {
                domNode.setPseudoClassEnabled(pseudoClass, !enabled);
            }, enabled);
        });
    }

    if (WI.domDebuggerManager.supported && isElement && !domNode.isPseudoElement() && attached) {
        contextMenu.appendSeparator();

        WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, domNode, options);
    }

    contextMenu.appendSeparator();

    if (!options.excludeLogElement && !domNode.isInUserAgentShadowTree() && !domNode.isPseudoElement()) {
        let label = isElement ? WI.UIString("Log Element", "Log (print) DOM element to Console") : WI.UIString("Log Node", "Log (print) DOM node to Console");
        contextMenu.appendItem(label, () => {
            WI.RemoteObject.resolveNode(domNode, WI.RuntimeManager.ConsoleObjectGroup).then((remoteObject) => {
                let text = isElement ? WI.UIString("Selected Element", "Selected DOM element") : WI.UIString("Selected Node", "Selected DOM node");
                const addSpecialUserLogClass = true;
                WI.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, addSpecialUserLogClass);
            });
        });
    }

    if (!options.excludeRevealElement && window.DOMAgent && attached) {
        contextMenu.appendItem(WI.repeatedUIString.revealInDOMTree(), () => {
            WI.domManager.inspectElement(domNode.id);
        });
    }

    if (WI.settings.experimentalEnableLayersTab.value && window.LayerTreeAgent && attached) {
        contextMenu.appendItem(WI.UIString("Reveal in Layers Tab", "Open Layers tab and select the layer corresponding to this node"), () => {
            WI.showLayersTab({nodeToSelect: domNode});
        });
    }

    if (window.PageAgent && attached) {
        contextMenu.appendItem(WI.UIString("Capture Screenshot", "Capture screenshot of the selected DOM node"), () => {
            PageAgent.snapshotNode(domNode.id, (error, dataURL) => {
                if (error) {
                    const target = WI.mainTarget;
                    const source = WI.ConsoleMessage.MessageSource.Other;
                    const level = WI.ConsoleMessage.MessageLevel.Error;
                    let consoleMessage = new WI.ConsoleMessage(target, source, level, error);
                    consoleMessage.shouldRevealConsole = true;

                    WI.consoleLogViewController.appendConsoleMessage(consoleMessage);
                    return;
                }

                WI.FileUtilities.save({
                    url: WI.FileUtilities.inspectorURLForFilename(WI.FileUtilities.screenshotString() + ".png"),
                    content: parseDataURL(dataURL).data,
                    base64Encoded: true,
                });
            });
        });
    }

    if (isElement && attached) {
        contextMenu.appendItem(WI.UIString("Scroll into View", "Scroll selected DOM node into view on the inspected web page"), () => {
            domNode.scrollIntoView();
        });
    }

    contextMenu.appendSeparator();
};

WI.appendContextMenuItemsForDOMNodeBreakpoints = function(contextMenu, domNode, options = {})
{
    if (contextMenu.__domBreakpointItemsAdded)
        return;

    contextMenu.__domBreakpointItemsAdded = true;

    let breakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode);

    contextMenu.appendSeparator();

    let subMenu = contextMenu.appendSubMenuItem(WI.UIString("Break on"));

    for (let type of Object.values(WI.DOMBreakpoint.Type)) {
        let label = WI.DOMBreakpointTreeElement.displayNameForType(type);
        let breakpoint = breakpoints.find((breakpoint) => breakpoint.type === type);

        subMenu.appendCheckboxItem(label, function() {
            if (breakpoint)
                WI.domDebuggerManager.removeDOMBreakpoint(breakpoint);
            else
                WI.domDebuggerManager.addDOMBreakpoint(new WI.DOMBreakpoint(domNode, type));
        }, !!breakpoint);
    }

    contextMenu.appendSeparator();

    if (breakpoints.length) {
        let shouldEnable = breakpoints.some((breakpoint) => breakpoint.disabled);
        contextMenu.appendItem(shouldEnable ? WI.UIString("Enable Breakpoint") : WI.UIString("Disable Breakpoint"), () => {
            for (let breakpoint of breakpoints)
                breakpoint.disabled = !shouldEnable;
        });

        contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => {
            for (let breakpoint of breakpoints)
                WI.domDebuggerManager.removeDOMBreakpoint(breakpoint);
        });

        contextMenu.appendSeparator();
    }

    let subtreeBreakpoints = WI.domDebuggerManager.domBreakpointsInSubtree(domNode);
    if (subtreeBreakpoints.length) {
        if (options.revealDescendantBreakpointsMenuItemHandler)
            contextMenu.appendItem(WI.UIString("Reveal Descendant Breakpoints"), options.revealDescendantBreakpointsMenuItemHandler);

        let subtreeShouldEnable = subtreeBreakpoints.some((breakpoint) => breakpoint.disabled);
        contextMenu.appendItem(subtreeShouldEnable ? WI.UIString("Enable Descendant Breakpoints") : WI.UIString("Disable Descendant Breakpoints"), () => {
            for (let subtreeBreakpoint of subtreeBreakpoints)
                subtreeBreakpoint.disabled = !subtreeShouldEnable;
        });

        contextMenu.appendItem(WI.UIString("Delete Descendant Breakpoints"), () => {
            for (let subtreeBreakpoint of subtreeBreakpoints)
                WI.domDebuggerManager.removeDOMBreakpoint(subtreeBreakpoint);
        });

        contextMenu.appendSeparator();
    }
};
