/*
 * Copyright (C) 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.StackTrace = class StackTrace
{
    constructor(callFrames, topCallFrameIsBoundary, truncated, parentStackTrace)
    {
        console.assert(callFrames && callFrames.every((callFrame) => callFrame instanceof WI.CallFrame));

        this._callFrames = callFrames;
        this._topCallFrameIsBoundary = topCallFrameIsBoundary || false;
        this._truncated = truncated || false;
        this._parentStackTrace = parentStackTrace || null;
    }

    // Static

    static fromPayload(target, payload)
    {
        let result = null;
        let previousStackTrace = null;

        while (payload) {
            let callFrames = payload.callFrames.map((x) => WI.CallFrame.fromPayload(target, x));
            let stackTrace = new WI.StackTrace(callFrames, payload.topCallFrameIsBoundary, payload.truncated);
            if (!result)
                result = stackTrace;
            if (previousStackTrace)
                previousStackTrace._parentStackTrace = stackTrace;

            previousStackTrace = stackTrace;
            payload = payload.parentStackTrace;
        }

        return result;
    }

    static fromString(target, stack)
    {
        let callFrames = WI.StackTrace._parseStackTrace(stack);
        return WI.StackTrace.fromPayload(target, {callFrames});
    }

    // May produce false negatives; must not produce any false positives.
    // It may return false on a valid stack trace, but it will never return true on an invalid stack trace.
    static isLikelyStackTrace(stack)
    {
        // This function runs for every logged string. It penalizes the performance.
        // As most logged strings are not stack traces, exit as early as possible.
        const smallestPossibleStackTraceLength = "http://a.bc/:9:1".length;
        if (stack.length < smallestPossibleStackTraceLength.length * 2)
            return false;

        const approximateStackLengthOf50Items = 5000;
        if (stack.length > approximateStackLengthOf50Items)
            return false;

        if (/^[^a-z$_]/i.test(stack[0]))
            return false;

        if (!WI.StackTrace._likelyStackTraceRegex) {
            const reasonablyLongProtocolLength = 10;
            const reasonablyLongLineLength = 500;
            const reasonablyLongNativeMethodLength = 120;
            const stackTraceLine = `(global code|eval code|module code|\\w+)?([^:]{1,${reasonablyLongProtocolLength}}://[^:]{1,${reasonablyLongLineLength}}:\\d+:\\d+|[^@]{1,${reasonablyLongNativeMethodLength}}@\\[native code\\])`;
            WI.StackTrace._likelyStackTraceRegex = new RegExp(`^${stackTraceLine}([\\n\\r]${stackTraceLine})+$`);
        }

        WI.StackTrace._likelyStackTraceRegex.lastIndex = 0;
        return WI.StackTrace._likelyStackTraceRegex.test(stack);
    }

    static _parseStackTrace(stack)
    {
        var lines = stack.split(/\n/g);
        var result = [];

        for (var line of lines) {
            var functionName = "";
            var url = "";
            var lineNumber = 0;
            var columnNumber = 0;
            var atIndex = line.indexOf("@");

            if (atIndex !== -1) {
                functionName = line.slice(0, atIndex);
                ({url, lineNumber, columnNumber} = WI.StackTrace._parseLocation(line.slice(atIndex + 1)));
            } else if (line.includes("/"))
                ({url, lineNumber, columnNumber} = WI.StackTrace._parseLocation(line));
            else
                functionName = line;

            result.push({functionName, url, lineNumber, columnNumber});
        }

        return result;
    }

    static _parseLocation(locationString)
    {
        var result = {url: "", lineNumber: 0, columnNumber: 0};
        var locationRegEx = /(.+?)(?::(\d+)(?::(\d+))?)?$/;
        var matched = locationString.match(locationRegEx);

        if (!matched)
            return result;

        result.url = matched[1];

        if (matched[2])
            result.lineNumber = parseInt(matched[2]);

        if (matched[3])
            result.columnNumber = parseInt(matched[3]);

        return result;
    }

    // Public

    get callFrames()
    {
        return this._callFrames;
    }

    get firstNonNativeCallFrame()
    {
        for (let frame of this._callFrames) {
            if (!frame.nativeCode)
                return frame;
        }

        return null;
    }

    get firstNonNativeNonAnonymousCallFrame()
    {
        for (let frame of this._callFrames) {
            if (frame.nativeCode)
                continue;
            if (frame.sourceCodeLocation) {
                let sourceCode = frame.sourceCodeLocation.sourceCode;
                if (sourceCode instanceof WI.Script && sourceCode.anonymous)
                    continue;
            }
            return frame;
        }

        return null;
    }

    get topCallFrameIsBoundary() { return this._topCallFrameIsBoundary; }
    get truncated() { return this._truncated; }
    get parentStackTrace() { return this._parentStackTrace; }
};
