/*
 * Copyright (C) 2013 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.CallFrame = class CallFrame
{
    constructor(target, {id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode, isTailDeleted, blackboxed} = {})
    {
        console.assert(target instanceof WI.Target, target);
        console.assert(!sourceCodeLocation || sourceCodeLocation instanceof WI.SourceCodeLocation, sourceCodeLocation);
        console.assert(!thisObject || thisObject instanceof WI.RemoteObject, thisObject);
        console.assert(!scopeChain || scopeChain.every((item) => item instanceof WI.ScopeChainNode), scopeChain);

        this._isConsoleEvaluation = sourceCodeLocation && isWebInspectorConsoleEvaluationScript(sourceCodeLocation.sourceCode.sourceURL);
        if (this._isConsoleEvaluation) {
            functionName = WI.UIString("Console Evaluation");
            programCode = true;
        }

        this._target = target;
        this._id = id || null;
        this._sourceCodeLocation = sourceCodeLocation || null;
        this._functionName = functionName || "";
        this._thisObject = thisObject || null;
        this._scopeChain = scopeChain || [];
        this._nativeCode = nativeCode || false;
        this._programCode = programCode || false;
        this._isTailDeleted = isTailDeleted || false;
        this._blackboxed = blackboxed || false;
    }

    // Public

    get target() { return this._target; }
    get id() { return this._id; }
    get sourceCodeLocation() { return this._sourceCodeLocation; }
    get functionName() { return this._functionName; }
    get nativeCode() { return this._nativeCode; }
    get programCode() { return this._programCode; }
    get thisObject() { return this._thisObject; }
    get scopeChain() { return this._scopeChain; }
    get isTailDeleted() { return this._isTailDeleted; }
    get blackboxed() { return this._blackboxed; }
    get isConsoleEvaluation() { return this._isConsoleEvaluation; }

    get displayName()
    {
        return this._functionName || WI.UIString("(anonymous function)");
    }

    isEqual(other)
    {
        if (!other)
            return false;

        if (this._sourceCodeLocation && other._sourceCodeLocation)
            return this._sourceCodeLocation.isEqual(other._sourceCodeLocation);

        return false;
    }

    saveIdentityToCookie()
    {
        // Do nothing. The call frame is torn down when the inspector closes, and
        // we shouldn't restore call frame content views across debugger pauses.
    }

    collectScopeChainVariableNames(callback)
    {
        let result = ["this", "__proto__"];

        var pendingRequests = this._scopeChain.length;

        function propertiesCollected(properties)
        {
            for (var i = 0; properties && i < properties.length; ++i)
                result.push(properties[i].name);

            if (--pendingRequests)
                return;

            callback(result);
        }

        for (var i = 0; i < this._scopeChain.length; ++i)
            this._scopeChain[i].objects[0].getPropertyDescriptors(propertiesCollected);
    }

    mergedScopeChain()
    {
        let mergedScopes = [];

        // Scopes list goes from top/local (1) to bottom/global (5)
        //   [scope1, scope2, scope3, scope4, scope5]
        let scopes = this._scopeChain.slice();

        // Merge similiar scopes. Some function call frames may have multiple
        // top level closure scopes (one for `var`s one for `let`s) that can be
        // combined to a single scope of variables. Go in reverse order so we
        // merge the first two closure scopes with the same name. Also mark
        // the first time we see a new name, so we know the base for the name.
        //   [scope1&2, scope3, scope4, scope5]
        //      foo      bar     GLE    global
        let lastMarkedHash = null;
        function markAsBaseIfNeeded(scope) {
            if (!scope.hash)
                return false;
            if (scope.type !== WI.ScopeChainNode.Type.Closure)
                return false;
            if (scope.hash === lastMarkedHash)
                return false;
            lastMarkedHash = scope.hash;
            scope.__baseClosureScope = true;
            return true;
        }

        function shouldMergeClosureScopes(youngScope, oldScope, lastMerge) {
            if (!youngScope || !oldScope)
                return false;

            // Don't merge unknown locations.
            if (!youngScope.hash || !oldScope.hash)
                return false;

            // Only merge closure scopes.
            if (youngScope.type !== WI.ScopeChainNode.Type.Closure)
                return false;
            if (oldScope.type !== WI.ScopeChainNode.Type.Closure)
                return false;

            // Don't merge if they are not the same.
            if (youngScope.hash !== oldScope.hash)
                return false;

            // Don't merge if there was already a merge.
            if (lastMerge && youngScope.hash === lastMerge.hash)
                return false;

            return true;
        }

        let lastScope = null;
        let lastMerge = null;
        for (let i = scopes.length - 1; i >= 0; --i) {
            let scope = scopes[i];
            markAsBaseIfNeeded(scope);
            if (shouldMergeClosureScopes(scope, lastScope, lastMerge)) {
                console.assert(lastScope.__baseClosureScope);
                let type = WI.ScopeChainNode.Type.Closure;
                let objects = lastScope.objects.concat(scope.objects);
                let merged = new WI.ScopeChainNode(type, objects, scope.name, scope.location);
                merged.__baseClosureScope = true;
                console.assert(objects.length === 2);

                mergedScopes.pop(); // Remove the last.
                mergedScopes.push(merged); // Add the merged scope.

                lastMerge = merged;
                lastScope = null;
            } else {
                mergedScopes.push(scope);

                lastMerge = null;
                lastScope = scope;
            }
        }

        mergedScopes = mergedScopes.reverse();

        // Mark the first Closure as Local if the name matches this call frame.
        for (let scope of mergedScopes) {
            if (scope.type === WI.ScopeChainNode.Type.Closure) {
                if (scope.name === this._functionName)
                    scope.convertToLocalScope();
                break;
            }
        }

        return mergedScopes;
    }

    // Static

    static functionNameFromPayload(payload)
    {
        let functionName = payload.functionName;
        if (functionName === "global code")
            return WI.UIString("Global Code");
        if (functionName === "eval code")
            return WI.UIString("Eval Code");
        if (functionName === "module code")
            return WI.UIString("Module Code");
        return functionName;
    }

    static programCodeFromPayload(payload)
    {
        return payload.functionName.endsWith(" code");
    }

    static fromDebuggerPayload(target, payload, scopeChain, sourceCodeLocation)
    {
        return new WI.CallFrame(target, {
            id: payload.callFrameId,
            sourceCodeLocation,
            functionName: WI.CallFrame.functionNameFromPayload(payload),
            thisObject: WI.RemoteObject.fromPayload(payload.this, target),
            scopeChain,
            programCode: WI.CallFrame.programCodeFromPayload(payload),
            isTailDeleted: payload.isTailDeleted,
            blackboxed: sourceCodeLocation && !!WI.debuggerManager.blackboxDataForSourceCode(sourceCodeLocation.sourceCode),
        });
    }

    static fromPayload(target, payload)
    {
        console.assert(payload);

        let {url, scriptId} = payload;
        let nativeCode = false;
        let sourceCodeLocation = null;

        if (url === "[native code]") {
            nativeCode = true;
            url = null;
        } else if (url || scriptId) {
            let sourceCode = null;
            if (scriptId) {
                sourceCode = WI.debuggerManager.scriptForIdentifier(scriptId, target);
                if (sourceCode && sourceCode.resource)
                    sourceCode = sourceCode.resource;
            }
            if (!sourceCode)
                sourceCode = WI.networkManager.resourcesForURL(url).firstValue;
            if (!sourceCode)
                sourceCode = WI.debuggerManager.scriptsForURL(url, target)[0];

            if (sourceCode) {
                // The lineNumber is 1-based, but we expect 0-based.
                let lineNumber = payload.lineNumber - 1;
                sourceCodeLocation = sourceCode.createLazySourceCodeLocation(lineNumber, payload.columnNumber);
            } else {
                // Treat this as native code if we were unable to find a source.
                console.assert(!url, "We should have detected source code for something with a url");
                nativeCode = true;
                url = null;
            }
        }

        return new WI.CallFrame(target, {
            sourceCodeLocation,
            functionName: WI.CallFrame.functionNameFromPayload(payload),
            nativeCode,
            programCode: WI.CallFrame.programCodeFromPayload(payload),
            blackboxed: sourceCodeLocation && !!WI.debuggerManager.blackboxDataForSourceCode(sourceCodeLocation.sourceCode),
        });
    }
};
