/*
* 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.ProfileDataGridNode = class ProfileDataGridNode extends WI.DataGridNode
{
    constructor(callingContextTreeNode, tree)
    {
        super(callingContextTreeNode, false);

        this._node = callingContextTreeNode;
        this._tree = tree;

        this._childrenToChargeToSelf = new Set;
        this._extraSelfTimeFromChargedChildren = 0;

        // FIXME: Make profile data grid nodes copyable.
        this.copyable = false;

        this.addEventListener("populate", this._populate, this);

        this._updateChildrenForModifiers();
        this._recalculateData();
    }

    // Public

    get callingContextTreeNode() { return this._node; }

    displayName()
    {
        let title = this._node.name;
        if (!title)
            return WI.UIString("(anonymous function)");
        if (title === "(program)")
            return WI.UIString("(program)");
        return title;
    }

    iconClassName()
    {
        let script = WI.debuggerManager.scriptForIdentifier(this._node.sourceID, WI.assumingMainTarget());
        if (!script || !script.url)
            return "native-icon";
        if (this._node.name === "(program)")
            return "program-icon";
        return "function-icon";
    }

    // Protected

    get data()
    {
        return this._data;
    }

    createCellContent(columnIdentifier, cell)
    {
        switch (columnIdentifier) {
        case "totalTime":
            return this._totalTimeContent();
        case "selfTime":
            return Number.secondsToMillisecondsString(this._data.selfTime);
        case "function":
            return this._displayContent();
        }

        return super.createCellContent(columnIdentifier, cell);
    }

    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();
        }
    }

    refresh()
    {
        this._updateChildrenForModifiers();
        this._recalculateData();

        super.refresh();
    }

    appendContextMenuItems(contextMenu)
    {
        let disableFocus = this === this._tree.currentFocusNode;
        contextMenu.appendItem(WI.UIString("Focus on Subtree"), () => {
            this._tree.addFocusNode(this);
        }, disableFocus);

        // FIXME: <https://webkit.org/b/155072> Web Inspector: Charge to Caller should work with Bottom Up Profile View
        let disableChargeToCaller = this._tree.callingContextTree.type === WI.CallingContextTree.Type.BottomUp;
        contextMenu.appendItem(WI.UIString("Charge \u201C%s\u201D to Callers").format(this.displayName()), () => {
            this._tree.addModifier({type: WI.ProfileDataGridTree.ModifierType.ChargeToCaller, source: this._node});
        }, disableChargeToCaller);

        contextMenu.appendSeparator();
    }

    // Protected

    filterableDataForColumn(columnIdentifier)
    {
        if (columnIdentifier === "function") {
            let filterableData = [this.displayName()];
            let script = WI.debuggerManager.scriptForIdentifier(this._node.sourceID, WI.assumingMainTarget());
            if (script && script.url && this._node.line >= 0 && this._node.column >= 0)
                filterableData.push(script.url);
            return filterableData;
        }

        return super.filterableDataForColumn(columnIdentifier);
    }

    // Private

    _updateChildrenForModifiers()
    {
        // NOTE: This currently assumes we either add modifiers or remove them all.
        // This doesn't handle removing a single modifier and re-inserting a single child.

        // FIXME: <https://webkit.org/b/155072> Web Inspector: Charge to Caller should work with Bottom Up Profile View
        let isBottomUp = this._tree.callingContextTree.type === WI.CallingContextTree.Type.BottomUp;
        if (!this._tree.hasModifiers() || isBottomUp) {
            // Add back child data grid nodes that were previously charged to us.
            if (!this.shouldRefreshChildren && this._childrenToChargeToSelf.size) {
                for (let child of this._childrenToChargeToSelf) {
                    console.assert(child.hasStackTraceInTimeRange(this._tree.startTime, this._tree.endTime));
                    this.appendChild(new WI.ProfileDataGridNode(child, this._tree));
                }

                this.sort();
            }

            this._extraSelfTimeFromChargedChildren = 0;
            this._childrenToChargeToSelf.clear();
            this.hasChildren = this._node.hasChildrenInTimeRange(this._tree.startTime, this._tree.endTime);
            return;
        }

        this._extraSelfTimeFromChargedChildren = 0;
        this._childrenToChargeToSelf.clear();

        let hasNonChargedChild = false;
        this._node.forEachChild((child) => {
            if (child.hasStackTraceInTimeRange(this._tree.startTime, this._tree.endTime)) {
                for (let {type, source} of this._tree.modifiers) {
                    if (type === WI.ProfileDataGridTree.ModifierType.ChargeToCaller) {
                        if (child.equals(source)) {
                            this._childrenToChargeToSelf.add(child);
                            this._extraSelfTimeFromChargedChildren += child.filteredTimestampsAndDuration(this._tree.startTime, this._tree.endTime).duration;
                            continue;
                        }
                    }
                    hasNonChargedChild = true;
                }
            }
        });

        this.hasChildren = hasNonChargedChild;

        // Remove child data grid nodes that have been charged to us.
        if (!this.shouldRefreshChildren && this._childrenToChargeToSelf.size) {
            for (let childDataGridNode of this.children) {
                if (this._childrenToChargeToSelf.has(childDataGridNode.callingContextTreeNode))
                    this.removeChild(childDataGridNode);
            }
        }
    }

    _recalculateData()
    {
        let {timestamps, duration} = this._node.filteredTimestampsAndDuration(this._tree.startTime, this._tree.endTime);
        let {leafTimestamps, leafDuration} = this._node.filteredLeafTimestampsAndDuration(this._tree.startTime, this._tree.endTime);

        let totalTime = duration;
        let selfTime = leafDuration + this._extraSelfTimeFromChargedChildren;
        let fraction = totalTime / this._tree.totalSampleTime;

        this._data = {totalTime, selfTime, fraction};
    }

    _totalTimeContent()
    {
        let {totalTime, fraction} = this._data;

        let fragment = document.createDocumentFragment();
        let timeElement = fragment.appendChild(document.createElement("span"));
        timeElement.classList.add("time");
        timeElement.textContent = Number.secondsToMillisecondsString(totalTime);
        let percentElement = fragment.appendChild(document.createElement("span"));
        percentElement.classList.add("percentage");
        percentElement.textContent = Number.percentageString(fraction);
        return fragment;
    }

    _displayContent()
    {
        let title = this.displayName();
        let iconClassName = this.iconClassName();

        let fragment = document.createDocumentFragment();
        let iconElement = fragment.appendChild(document.createElement("img"));
        iconElement.classList.add("icon", iconClassName);
        let titleElement = fragment.appendChild(document.createElement("span"));
        titleElement.textContent = title;

        let script = WI.debuggerManager.scriptForIdentifier(this._node.sourceID, WI.assumingMainTarget());
        if (script && script.url && this._node.line >= 0 && this._node.column >= 0) {
            // Convert from 1-based line and column to 0-based.
            let sourceCodeLocation = script.createSourceCodeLocation(this._node.line - 1, this._node.column - 1);

            let locationElement = fragment.appendChild(document.createElement("span"));
            locationElement.classList.add("location");
            sourceCodeLocation.populateLiveDisplayLocationString(locationElement, "textContent", WI.SourceCodeLocation.ColumnStyle.Hidden, WI.SourceCodeLocation.NameStyle.Short);

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

        return fragment;
    }

    _populate()
    {
        if (!this.shouldRefreshChildren)
            return;

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

        this._node.forEachChild((child) => {
            if (!this._childrenToChargeToSelf.has(child)) {
                if (child.hasStackTraceInTimeRange(this._tree.startTime, this._tree.endTime))
                    this.appendChild(new WI.ProfileDataGridNode(child, this._tree));
            }
        });

        this.sort();
    }
};
