/*
* 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.HeapSnapshotInstanceDataGridNode = class HeapSnapshotInstanceDataGridNode extends WI.DataGridNode
{
    constructor(node, tree, edge, base)
    {
        // Don't treat strings as having child nodes, even if they have a Structure.
        let hasChildren = node.hasChildren && node.className !== "string";

        // FIXME: Make instance grid nodes copyable.
        super(node, {hasChildren, copyable: false});

        console.assert(node instanceof WI.HeapSnapshotNodeProxy);
        console.assert(!edge || edge instanceof WI.HeapSnapshotEdgeProxy);
        console.assert(!base || base instanceof WI.HeapSnapshotInstanceDataGridNode);

        this._node = node;
        this._tree = tree;
        this._edge = edge || null;
        this._base = base || null;

        if (hasChildren)
            this.addEventListener("populate", this._populate, this);
    }

    // Static

    static logHeapSnapshotNode(node)
    {
        node.shortestGCRootPath((gcRootPath) => {
            let text = WI.UIString("Heap Snapshot Object (%s)").format("@" + node.id);
            let addSpecialUserLogClass = !gcRootPath.length;

            if (gcRootPath.length) {
                gcRootPath = gcRootPath.slice().reverse();
                let windowIndex = gcRootPath.findIndex((x) => {
                    return x instanceof WI.HeapSnapshotNodeProxy && x.className === "Window";
                });

                let heapSnapshotRootPath = WI.HeapSnapshotRootPath.emptyPath();
                for (let i = windowIndex === -1 ? 0 : windowIndex; i < gcRootPath.length; ++i) {
                    let component = gcRootPath[i];
                    if (component instanceof WI.HeapSnapshotNodeProxy) {
                        if (component.className === "Window")
                            heapSnapshotRootPath = heapSnapshotRootPath.appendGlobalScopeName(component, "window");
                    } else if (component instanceof WI.HeapSnapshotEdgeProxy)
                        heapSnapshotRootPath = heapSnapshotRootPath.appendEdge(component);
                }

                if (heapSnapshotRootPath.isFullPathImpossible())
                    addSpecialUserLogClass = true;
                else
                    text = heapSnapshotRootPath.fullPath;
            }

            const shouldRevealConsole = true;

            if (node.className === "string") {
                WI.heapManager.getPreview(node, function(error, string, functionDetails, objectPreviewPayload) {
                    let remoteObject = error ? WI.RemoteObject.fromPrimitiveValue(undefined) : WI.RemoteObject.fromPrimitiveValue(string);
                    WI.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, addSpecialUserLogClass, shouldRevealConsole);
                });
            } else {
                WI.heapManager.getRemoteObject(node, WI.RuntimeManager.ConsoleObjectGroup, function(error, remoteObjectPayload) {
                    let remoteObject = error ? WI.RemoteObject.fromPrimitiveValue(undefined) : WI.RemoteObject.fromPayload(remoteObjectPayload, WI.assumingMainTarget());
                    WI.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, addSpecialUserLogClass, shouldRevealConsole);
                });
            }
        });
    }

    // Protected

    get data() { return this._node; }
    get node() { return this._node; }

    get propertyName()
    {
        if (!this._edge)
            return "";

        if (!this._propertyName)
            this._propertyName = WI.HeapSnapshotRootPath.pathComponentForIndividualEdge(this._edge);
        return this._propertyName;
    }

    createCells()
    {
        super.createCells();

        this.element.classList.add("instance");
    }

    createCellContent(columnIdentifier)
    {
        if (columnIdentifier === "retainedSize") {
            let subRetainedSize = false;
            if (this._base && !this._tree.alwaysShowRetainedSize) {
                if (this._isDominatedByNonBaseParent())
                    subRetainedSize = true;
                else if (!this._isDominatedByBase())
                    return emDash;
            }

            let size = this._node.retainedSize;
            let fragment = document.createDocumentFragment();
            let sizeElement = fragment.appendChild(document.createElement("span"));
            sizeElement.classList.add("size");
            sizeElement.textContent = Number.bytesToString(size);
            let fraction = size / this._tree._heapSnapshot.totalSize;
            let percentElement = fragment.appendChild(document.createElement("span"));
            percentElement.classList.add("percentage");
            percentElement.textContent = Number.percentageString(fraction);

            if (subRetainedSize) {
                sizeElement.classList.add("sub-retained");
                percentElement.classList.add("sub-retained");
            }

            return fragment;
        }

        if (columnIdentifier === "size")
            return Number.bytesToString(this._node.size);

        if (columnIdentifier === "className") {
            let {className, id, internal, isObjectType} = this._node;
            let containerElement = document.createElement("span");
            containerElement.addEventListener("contextmenu", this._contextMenuHandler.bind(this));

            let iconElement = containerElement.appendChild(document.createElement("img"));
            iconElement.classList.add("icon", WI.HeapSnapshotClusterContentView.iconStyleClassNameForClassName(className, internal, isObjectType));

            if (this._edge) {
                let nameElement = containerElement.appendChild(document.createElement("span"));
                let propertyName = this.propertyName;
                if (propertyName)
                    nameElement.textContent = propertyName + ": " + this._node.className + " ";
                else
                    nameElement.textContent = this._node.className + " ";
            }

            let idElement = containerElement.appendChild(document.createElement("span"));
            idElement.classList.add("object-id");
            idElement.textContent = "@" + id;
            idElement.addEventListener("click", WI.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, this._node));
            idElement.addEventListener("mouseover", this._mouseoverHandler.bind(this));

            let spacerElement = containerElement.appendChild(document.createElement("span"));
            spacerElement.textContent = " ";

            if (className === "Window" && this._node.dominatorNodeIdentifier === 0) {
                containerElement.append("Window ");
                this._populateWindowPreview(containerElement);
            } else
                this._populatePreview(containerElement);

            return containerElement;
        }

        return super.createCellContent(columnIdentifier);
    }

    sort()
    {
        let children = this.children;
        children.sort(this._tree._sortComparator);

        for (let i = 0; i < children.length; ++i) {
            children[i]._recalculateSiblings(i);
            children[i].sort();
        }
    }

    // Private

    _isDominatedByBase()
    {
        return this._node.dominatorNodeIdentifier === this._base.node.id;
    }

    _isDominatedByNonBaseParent()
    {
        for (let p = this.parent; p; p = p.parent) {
            if (p === this._base)
                return false;
            if (this._node.dominatorNodeIdentifier === p.node.id)
                return true;
        }

        return false;
    }

    _populate()
    {
        this.removeEventListener("populate", this._populate, this);

        function propertyName(edge) {
            return edge ? WI.HeapSnapshotRootPath.pathComponentForIndividualEdge(edge) : "";
        }

        this._node.retainedNodes((instances, edges) => {
            // Reference edge from instance so we can get it after sorting.
            for (let i = 0; i < instances.length; ++i)
                instances[i].__edge = edges[i];

            instances.sort((a, b) => {
                let fakeDataGridNodeA = {data: a, propertyName: propertyName(a.__edge)};
                let fakeDataGridNodeB = {data: b, propertyName: propertyName(b.__edge)};
                return this._tree._sortComparator(fakeDataGridNodeA, fakeDataGridNodeB);
            });

            // FIXME: This should gracefully handle a node that references many objects.

            for (let instance of instances) {
                if (instance.__edge && instance.__edge.isPrivateSymbol())
                    continue;

                this.appendChild(new WI.HeapSnapshotInstanceDataGridNode(instance, this._tree, instance.__edge, this._base || this));
            }
        });
    }

    _contextMenuHandler(event)
    {
        let contextMenu = WI.ContextMenu.createFromEvent(event);
        contextMenu.appendSeparator();
        contextMenu.appendItem(WI.UIString("Log Value"), WI.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, this._node));
    }

    _populateError(containerElement)
    {
        if (this._node.internal)
            return;

        let previewErrorElement = containerElement.appendChild(document.createElement("span"));
        previewErrorElement.classList.add("preview-error");
        previewErrorElement.textContent = WI.UIString("No preview available");
    }

    _populateWindowPreview(containerElement)
    {
        const objectGroup = undefined;
        WI.heapManager.getRemoteObject(this._node, objectGroup, (error, remoteObjectPayload) => {
            if (error) {
                this._populateError(containerElement);
                return;
            }

            function inspectedPage_window_getLocationHref() {
                return this.location.href;
            }

            let remoteObject = WI.RemoteObject.fromPayload(remoteObjectPayload, WI.assumingMainTarget());
            remoteObject.callFunctionJSON(inspectedPage_window_getLocationHref, undefined, (href) => {
                remoteObject.release();

                if (!href)
                    this._populateError(containerElement);
                else {
                    let primitiveRemoteObject = WI.RemoteObject.fromPrimitiveValue(href);
                    containerElement.appendChild(WI.FormattedValue.createElementForRemoteObject(primitiveRemoteObject));
                }
            });
        });
    }

    _populatePreview(containerElement)
    {
        WI.heapManager.getPreview(this._node, (error, string, functionDetails, objectPreviewPayload) => {
            if (error) {
                this._populateError(containerElement);
                return;
            }

            if (string) {
                if (this._node.className === "BigInt") {
                    let bigIntRemoteObject = WI.RemoteObject.createBigIntFromDescriptionString(string + "n");
                    containerElement.appendChild(WI.FormattedValue.createElementForRemoteObject(bigIntRemoteObject));
                } else {
                    let primitiveRemoteObject = WI.RemoteObject.fromPrimitiveValue(string);
                    containerElement.appendChild(WI.FormattedValue.createElementForRemoteObject(primitiveRemoteObject));
                }
                return;
            }

            if (functionDetails) {
                let {location, name, displayName} = functionDetails;
                let functionNameElement = containerElement.appendChild(document.createElement("span"));
                functionNameElement.classList.add("function-name");
                functionNameElement.textContent = name || displayName || WI.UIString("(anonymous function)");
                let sourceCode = WI.debuggerManager.scriptForIdentifier(location.scriptId, WI.assumingMainTarget());
                if (sourceCode) {
                    let locationElement = containerElement.appendChild(document.createElement("span"));
                    locationElement.classList.add("location");
                    let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber);
                    sourceCodeLocation.populateLiveDisplayLocationString(locationElement, "textContent", WI.SourceCodeLocation.ColumnStyle.Hidden, WI.SourceCodeLocation.NameStyle.Short);

                    const options = {
                        dontFloat: true,
                        useGoToArrowButton: true,
                        ignoreNetworkTab: true,
                        ignoreSearchTab: true,
                    };
                    let goToArrowButtonLink = WI.createSourceCodeLocationLink(sourceCodeLocation, options);
                    containerElement.appendChild(goToArrowButtonLink);
                }
                return;
            }

            if (objectPreviewPayload) {
                let objectPreview = WI.ObjectPreview.fromPayload(objectPreviewPayload);
                let previewElement = WI.FormattedValue.createObjectPreviewOrFormattedValueForObjectPreview(objectPreview);
                containerElement.appendChild(previewElement);
                return;
            }
        });
    }

    _mouseoverHandler(event)
    {
        let targetFrame = WI.Rect.rectFromClientRect(event.target.getBoundingClientRect());
        if (!targetFrame.size.width && !targetFrame.size.height)
            return;

        if (this._tree.popoverGridNode === this._node)
            return;

        this._tree.popoverGridNode = this._node;
        this._tree.popoverTargetElement = event.target;

        let popoverContentElement = document.createElement("div");
        popoverContentElement.classList.add("heap-snapshot", "heap-snapshot-instance-popover-content");

        function appendTitle(node) {
            let idElement = document.createElement("span");
            idElement.classList.add("object-id");
            idElement.textContent = "@" + node.id;
            idElement.addEventListener("click", WI.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, node));

            let title = popoverContentElement.appendChild(document.createElement("div"));
            title.classList.add("title");
            let localizedString = WI.UIString("Shortest property path to %s").format("@@@");
            let [before, after] = localizedString.split(/\s*@@@\s*/);
            title.append(before + " ", idElement, " " + after);
        }

        function appendPath(path) {
            let tableContainer = popoverContentElement.appendChild(document.createElement("div"));
            tableContainer.classList.add("table-container");

            let tableElement = tableContainer.appendChild(document.createElement("table"));

            path = path.slice().reverse();
            let windowIndex = path.findIndex((x) => {
                return x instanceof WI.HeapSnapshotNodeProxy && x.className === "Window";
            });

            let edge = null;
            for (let i = windowIndex === -1 ? 0 : windowIndex; i < path.length; ++i) {
                let component = path[i];
                if (component instanceof WI.HeapSnapshotEdgeProxy) {
                    edge = component;
                    continue;
                }
                appendPathRow(tableElement, edge, component);
                edge = null;
            }
        }

        function appendPathRow(tableElement, edge, node) {
            let tableRow = tableElement.appendChild(document.createElement("tr"));

            // Edge name.
            let pathDataElement = tableRow.appendChild(document.createElement("td"));
            pathDataElement.classList.add("edge-name");

            if (node.className === "Window")
                pathDataElement.textContent = "window";
            else if (edge) {
                let edgeString = stringifyEdge(edge);
                pathDataElement.textContent = typeof edgeString === "string" ? edgeString : emDash;
            } else
                pathDataElement.textContent = emDash;

            if (pathDataElement.textContent.length > 10)
                pathDataElement.title = pathDataElement.textContent;

            // Object.
            let objectDataElement = tableRow.appendChild(document.createElement("td"));
            objectDataElement.classList.add("object-data");

            let containerElement = objectDataElement.appendChild(document.createElement("div"));
            containerElement.classList.add("node");

            let iconElement = containerElement.appendChild(document.createElement("img"));
            iconElement.classList.add("icon", WI.HeapSnapshotClusterContentView.iconStyleClassNameForClassName(node.className, node.internal, node.isObjectType));

            let classNameElement = containerElement.appendChild(document.createElement("span"));
            classNameElement.textContent = sanitizeClassName(node.className) + " ";

            let idElement = containerElement.appendChild(document.createElement("span"));
            idElement.classList.add("object-id");
            idElement.textContent = "@" + node.id;
            idElement.addEventListener("click", WI.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, node));

            // Extra.
            if (node.className === "Function") {
                let goToArrowPlaceHolderElement = containerElement.appendChild(document.createElement("span"));
                goToArrowPlaceHolderElement.style.display = "inline-block";
                goToArrowPlaceHolderElement.style.width = "10px";
                WI.heapManager.getPreview(node, function(error, string, functionDetails, objectPreviewPayload) {
                    if (functionDetails) {
                        let location = functionDetails.location;
                        let sourceCode = WI.debuggerManager.scriptForIdentifier(location.scriptId, WI.assumingMainTarget());
                        if (sourceCode) {
                            let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber);

                            const options = {
                                dontFloat: true,
                                useGoToArrowButton: true,
                                ignoreNetworkTab: true,
                                ignoreSearchTab: true,
                            };
                            let goToArrowButtonLink = WI.createSourceCodeLocationLink(sourceCodeLocation, options);
                            containerElement.replaceChild(goToArrowButtonLink, goToArrowPlaceHolderElement);
                        }
                    }
                });
            }
        }

        function sanitizeClassName(className) {
            if (className.endsWith("LexicalEnvironment"))
                return WI.UIString("Scope");
            return className;
        }

        function stringifyEdge(edge) {
            switch (edge.type) {
            case WI.HeapSnapshotEdgeProxy.EdgeType.Property:
            case WI.HeapSnapshotEdgeProxy.EdgeType.Variable:
                if (/^(?![0-9])\w+$/.test(edge.data))
                    return edge.data;
                return "[" + doubleQuotedString(edge.data) + "]";
            case WI.HeapSnapshotEdgeProxy.EdgeType.Index:
                return "[" + edge.data + "]";
            case WI.HeapSnapshotEdgeProxy.EdgeType.Internal:
            default:
                return null;
            }
        }

        this._node.shortestGCRootPath((path) => {
            if (!this._tree.visible)
                return;

            if (path.length) {
                appendTitle(this._node);
                appendPath(path);
            } else if (this._node.gcRoot) {
                let textElement = popoverContentElement.appendChild(document.createElement("div"));
                textElement.textContent = WI.UIString("This object is a root");
            } else {
                let emptyElement = popoverContentElement.appendChild(document.createElement("div"));
                emptyElement.textContent = WI.UIString("This object is referenced by internal objects");
            }

            this._tree.popover.presentNewContentWithFrame(popoverContentElement, targetFrame.pad(2), [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
        });
    }
};
