/*
 * Copyright 2014 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

export default class TracingModel {
  /**
   * @param {!BackingStorage} backingStorage
   */
  constructor(backingStorage) {
    this._backingStorage = backingStorage;
    // Avoid extra reset of the storage as it's expensive.
    this._firstWritePending = true;
    /** @type {!Map<(number|string), !Process>} */
    this._processById = new Map();
    this._processByName = new Map();
    this._minimumRecordTime = 0;
    this._maximumRecordTime = 0;
    this._devToolsMetadataEvents = [];
    /** @type {!Array<!Event>} */
    this._asyncEvents = [];
    /** @type {!Map<string, !AsyncEvent>} */
    this._openAsyncEvents = new Map();
    /** @type {!Map<string, !Array<!AsyncEvent>>} */
    this._openNestableAsyncEvents = new Map();
    /** @type {!Map<string, !ProfileEventsGroup>} */
    this._profileGroups = new Map();
    /** @type {!Map<string, !Set<string>>} */
    this._parsedCategories = new Map();
  }

  /**
   * @param {string} phase
   * @return {boolean}
   */
  static isNestableAsyncPhase(phase) {
    return phase === 'b' || phase === 'e' || phase === 'n';
  }

  /**
   * @param {string} phase
   * @return {boolean}
   */
  static isAsyncBeginPhase(phase) {
    return phase === 'S' || phase === 'b';
  }

  /**
   * @param {string} phase
   * @return {boolean}
   */
  static isAsyncPhase(phase) {
    return TracingModel.isNestableAsyncPhase(phase) || phase === 'S' || phase === 'T' || phase === 'F' || phase === 'p';
  }

  /**
   * @param {string} phase
   * @return {boolean}
   */
  static isFlowPhase(phase) {
    return phase === 's' || phase === 't' || phase === 'f';
  }

  /**
   * @param {!Event} event
   * @return {boolean}
   */
  static isTopLevelEvent(event) {
    return event.hasCategory(DevToolsTimelineEventCategory) && event.name === 'RunTask' ||
        event.hasCategory(LegacyTopLevelEventCategory) ||
        event.hasCategory(DevToolsMetadataEventCategory) &&
        event.name === 'Program';  // Older timelines may have this instead of toplevel.
  }

  /**
   * @param {!SDK.TracingManager.EventPayload} payload
   * @return {string|undefined}
   */
  static _extractId(payload) {
    const scope = payload.scope || '';
    if (typeof payload.id2 === 'undefined') {
      return scope && payload.id ? `${scope}@${payload.id}` : payload.id;
    }
    const id2 = payload.id2;
    if (typeof id2 === 'object' && ('global' in id2) !== ('local' in id2)) {
      return typeof id2['global'] !== 'undefined' ? `:${scope}:${id2['global']}` :
                                                    `:${scope}:${payload.pid}:${id2['local']}`;
    }
    console.error(
        `Unexpected id2 field at ${payload.ts / 1000}, one and only one of 'local' and 'global' should be present.`);
  }

  /**
   * @param {!TracingModel} tracingModel
   * @return {?Thread}
   *
   * TODO: Move this to a better place. This is here just for convenience o
   * re-use between modules. This really belongs to a higher level, since it
   * is specific to chrome's usage of tracing.
   */
  static browserMainThread(tracingModel) {
    const processes = tracingModel.sortedProcesses();
    // Avoid warning for an empty model.
    if (!processes.length) {
      return null;
    }
    const browserMainThreadName = 'CrBrowserMain';
    const browserProcesses = [];
    const browserMainThreads = [];
    for (const process of processes) {
      if (process.name().toLowerCase().endsWith('browser')) {
        browserProcesses.push(process);
      }
      browserMainThreads.push(...process.sortedThreads().filter(t => t.name() === browserMainThreadName));
    }
    if (browserMainThreads.length === 1) {
      return browserMainThreads[0];
    }
    if (browserProcesses.length === 1) {
      return browserProcesses[0].threadByName(browserMainThreadName);
    }
    const tracingStartedInBrowser =
        tracingModel.devToolsMetadataEvents().filter(e => e.name === 'TracingStartedInBrowser');
    if (tracingStartedInBrowser.length === 1) {
      return tracingStartedInBrowser[0].thread;
    }
    Common.console.error('Failed to find browser main thread in trace, some timeline features may be unavailable');
    return null;
  }

  /**
   * @return {!Array.<!Event>}
   */
  devToolsMetadataEvents() {
    return this._devToolsMetadataEvents;
  }

  /**
   * @param {!Array.<!SDK.TracingManager.EventPayload>} events
   */
  addEvents(events) {
    for (let i = 0; i < events.length; ++i) {
      this._addEvent(events[i]);
    }
  }

  tracingComplete() {
    this._processPendingAsyncEvents();
    this._backingStorage.appendString(this._firstWritePending ? '[]' : ']');
    this._backingStorage.finishWriting();
    this._firstWritePending = false;
    for (const process of this._processById.values()) {
      for (const thread of process._threads.values()) {
        thread.tracingComplete();
      }
    }
  }

  dispose() {
    if (!this._firstWritePending) {
      this._backingStorage.reset();
    }
  }

  /**
   * @param {number} offset
   */
  adjustTime(offset) {
    this._minimumRecordTime += offset;
    this._maximumRecordTime += offset;
    for (const process of this._processById.values()) {
      for (const thread of process._threads.values()) {
        for (const event of thread.events()) {
          event.startTime += offset;
          if (typeof event.endTime === 'number') {
            event.endTime += offset;
          }
        }
        for (const event of thread.asyncEvents()) {
          event.startTime += offset;
          if (typeof event.endTime === 'number') {
            event.endTime += offset;
          }
        }
      }
    }
  }

  /**
   * @param {!SDK.TracingManager.EventPayload} payload
   */
  _addEvent(payload) {
    let process = this._processById.get(payload.pid);
    if (!process) {
      process = new Process(this, payload.pid);
      this._processById.set(payload.pid, process);
    }

    const phase = Phase;
    const eventsDelimiter = ',\n';
    this._backingStorage.appendString(this._firstWritePending ? '[' : eventsDelimiter);
    this._firstWritePending = false;
    const stringPayload = JSON.stringify(payload);
    const isAccessible = payload.ph === phase.SnapshotObject;
    let backingStorage = null;
    const keepStringsLessThan = 10000;
    if (isAccessible && stringPayload.length > keepStringsLessThan) {
      backingStorage = this._backingStorage.appendAccessibleString(stringPayload);
    } else {
      this._backingStorage.appendString(stringPayload);
    }

    const timestamp = payload.ts / 1000;
    // We do allow records for unrelated threads to arrive out-of-order,
    // so there's a chance we're getting records from the past.
    if (timestamp && (!this._minimumRecordTime || timestamp < this._minimumRecordTime) &&
        (payload.ph === phase.Begin || payload.ph === phase.Complete || payload.ph === phase.Instant)) {
      this._minimumRecordTime = timestamp;
    }
    const endTimeStamp = (payload.ts + (payload.dur || 0)) / 1000;
    this._maximumRecordTime = Math.max(this._maximumRecordTime, endTimeStamp);
    const event = process._addEvent(payload);
    if (!event) {
      return;
    }
    if (payload.ph === phase.Sample) {
      this._addSampleEvent(event);
      return;
    }
    // Build async event when we've got events from all threads & processes, so we can sort them and process in the
    // chronological order. However, also add individual async events to the thread flow (above), so we can easily
    // display them on the same chart as other events, should we choose so.
    if (TracingModel.isAsyncPhase(payload.ph)) {
      this._asyncEvents.push(event);
    }
    event._setBackingStorage(backingStorage);
    if (event.hasCategory(DevToolsMetadataEventCategory)) {
      this._devToolsMetadataEvents.push(event);
    }

    if (payload.ph !== phase.Metadata) {
      return;
    }

    switch (payload.name) {
      case MetadataEvent.ProcessSortIndex:
        process._setSortIndex(payload.args['sort_index']);
        break;
      case MetadataEvent.ProcessName:
        const processName = payload.args['name'];
        process._setName(processName);
        this._processByName.set(processName, process);
        break;
      case MetadataEvent.ThreadSortIndex:
        process.threadById(payload.tid)._setSortIndex(payload.args['sort_index']);
        break;
      case MetadataEvent.ThreadName:
        process.threadById(payload.tid)._setName(payload.args['name']);
        break;
    }
  }

  /**
   * @param {!Event} event
   */
  _addSampleEvent(event) {
    const id = `${event.thread.process().id()}:${event.id}`;
    const group = this._profileGroups.get(id);
    if (group) {
      group._addChild(event);
    } else {
      this._profileGroups.set(id, new ProfileEventsGroup(event));
    }
  }

  /**
   * @param {!Event} event
   * @return {?ProfileEventsGroup}
   */
  profileGroup(event) {
    return this._profileGroups.get(`${event.thread.process().id()}:${event.id}`) || null;
  }

  /**
   * @return {number}
   */
  minimumRecordTime() {
    return this._minimumRecordTime;
  }

  /**
   * @return {number}
   */
  maximumRecordTime() {
    return this._maximumRecordTime;
  }

  /**
   * @return {!Array.<!Process>}
   */
  sortedProcesses() {
    return NamedObject._sort(this._processById.valuesArray());
  }

  /**
   * @param {string} name
   * @return {?Process}
   */
  processByName(name) {
    return this._processByName.get(name);
  }

  /**
   * @param {number} pid
   * @return {?Process}
   */
  processById(pid) {
    return this._processById.get(pid) || null;
  }

  /**
   * @param {string} processName
   * @param {string} threadName
   * @return {?Thread}
   */
  threadByName(processName, threadName) {
    const process = this.processByName(processName);
    return process && process.threadByName(threadName);
  }

  _processPendingAsyncEvents() {
    this._asyncEvents.sort(Event.compareStartTime);
    for (let i = 0; i < this._asyncEvents.length; ++i) {
      const event = this._asyncEvents[i];
      if (TracingModel.isNestableAsyncPhase(event.phase)) {
        this._addNestableAsyncEvent(event);
      } else {
        this._addAsyncEvent(event);
      }
    }
    this._asyncEvents = [];
    this._closeOpenAsyncEvents();
  }

  _closeOpenAsyncEvents() {
    for (const event of this._openAsyncEvents.values()) {
      event.setEndTime(this._maximumRecordTime);
      // FIXME: remove this once we figure a better way to convert async console
      // events to sync [waterfall] timeline records.
      event.steps[0].setEndTime(this._maximumRecordTime);
    }
    this._openAsyncEvents.clear();

    for (const eventStack of this._openNestableAsyncEvents.values()) {
      while (eventStack.length) {
        eventStack.pop().setEndTime(this._maximumRecordTime);
      }
    }
    this._openNestableAsyncEvents.clear();
  }

  /**
   * @param {!Event} event
   */
  _addNestableAsyncEvent(event) {
    const phase = Phase;
    const key = event.categoriesString + '.' + event.id;
    let openEventsStack = this._openNestableAsyncEvents.get(key);

    switch (event.phase) {
      case phase.NestableAsyncBegin:
        if (!openEventsStack) {
          openEventsStack = [];
          this._openNestableAsyncEvents.set(key, openEventsStack);
        }
        const asyncEvent = new AsyncEvent(event);
        openEventsStack.push(asyncEvent);
        event.thread._addAsyncEvent(asyncEvent);
        break;

      case phase.NestableAsyncInstant:
        if (openEventsStack && openEventsStack.length) {
          openEventsStack.peekLast()._addStep(event);
        }
        break;

      case phase.NestableAsyncEnd:
        if (!openEventsStack || !openEventsStack.length) {
          break;
        }
        const top = openEventsStack.pop();
        if (top.name !== event.name) {
          console.error(
              `Begin/end event mismatch for nestable async event, ${top.name} vs. ${event.name}, key: ${key}`);
          break;
        }
        top._addStep(event);
    }
  }

  /**
   * @param {!Event} event
   */
  _addAsyncEvent(event) {
    const phase = Phase;
    const key = event.categoriesString + '.' + event.name + '.' + event.id;
    let asyncEvent = this._openAsyncEvents.get(key);

    if (event.phase === phase.AsyncBegin) {
      if (asyncEvent) {
        console.error(`Event ${event.name} has already been started`);
        return;
      }
      asyncEvent = new AsyncEvent(event);
      this._openAsyncEvents.set(key, asyncEvent);
      event.thread._addAsyncEvent(asyncEvent);
      return;
    }
    if (!asyncEvent) {
      // Quietly ignore stray async events, we're probably too late for the start.
      return;
    }
    if (event.phase === phase.AsyncEnd) {
      asyncEvent._addStep(event);
      this._openAsyncEvents.delete(key);
      return;
    }
    if (event.phase === phase.AsyncStepInto || event.phase === phase.AsyncStepPast) {
      const lastStep = asyncEvent.steps.peekLast();
      if (lastStep.phase !== phase.AsyncBegin && lastStep.phase !== event.phase) {
        console.assert(
            false, 'Async event step phase mismatch: ' + lastStep.phase + ' at ' + lastStep.startTime + ' vs. ' +
                event.phase + ' at ' + event.startTime);
        return;
      }
      asyncEvent._addStep(event);
      return;
    }
    console.assert(false, 'Invalid async event phase');
  }

  /**
   * @return {!BackingStorage}
   */
  backingStorage() {
    return this._backingStorage;
  }

  /**
   * @param {string} str
   * @return {!Set<string>}
   */
  _parsedCategoriesForString(str) {
    let parsedCategories = this._parsedCategories.get(str);
    if (!parsedCategories) {
      parsedCategories = new Set(str ? str.split(',') : []);
      this._parsedCategories.set(str, parsedCategories);
    }
    return parsedCategories;
  }
}

/**
 * @enum {string}
 */
export const Phase = {
  Begin: 'B',
  End: 'E',
  Complete: 'X',
  Instant: 'I',
  AsyncBegin: 'S',
  AsyncStepInto: 'T',
  AsyncStepPast: 'p',
  AsyncEnd: 'F',
  NestableAsyncBegin: 'b',
  NestableAsyncEnd: 'e',
  NestableAsyncInstant: 'n',
  FlowBegin: 's',
  FlowStep: 't',
  FlowEnd: 'f',
  Metadata: 'M',
  Counter: 'C',
  Sample: 'P',
  CreateObject: 'N',
  SnapshotObject: 'O',
  DeleteObject: 'D'
};

export const MetadataEvent = {
  ProcessSortIndex: 'process_sort_index',
  ProcessName: 'process_name',
  ThreadSortIndex: 'thread_sort_index',
  ThreadName: 'thread_name'
};

// TODO(alph): LegacyTopLevelEventCategory is not recorded since M74 and used for loading
// legacy profiles. Drop at some point.
export const LegacyTopLevelEventCategory = 'toplevel';

export const DevToolsMetadataEventCategory = 'disabled-by-default-devtools.timeline';
export const DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';

/**
 * @interface
 */
export class BackingStorage {
  /**
   * @param {string} string
   */
  appendString(string) {
  }

  /**
   * @param {string} string
   * @return {function():!Promise.<?string>}
   */
  appendAccessibleString(string) {
  }

  finishWriting() {
  }

  reset() {}
}

/**
 * @unrestricted
 */
export class Event {
  /**
   * @param {string|undefined} categories
   * @param {string} name
   * @param {!Phase} phase
   * @param {number} startTime
   * @param {!Thread} thread
   */
  constructor(categories, name, phase, startTime, thread) {
    /** @type {string} */
    this.categoriesString = categories || '';
    /** @type {!Set<string>} */
    this._parsedCategories = thread._model._parsedCategoriesForString(this.categoriesString);
    /** @type {string} */
    this.name = name;
    /** @type {!Phase} */
    this.phase = phase;
    /** @type {number} */
    this.startTime = startTime;
    /** @type {!Thread} */
    this.thread = thread;
    /** @type {!Object} */
    this.args = {};

    /** @type {number} */
    this.selfTime = 0;
  }

  /**
   * @this {null}
   * @param {!SDK.TracingManager.EventPayload} payload
   * @param {!Thread} thread
   * @return {!Event}
   */
  static fromPayload(payload, thread) {
    const event = new Event(payload.cat, payload.name, /** @type {!Phase} */ (payload.ph), payload.ts / 1000, thread);
    if (payload.args) {
      event.addArgs(payload.args);
    }
    if (typeof payload.dur === 'number') {
      event.setEndTime((payload.ts + payload.dur) / 1000);
    }
    const id = TracingModel._extractId(payload);
    if (typeof id !== 'undefined') {
      event.id = id;
    }
    if (payload.bind_id) {
      event.bind_id = payload.bind_id;
    }

    return event;
  }

  /**
   * @param {!Event} a
   * @param {!Event} b
   * @return {number}
   */
  static compareStartTime(a, b) {
    return a.startTime - b.startTime;
  }

  /**
   * @param {!Event} a
   * @param {!Event} b
   * @return {number}
   */
  static orderedCompareStartTime(a, b) {
    // Array.mergeOrdered coalesces objects if comparator returns 0.
    // To change this behavior this comparator return -1 in the case events
    // startTime's are equal, so both events got placed into the result array.
    return a.startTime - b.startTime || a.ordinal - b.ordinal || -1;
  }

  /**
   * @param {string} categoryName
   * @return {boolean}
   */
  hasCategory(categoryName) {
    return this._parsedCategories.has(categoryName);
  }

  /**
   * @param {number} endTime
   */
  setEndTime(endTime) {
    if (endTime < this.startTime) {
      console.assert(false, 'Event out of order: ' + this.name);
      return;
    }
    this.endTime = endTime;
    this.duration = endTime - this.startTime;
  }

  /**
   * @param {!Object} args
   */
  addArgs(args) {
    // Shallow copy args to avoid modifying original payload which may be saved to file.
    for (const name in args) {
      if (name in this.args) {
        console.error('Same argument name (' + name + ') is used for begin and end phases of ' + this.name);
      }
      this.args[name] = args[name];
    }
  }

  /**
   * @param {!Event} endEvent
   */
  _complete(endEvent) {
    if (endEvent.args) {
      this.addArgs(endEvent.args);
    } else {
      console.error('Missing mandatory event argument \'args\' at ' + endEvent.startTime);
    }
    this.setEndTime(endEvent.startTime);
  }

  /**
   * @param {?function():!Promise.<?string>} backingStorage
   */
  _setBackingStorage(backingStorage) {
  }
}

export class ObjectSnapshot extends Event {
  /**
   * @param {string|undefined} category
   * @param {string} name
   * @param {number} startTime
   * @param {!Thread} thread
   */
  constructor(category, name, startTime, thread) {
    super(category, name, Phase.SnapshotObject, startTime, thread);
    /** @type {?function():!Promise<?string>} */
    this._backingStorage = null;
    /** @type {string} */
    this.id;
    /** @type {?Promise<?>} */
    this._objectPromise = null;
  }

  /**
   * @override
   * @this {null}
   * @param {!SDK.TracingManager.EventPayload} payload
   * @param {!Thread} thread
   * @return {!ObjectSnapshot}
   */
  static fromPayload(payload, thread) {
    const snapshot = new ObjectSnapshot(payload.cat, payload.name, payload.ts / 1000, thread);
    const id = TracingModel._extractId(payload);
    if (typeof id !== 'undefined') {
      snapshot.id = id;
    }
    if (!payload.args || !payload.args['snapshot']) {
      console.error('Missing mandatory \'snapshot\' argument at ' + payload.ts / 1000);
      return snapshot;
    }
    if (payload.args) {
      snapshot.addArgs(payload.args);
    }
    return snapshot;
  }

  /**
   * @param {function(?)} callback
   */
  requestObject(callback) {
    const snapshot = this.args['snapshot'];
    if (snapshot) {
      callback(snapshot);
      return;
    }
    this._backingStorage().then(onRead, callback.bind(null, null));
    /**
     * @param {?string} result
     */
    function onRead(result) {
      if (!result) {
        callback(null);
        return;
      }
      try {
        const payload = JSON.parse(result);
        callback(payload['args']['snapshot']);
      } catch (e) {
        Common.console.error('Malformed event data in backing storage');
        callback(null);
      }
    }
  }

  /**
   * @return {!Promise<?>}
   */
  objectPromise() {
    if (!this._objectPromise) {
      this._objectPromise = new Promise(this.requestObject.bind(this));
    }
    return this._objectPromise;
  }

  /**
   * @override
   * @param {?function():!Promise.<?>} backingStorage
   */
  _setBackingStorage(backingStorage) {
    if (!backingStorage) {
      return;
    }
    this._backingStorage = backingStorage;
    this.args = {};
  }
}

/**
 * @unrestricted
 */
export class AsyncEvent extends Event {
  /**
   * @param {!Event} startEvent
   */
  constructor(startEvent) {
    super(startEvent.categoriesString, startEvent.name, startEvent.phase, startEvent.startTime, startEvent.thread);
    this.addArgs(startEvent.args);
    this.steps = [startEvent];
  }

  /**
   * @param {!Event} event
   */
  _addStep(event) {
    this.steps.push(event);
    if (event.phase === Phase.AsyncEnd || event.phase === Phase.NestableAsyncEnd) {
      this.setEndTime(event.startTime);
      // FIXME: ideally, we shouldn't do this, but this makes the logic of converting
      // async console events to sync ones much simpler.
      this.steps[0].setEndTime(event.startTime);
    }
  }
}

/**
 * @unrestricted
 */
class ProfileEventsGroup {
  /**
   * @param {!Event} event
   */
  constructor(event) {
    /** @type {!Array<!Event>} */
    this.children = [event];
  }

  /**
   * @param {!Event} event
   */
  _addChild(event) {
    this.children.push(event);
  }
}

class NamedObject {
  /**
   * @param {!TracingModel} model
   * @param {number} id
   */
  constructor(model, id) {
    this._model = model;
    this._id = id;
    this._name = '';
    this._sortIndex = 0;
  }

  /**
   * @param {!Array.<!NamedObject>} array
   */
  static _sort(array) {
    /**
     * @param {!NamedObject} a
     * @param {!NamedObject} b
     */
    function comparator(a, b) {
      return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.name().localeCompare(b.name());
    }
    return array.sort(comparator);
  }

  /**
   * @param {string} name
   */
  _setName(name) {
    this._name = name;
  }

  /**
   * @return {string}
   */
  name() {
    return this._name;
  }

  /**
   * @param {number} sortIndex
   */
  _setSortIndex(sortIndex) {
    this._sortIndex = sortIndex;
  }
}

export class Process extends NamedObject {
  /**
   * @param {!TracingModel} model
   * @param {number} id
   */
  constructor(model, id) {
    super(model, id);
    /** @type {!Map<number, !Thread>} */
    this._threads = new Map();
    this._threadByName = new Map();
  }

  /**
   * @return {number}
   */
  id() {
    return this._id;
  }

  /**
   * @param {number} id
   * @return {!Thread}
   */
  threadById(id) {
    let thread = this._threads.get(id);
    if (!thread) {
      thread = new Thread(this, id);
      this._threads.set(id, thread);
    }
    return thread;
  }

  /**
   * @param {string} name
   * @return {?Thread}
   */
  threadByName(name) {
    return this._threadByName.get(name) || null;
  }

  /**
   * @param {string} name
   * @param {!Thread} thread
   */
  _setThreadByName(name, thread) {
    this._threadByName.set(name, thread);
  }

  /**
   * @param {!SDK.TracingManager.EventPayload} payload
   * @return {?Event} event
   */
  _addEvent(payload) {
    return this.threadById(payload.tid)._addEvent(payload);
  }

  /**
   * @return {!Array.<!Thread>}
   */
  sortedThreads() {
    return NamedObject._sort(this._threads.valuesArray());
  }
}

export class Thread extends NamedObject {
  /**
   * @param {!Process} process
   * @param {number} id
   */
  constructor(process, id) {
    super(process._model, id);
    this._process = process;
    this._events = [];
    this._asyncEvents = [];
    this._lastTopLevelEvent = null;
  }

  tracingComplete() {
    this._asyncEvents.sort(Event.compareStartTime);
    this._events.sort(Event.compareStartTime);
    const phases = Phase;
    const stack = [];
    for (let i = 0; i < this._events.length; ++i) {
      const e = this._events[i];
      e.ordinal = i;
      switch (e.phase) {
        case phases.End:
          this._events[i] = null;  // Mark for removal.
          // Quietly ignore unbalanced close events, they're legit (we could have missed start one).
          if (!stack.length) {
            continue;
          }
          const top = stack.pop();
          if (top.name !== e.name || top.categoriesString !== e.categoriesString) {
            console.error(
                'B/E events mismatch at ' + top.startTime + ' (' + top.name + ') vs. ' + e.startTime + ' (' + e.name +
                ')');
          } else {
            top._complete(e);
          }
          break;
        case phases.Begin:
          stack.push(e);
          break;
      }
    }
    while (stack.length) {
      stack.pop().setEndTime(this._model.maximumRecordTime());
    }
    this._events.remove(null, false);
  }

  /**
   * @param {!SDK.TracingManager.EventPayload} payload
   * @return {?Event} event
   */
  _addEvent(payload) {
    const event = payload.ph === Phase.SnapshotObject ? ObjectSnapshot.fromPayload(payload, this) :
                                                        Event.fromPayload(payload, this);
    if (TracingModel.isTopLevelEvent(event)) {
      // Discard nested "top-level" events.
      if (this._lastTopLevelEvent && this._lastTopLevelEvent.endTime > event.startTime) {
        return null;
      }
      this._lastTopLevelEvent = event;
    }
    this._events.push(event);
    return event;
  }

  /**
   * @param {!AsyncEvent} asyncEvent
   */
  _addAsyncEvent(asyncEvent) {
    this._asyncEvents.push(asyncEvent);
  }

  /**
   * @override
   * @param {string} name
   */
  _setName(name) {
    super._setName(name);
    this._process._setThreadByName(name, this);
  }

  /**
   * @return {number}
   */
  id() {
    return this._id;
  }

  /**
   * @return {!Process}
   */
  process() {
    return this._process;
  }

  /**
   * @return {!Array.<!Event>}
   */
  events() {
    return this._events;
  }

  /**
   * @return {!Array.<!AsyncEvent>}
   */
  asyncEvents() {
    return this._asyncEvents;
  }
}

/* Legacy exported object */
self.SDK = self.SDK || {};

/* Legacy exported object */
SDK = SDK || {};

/** @constructor */
SDK.TracingModel = TracingModel;

SDK.TracingModel.Phase = Phase;
SDK.TracingModel.MetadataEvent = MetadataEvent;
SDK.TracingModel.LegacyTopLevelEventCategory = LegacyTopLevelEventCategory;
SDK.TracingModel.DevToolsMetadataEventCategory = DevToolsMetadataEventCategory;
SDK.TracingModel.DevToolsTimelineEventCategory = DevToolsTimelineEventCategory;

/** @constructor */
SDK.TracingModel.Event = Event;

/** @constructor */
SDK.TracingModel.ObjectSnapshot = ObjectSnapshot;

/** @constructor */
SDK.TracingModel.AsyncEvent = AsyncEvent;

/** @constructor */
SDK.TracingModel.Process = Process;

/** @constructor */
SDK.TracingModel.Thread = Thread;

/** @interface */
SDK.BackingStorage = BackingStorage;
