/*
 * Copyright (C) 2013, 2015 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.CallFrameTreeElement = class CallFrameTreeElement extends WI.GeneralTreeElement
{
    constructor(callFrame, isAsyncBoundaryCallFrame)
    {
        console.assert(callFrame instanceof WI.CallFrame);

        let className = WI.CallFrameView.iconClassNameForCallFrame(callFrame);
        let title = callFrame.functionName || WI.UIString("(anonymous function)");
        const subtitle = null;
        super(["call-frame", className], title, subtitle, callFrame);

        this._callFrame = callFrame;
        this._isActiveCallFrame = false;

        this._isAsyncBoundaryCallFrame = isAsyncBoundaryCallFrame;
         if (this._isAsyncBoundaryCallFrame) {
            this.addClassName("async-boundary");
            this.selectable = false;
         }

        if (this._callFrame.nativeCode || !this._callFrame.sourceCodeLocation) {
            this.subtitle = "";
            this.selectable = false;
            return;
        }

        let displayScriptURL = this._callFrame.sourceCodeLocation.displaySourceCode.url;
        if (displayScriptURL) {
            this.subtitle = document.createElement("span");
            this._callFrame.sourceCodeLocation.populateLiveDisplayLocationString(this.subtitle, "textContent");
            // Set the tooltip on the entire tree element in onattach, once the element is created.
            this.tooltipHandledSeparately = true;
        }

        this._isBlackboxed = WI.debuggerManager.blackboxDataForSourceCode(this._callFrame.sourceCodeLocation.sourceCode);
        if (this._isBlackboxed) {
            this.addClassName("blackboxed");
            this.tooltipHandledSeparately = true;
        }
    }

    // Public

    get callFrame() { return this._callFrame; }
    get isAsyncBoundaryCallFrame() { return this._isAsyncBoundaryCallFrame; }

    get isActiveCallFrame()
    {
        return this._isActiveCallFrame;
    }

    set isActiveCallFrame(x)
    {
        if (this._isActiveCallFrame === x)
            return;

        this._isActiveCallFrame = x;
        this._updateStatus();
    }

    // Protected

    onattach()
    {
        super.onattach();

        console.assert(this.element);

        if (this.tooltipHandledSeparately) {
            let tailCallSuffix = "";
            if (this._callFrame.isTailDeleted)
                tailCallSuffix = " " + WI.UIString("(Tail Call)");
            let tooltipPrefix = this.mainTitle + tailCallSuffix + "\n";

            let tooltipSuffix = "";
            if (this._isBlackboxed)
                tooltipSuffix += "\n\n" + WI.UIString("Script ignored due to blackbox");

            this._callFrame.sourceCodeLocation.populateLiveDisplayLocationTooltip(this.element, tooltipPrefix, tooltipSuffix);
        }

        this._updateStatus();
    }

    populateContextMenu(contextMenu, event)
    {
        if (this._callFrame.sourceCodeLocation)
            WI.appendContextMenuItemsForSourceCode(contextMenu, this._callFrame.sourceCodeLocation);

        super.populateContextMenu(contextMenu, event);
    }

    // Private

    _updateStatus()
    {
        if (!this.element)
            return;

        if (!this._isActiveCallFrame) {
            this.status = null;
            return;
        }

        if (!this._statusImageElement)
            this._statusImageElement = WI.ImageUtilities.useSVGSymbol("Images/ActiveCallFrame.svg", "status-image");
        this.status = this._statusImageElement;
    }
};
