/*
 * 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.TimelineRecording = class TimelineRecording extends WI.Object
{
    constructor(identifier, displayName, instruments)
    {
        super();

        this._identifier = identifier;
        this._timelines = new Map;
        this._displayName = displayName;
        this._capturing = false;
        this._readonly = false;
        this._imported = false;
        this._instruments = instruments || [];

        this._startTime = NaN;
        this._endTime = NaN;
        this._discontinuities = null;

        this._exportDataRecords = null;
        this._exportDataMarkers = null;
        this._exportDataMemoryPressureEvents = null;
        this._exportDataSampleStackTraces = null;
        this._exportDataSampleDurations = null;

        this._topDownCallingContextTree = new WI.CallingContextTree(WI.CallingContextTree.Type.TopDown);
        this._bottomUpCallingContextTree = new WI.CallingContextTree(WI.CallingContextTree.Type.BottomUp);
        this._topFunctionsTopDownCallingContextTree = new WI.CallingContextTree(WI.CallingContextTree.Type.TopFunctionsTopDown);
        this._topFunctionsBottomUpCallingContextTree = new WI.CallingContextTree(WI.CallingContextTree.Type.TopFunctionsBottomUp);

        for (let type of WI.TimelineManager.availableTimelineTypes()) {
            let timeline = WI.Timeline.create(type);
            this._timelines.set(type, timeline);
            timeline.addEventListener(WI.Timeline.Event.TimesUpdated, this._timelineTimesUpdated, this);
        }

        // For legacy backends, we compute the elapsed time of records relative to this timestamp.
        this._legacyFirstRecordedTimestamp = NaN;

        this.reset(true);
    }

    // Static

    static sourceCodeTimelinesSupported()
    {
        // FIXME: Support Network Timeline in ServiceWorker.
        return WI.sharedApp.debuggableType === WI.DebuggableType.Web;
    }

    // Import / Export

    static import(identifier, json, displayName)
    {
        let {startTime, endTime, discontinuities, instrumentTypes, records, markers, memoryPressureEvents, sampleStackTraces, sampleDurations} = json;
        let importedDisplayName = WI.UIString("Imported - %s").format(displayName);
        let instruments = instrumentTypes.map((type) => WI.Instrument.createForTimelineType(type));
        let recording = new WI.TimelineRecording(identifier, importedDisplayName, instruments);

        recording._readonly = true;
        recording._imported = true;
        recording._startTime = startTime;
        recording._endTime = endTime;
        recording._discontinuities = discontinuities;

        recording.initializeCallingContextTrees(sampleStackTraces, sampleDurations);

        for (let recordJSON of records) {
            let record = WI.TimelineRecord.fromJSON(recordJSON);
            if (record) {
                recording.addRecord(record);

                if (record instanceof WI.ScriptTimelineRecord)
                    record.profilePayload = recording._topDownCallingContextTree.toCPUProfilePayload(record.startTime, record.endTime);
            }
        }

        for (let memoryPressureJSON of memoryPressureEvents) {
            let memoryPressureEvent = WI.MemoryPressureEvent.fromJSON(memoryPressureJSON);
            if (memoryPressureEvent)
                recording.addMemoryPressureEvent(memoryPressureEvent);
        }

        // Add markers once we've transitioned the active recording.
        setTimeout(() => {
            recording.__importing = true;

            for (let markerJSON of markers) {
                let marker = WI.TimelineMarker.fromJSON(markerJSON);
                if (marker)
                    recording.addEventMarker(marker);
            }

            recording.__importing = false;
        });

        return recording;
    }

    exportData()
    {
        console.assert(this.canExport(), "Attempted to export a recording which should not be exportable.");

        // FIXME: Overview data (sourceCodeTimelinesMap).
        // FIXME: Record hierarchy (parent / child relationship) is lost.

        return {
            displayName: this._displayName,
            startTime: this._startTime,
            endTime: this._endTime,
            discontinuities: this._discontinuities,
            instrumentTypes: this._instruments.map((instrument) => instrument.timelineRecordType),
            records: this._exportDataRecords,
            markers: this._exportDataMarkers,
            memoryPressureEvents: this._exportDataMemoryPressureEvents,
            sampleStackTraces: this._exportDataSampleStackTraces,
            sampleDurations: this._exportDataSampleDurations,
        };
    }

    // Public

    get displayName() { return this._displayName; }
    get identifier() { return this._identifier; }
    get timelines() { return this._timelines; }
    get instruments() { return this._instruments; }
    get capturing() { return this._capturing; }
    get readonly() { return this._readonly; }
    get imported() { return this._imported; }
    get startTime() { return this._startTime; }
    get endTime() { return this._endTime; }

    get topDownCallingContextTree() { return this._topDownCallingContextTree; }
    get bottomUpCallingContextTree() { return this._bottomUpCallingContextTree; }
    get topFunctionsTopDownCallingContextTree() { return this._topFunctionsTopDownCallingContextTree; }
    get topFunctionsBottomUpCallingContextTree() { return this._topFunctionsBottomUpCallingContextTree; }

    start(initiatedByBackend)
    {
        console.assert(!this._capturing, "Attempted to start an already started session.");
        console.assert(!this._readonly, "Attempted to start a readonly session.");

        this._capturing = true;

        for (let instrument of this._instruments)
            instrument.startInstrumentation(initiatedByBackend);
    }

    stop(initiatedByBackend)
    {
        console.assert(this._capturing, "Attempted to stop an already stopped session.");
        console.assert(!this._readonly, "Attempted to stop a readonly session.");

        this._capturing = false;

        for (let instrument of this._instruments)
            instrument.stopInstrumentation(initiatedByBackend);
    }

    saveIdentityToCookie()
    {
        // Do nothing. Timeline recordings are not persisted when the inspector is
        // re-opened, so do not attempt to restore by identifier or display name.
    }

    isEmpty()
    {
        for (var timeline of this._timelines.values()) {
            if (timeline.records.length)
                return false;
        }

        return true;
    }

    unloaded(importing)
    {
        console.assert(importing || !this.isEmpty(), "Shouldn't unload an empty recording; it should be reused instead.");

        this._readonly = true;

        this.dispatchEventToListeners(WI.TimelineRecording.Event.Unloaded);
    }

    reset(suppressEvents)
    {
        console.assert(!this._readonly, "Can't reset a read-only recording.");

        this._sourceCodeTimelinesMap = new Map;

        this._startTime = NaN;
        this._endTime = NaN;
        this._discontinuities = [];

        this._exportDataRecords = [];
        this._exportDataMarkers = []
        this._exportDataMemoryPressureEvents = [];
        this._exportDataSampleStackTraces = [];
        this._exportDataSampleDurations = [];

        this._topDownCallingContextTree.reset();
        this._bottomUpCallingContextTree.reset();
        this._topFunctionsTopDownCallingContextTree.reset();
        this._topFunctionsBottomUpCallingContextTree.reset();

        for (var timeline of this._timelines.values())
            timeline.reset(suppressEvents);

        WI.RenderingFrameTimelineRecord.resetFrameIndex();

        if (!suppressEvents) {
            this.dispatchEventToListeners(WI.TimelineRecording.Event.Reset);
            this.dispatchEventToListeners(WI.TimelineRecording.Event.TimesUpdated);
        }
    }

    get sourceCodeTimelines()
    {
        let timelines = [];
        for (let timelinesForSourceCode of this._sourceCodeTimelinesMap.values())
            timelines = timelines.concat(Array.from(timelinesForSourceCode.values()));
        return timelines;
    }

    timelineForInstrument(instrument)
    {
        return this._timelines.get(instrument.timelineRecordType);
    }

    instrumentForTimeline(timeline)
    {
        return this._instruments.find((instrument) => instrument.timelineRecordType === timeline.type);
    }

    timelineForRecordType(recordType)
    {
        return this._timelines.get(recordType);
    }

    addInstrument(instrument)
    {
        console.assert(instrument instanceof WI.Instrument, instrument);
        console.assert(!this._instruments.includes(instrument), this._instruments, instrument);

        this._instruments.push(instrument);

        this.dispatchEventToListeners(WI.TimelineRecording.Event.InstrumentAdded, {instrument});
    }

    removeInstrument(instrument)
    {
        console.assert(instrument instanceof WI.Instrument, instrument);
        console.assert(this._instruments.includes(instrument), this._instruments, instrument);

        this._instruments.remove(instrument);

        this.dispatchEventToListeners(WI.TimelineRecording.Event.InstrumentRemoved, {instrument});
    }

    addEventMarker(marker)
    {
        this._exportDataMarkers.push(marker);

        if (!this._capturing && !this.__importing)
            return;

        this.dispatchEventToListeners(WI.TimelineRecording.Event.MarkerAdded, {marker});
    }

    addRecord(record)
    {
        this._exportDataRecords.push(record);

        let timeline = this._timelines.get(record.type);
        console.assert(timeline, record, this._timelines);
        if (!timeline)
            return;

        // Add the record to the global timeline by type.
        timeline.addRecord(record);

        // Some records don't have source code timelines.
        if (record.type === WI.TimelineRecord.Type.Network
            || record.type === WI.TimelineRecord.Type.RenderingFrame
            || record.type === WI.TimelineRecord.Type.CPU
            || record.type === WI.TimelineRecord.Type.Memory
            || record.type === WI.TimelineRecord.Type.HeapAllocations)
            return;

        if (!WI.TimelineRecording.sourceCodeTimelinesSupported())
            return;

        // Add the record to the source code timelines.
        let sourceCode = null;
        if (record.sourceCodeLocation)
            sourceCode = record.sourceCodeLocation.sourceCode;
        else if (record.type === WI.TimelineRecord.Type.Media) {
            if (record.domNode && record.domNode.frame)
                sourceCode = record.domNode.frame.mainResource;
        }
        if (!sourceCode)
            sourceCode = WI.networkManager.mainFrame.provisionalMainResource || WI.networkManager.mainFrame.mainResource;

        var sourceCodeTimelines = this._sourceCodeTimelinesMap.get(sourceCode);
        if (!sourceCodeTimelines) {
            sourceCodeTimelines = new Map;
            this._sourceCodeTimelinesMap.set(sourceCode, sourceCodeTimelines);
        }

        var newTimeline = false;
        var key = this._keyForRecord(record);
        var sourceCodeTimeline = sourceCodeTimelines.get(key);
        if (!sourceCodeTimeline) {
            sourceCodeTimeline = new WI.SourceCodeTimeline(sourceCode, record.sourceCodeLocation, record.type, record.eventType);
            sourceCodeTimelines.set(key, sourceCodeTimeline);
            newTimeline = true;
        }

        sourceCodeTimeline.addRecord(record);

        if (newTimeline)
            this.dispatchEventToListeners(WI.TimelineRecording.Event.SourceCodeTimelineAdded, {sourceCodeTimeline});
    }

    addMemoryPressureEvent(memoryPressureEvent)
    {
        this._exportDataMemoryPressureEvents.push(memoryPressureEvent);

        let memoryTimeline = this._timelines.get(WI.TimelineRecord.Type.Memory);
        console.assert(memoryTimeline, this._timelines);
        if (!memoryTimeline)
            return;

        memoryTimeline.addMemoryPressureEvent(memoryPressureEvent);
    }

    addDiscontinuity(startTime, endTime)
    {
        this._discontinuities.push({startTime, endTime});
    }

    discontinuitiesInTimeRange(startTime, endTime)
    {
        return this._discontinuities.filter((item) => item.startTime < endTime && item.endTime > startTime);
    }

    addScriptInstrumentForProgrammaticCapture()
    {
        for (let instrument of this._instruments) {
            if (instrument instanceof WI.ScriptInstrument)
                return;
        }

        this.addInstrument(new WI.ScriptInstrument);

        let instrumentTypes = this._instruments.map((instrument) => instrument.timelineRecordType);
        WI.timelineManager.enabledTimelineTypes = instrumentTypes;
    }

    computeElapsedTime(timestamp)
    {
        if (!timestamp || isNaN(timestamp))
            return NaN;

        // COMPATIBILITY (iOS 8): old backends send timestamps (seconds or milliseconds since the epoch),
        // rather than seconds elapsed since timeline capturing started. We approximate the latter by
        // subtracting the start timestamp, as old versions did not use monotonic times.
        if (WI.TimelineRecording.isLegacy === undefined)
            WI.TimelineRecording.isLegacy = timestamp > WI.TimelineRecording.TimestampThresholdForLegacyRecordConversion;

        if (!WI.TimelineRecording.isLegacy)
            return timestamp;

        // If the record's start time is large, but not really large, then it is seconds since epoch
        // not millseconds since epoch, so convert it to milliseconds.
        if (timestamp < WI.TimelineRecording.TimestampThresholdForLegacyAssumedMilliseconds)
            timestamp *= 1000;

        if (isNaN(this._legacyFirstRecordedTimestamp))
            this._legacyFirstRecordedTimestamp = timestamp;

        // Return seconds since the first recorded value.
        return (timestamp - this._legacyFirstRecordedTimestamp) / 1000.0;
    }

    setLegacyBaseTimestamp(timestamp)
    {
        console.assert(isNaN(this._legacyFirstRecordedTimestamp));

        if (timestamp < WI.TimelineRecording.TimestampThresholdForLegacyAssumedMilliseconds)
            timestamp *= 1000;

        this._legacyFirstRecordedTimestamp = timestamp;
    }

    initializeTimeBoundsIfNecessary(timestamp)
    {
        if (isNaN(this._startTime)) {
            console.assert(isNaN(this._endTime));

            this._startTime = timestamp;
            this._endTime = timestamp;

            this.dispatchEventToListeners(WI.TimelineRecording.Event.TimesUpdated);
        }
    }

    initializeCallingContextTrees(stackTraces, sampleDurations)
    {
        this._exportDataSampleStackTraces.concat(stackTraces);
        this._exportDataSampleDurations.concat(sampleDurations);

        for (let i = 0; i < stackTraces.length; i++) {
            this._topDownCallingContextTree.updateTreeWithStackTrace(stackTraces[i], sampleDurations[i]);
            this._bottomUpCallingContextTree.updateTreeWithStackTrace(stackTraces[i], sampleDurations[i]);
            this._topFunctionsTopDownCallingContextTree.updateTreeWithStackTrace(stackTraces[i], sampleDurations[i]);
            this._topFunctionsBottomUpCallingContextTree.updateTreeWithStackTrace(stackTraces[i], sampleDurations[i]);
        }
    }

    canExport()
    {
        if (this._capturing)
            return false;

        if (isNaN(this._startTime))
            return false;

        return true;
    }

    // Private

    _keyForRecord(record)
    {
        var key = record.type;
        if (record instanceof WI.ScriptTimelineRecord || record instanceof WI.LayoutTimelineRecord)
            key += ":" + record.eventType;
        if (record instanceof WI.ScriptTimelineRecord && record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched)
            key += ":" + record.details;
        if (record instanceof WI.MediaTimelineRecord) {
            key += ":" + record.eventType;
            if (record.eventType === WI.MediaTimelineRecord.EventType.DOMEvent) {
                if (record.domEvent && record.domEvent.eventName)
                    key += ":" + record.domEvent.eventName;
            } else if (record.eventType === WI.MediaTimelineRecord.EventType.PowerEfficientPlaybackStateChanged)
                key += ":" + (record.isPowerEfficient ? "enabled" : "disabled");
        }
        if (record.sourceCodeLocation)
            key += ":" + record.sourceCodeLocation.lineNumber + ":" + record.sourceCodeLocation.columnNumber;
        return key;
    }

    _timelineTimesUpdated(event)
    {
        var timeline = event.target;
        var changed = false;

        if (isNaN(this._startTime) || timeline.startTime < this._startTime) {
            this._startTime = timeline.startTime;
            changed = true;
        }

        if (isNaN(this._endTime) || this._endTime < timeline.endTime) {
            this._endTime = timeline.endTime;
            changed = true;
        }

        if (changed)
            this.dispatchEventToListeners(WI.TimelineRecording.Event.TimesUpdated);
    }
};

WI.TimelineRecording.Event = {
    Reset: "timeline-recording-reset",
    Unloaded: "timeline-recording-unloaded",
    SourceCodeTimelineAdded: "timeline-recording-source-code-timeline-added",
    InstrumentAdded: "timeline-recording-instrument-added",
    InstrumentRemoved: "timeline-recording-instrument-removed",
    TimesUpdated: "timeline-recording-times-updated",
    MarkerAdded: "timeline-recording-marker-added",
};

WI.TimelineRecording.isLegacy = undefined;
WI.TimelineRecording.TimestampThresholdForLegacyRecordConversion = 10000000; // Some value not near zero.
WI.TimelineRecording.TimestampThresholdForLegacyAssumedMilliseconds = 1420099200000; // Date.parse("Jan 1, 2015"). Milliseconds since epoch.

WI.TimelineRecording.SerializationVersion = 1;
