/*
 * Copyright (C) 2014 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

/**
 * @implements {PerfUI.FlameChartDataProvider}
 * @unrestricted
 */
Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
  constructor() {
    super();
    this.reset();
    this._font = '11px ' + Host.fontFamily();
    /** @type {?PerfUI.FlameChart.TimelineData} */
    this._timelineData = null;
    this._currentLevel = 0;
    /** @type {?Timeline.PerformanceModel} */
    this._performanceModel = null;
    /** @type {?TimelineModel.TimelineModel} */
    this._model = null;
    this._minimumBoundary = 0;
    this._maximumBoundary = 0;
    this._timeSpan = 0;

    this._consoleColorGenerator =
        new Common.Color.Generator({min: 30, max: 55}, {min: 70, max: 100, count: 6}, 50, 0.7);
    this._extensionColorGenerator =
        new Common.Color.Generator({min: 210, max: 300}, {min: 70, max: 100, count: 6}, 70, 0.7);

    this._headerLevel1 = this._buildGroupStyle({shareHeaderLine: false});
    this._headerLevel2 = this._buildGroupStyle({padding: 2, nestingLevel: 1, collapsible: false});
    this._staticHeader = this._buildGroupStyle({collapsible: false});
    this._framesHeader = this._buildGroupStyle({useFirstLineForOverview: true});
    this._timingsHeader = this._buildGroupStyle({shareHeaderLine: true, useFirstLineForOverview: true});
    this._screenshotsHeader =
        this._buildGroupStyle({useFirstLineForOverview: true, nestingLevel: 1, collapsible: false, itemsHeight: 150});
    this._interactionsHeaderLevel1 = this._buildGroupStyle({useFirstLineForOverview: true});
    this._interactionsHeaderLevel2 = this._buildGroupStyle({padding: 2, nestingLevel: 1});

    /** @type {!Map<string, number>} */
    this._flowEventIndexById = new Map();
  }

  /**
   * @param {!Object} extra
   * @return {!PerfUI.FlameChart.GroupStyle}
   */
  _buildGroupStyle(extra) {
    const defaultGroupStyle = {
      padding: 4,
      height: 17,
      collapsible: true,
      color: UI.themeSupport.patchColorText('#222', UI.ThemeSupport.ColorUsage.Foreground),
      backgroundColor: UI.themeSupport.patchColorText('white', UI.ThemeSupport.ColorUsage.Background),
      font: this._font,
      nestingLevel: 0,
      shareHeaderLine: true
    };
    return /** @type {!PerfUI.FlameChart.GroupStyle} */ (Object.assign(defaultGroupStyle, extra));
  }

  /**
   * @param {?Timeline.PerformanceModel} performanceModel
   */
  setModel(performanceModel) {
    this.reset();
    this._performanceModel = performanceModel;
    this._model = performanceModel && performanceModel.timelineModel();
  }

  /**
   * @param {!PerfUI.FlameChart.Group} group
   * @return {?TimelineModel.TimelineModel.Track}
   */
  groupTrack(group) {
    return group._track || null;
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {?string}
   */
  entryTitle(entryIndex) {
    const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
    const entryType = this._entryType(entryIndex);
    if (entryType === entryTypes.Event) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      if (event.phase === SDK.TracingModel.Phase.AsyncStepInto ||
          event.phase === SDK.TracingModel.Phase.AsyncStepPast) {
        return event.name + ':' + event.args['step'];
      }
      if (event._blackboxRoot) {
        return Common.UIString('Blackboxed');
      }
      if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
        return Timeline.TimelineUIUtils.markerShortTitle(event);
      }
      return Timeline.TimelineUIUtils.eventTitle(event);
    }
    if (entryType === entryTypes.ExtensionEvent) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      return event.name;
    }
    if (entryType === entryTypes.Screenshot) {
      return '';
    }
    let title = this._entryIndexToTitle[entryIndex];
    if (!title) {
      title = Common.UIString('Unexpected entryIndex %d', entryIndex);
      console.error(title);
    }
    return title;
  }

  /**
   * @override
   * @param {number} index
   * @return {string}
   */
  textColor(index) {
    const event = this._entryData[index];
    return event && event._blackboxRoot ? '#888' : Timeline.FlameChartStyle.textColor;
  }

  /**
   * @override
   * @param {number} index
   * @return {?string}
   */
  entryFont(index) {
    return this._font;
  }

  reset() {
    this._currentLevel = 0;
    this._timelineData = null;
    /** @type {!Array<!SDK.FilmStripModel.Frame|!SDK.TracingModel.Event|!TimelineModel.TimelineFrame|!TimelineModel.TimelineIRModel.Phases>} */
    this._entryData = [];
    /** @type {!Array<!SDK.TracingModel.Event>} */
    this._entryParent = [];
    /** @type {!Array<!Timeline.TimelineFlameChartDataProvider.EntryType>} */
    this._entryTypeByLevel = [];
    /** @type {!Array<string>} */
    this._entryIndexToTitle = [];
    /** @type {!Array<!Timeline.TimelineFlameChartMarker>} */
    this._markers = [];
    /** @type {!Map<!Timeline.TimelineCategory, string>} */
    this._asyncColorByCategory = new Map();
    /** @type {!Map<!TimelineModel.TimelineIRModel.Phases, string>} */
    this._asyncColorByInteractionPhase = new Map();
    /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */
    this._extensionInfo = [];
    /** @type {!Map<!SDK.FilmStripModel.Frame, ?Image>} */
    this._screenshotImageCache = new Map();
  }

  /**
   * @override
   * @return {number}
   */
  maxStackDepth() {
    return this._currentLevel;
  }

  /**
   * @override
   * @return {!PerfUI.FlameChart.TimelineData}
   */
  timelineData() {
    if (this._timelineData) {
      return this._timelineData;
    }

    this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
    if (!this._model) {
      return this._timelineData;
    }

    this._flowEventIndexById.clear();
    this._minimumBoundary = this._model.minimumRecordTime();
    this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTime() - this._minimumBoundary;
    this._currentLevel = 0;

    if (this._model.isGenericTrace()) {
      this._processGenericTrace();
    } else {
      this._processInspectorTrace();
    }

    return this._timelineData;
  }

  _processGenericTrace() {
    const processGroupStyle = this._buildGroupStyle({shareHeaderLine: false});
    const threadGroupStyle = this._buildGroupStyle({padding: 2, nestingLevel: 1, shareHeaderLine: false});
    const eventEntryType = Timeline.TimelineFlameChartDataProvider.EntryType.Event;
    /** @type {!Platform.Multimap<!SDK.TracingModel.Process, !TimelineModel.TimelineModel.Track>} */
    const tracksByProcess = new Platform.Multimap();
    for (const track of this._model.tracks()) {
      if (track.thread !== null) {
        tracksByProcess.set(track.thread.process(), track);
      } else {
        // The Timings track can reach this point, so we should probably do something more useful.
        console.error('Failed to process track');
      }
    }
    for (const process of tracksByProcess.keysArray()) {
      if (tracksByProcess.size > 1) {
        const name = `${process.name()} ${process.id()}`;
        this._appendHeader(name, processGroupStyle, false /* selectable */);
      }
      for (const track of tracksByProcess.get(process)) {
        const group = this._appendSyncEvents(
            track, track.events, track.name, threadGroupStyle, eventEntryType, true /* selectable */);
        if (!this._timelineData.selectedGroup || track.name === TimelineModel.TimelineModel.BrowserMainThreadName) {
          this._timelineData.selectedGroup = group;
        }
      }
    }
  }

  _processInspectorTrace() {
    this._appendFrames();
    this._appendInteractionRecords();

    const eventEntryType = Timeline.TimelineFlameChartDataProvider.EntryType.Event;

    const weight = track => {
      switch (track.type) {
        case TimelineModel.TimelineModel.TrackType.Input:
          return 0;
        case TimelineModel.TimelineModel.TrackType.Animation:
          return 1;
        case TimelineModel.TimelineModel.TrackType.Timings:
          return 2;
        case TimelineModel.TimelineModel.TrackType.Console:
          return 3;
        case TimelineModel.TimelineModel.TrackType.MainThread:
          return track.forMainFrame ? 4 : 5;
        case TimelineModel.TimelineModel.TrackType.Worker:
          return 6;
        case TimelineModel.TimelineModel.TrackType.Raster:
          return 7;
        case TimelineModel.TimelineModel.TrackType.GPU:
          return 8;
        case TimelineModel.TimelineModel.TrackType.Other:
          return 9;
      }
    };

    const tracks = this._model.tracks().slice();
    tracks.sort((a, b) => weight(a) - weight(b));
    let rasterCount = 0;
    for (const track of tracks) {
      switch (track.type) {
        case TimelineModel.TimelineModel.TrackType.Input:
          this._appendAsyncEventsGroup(
              track, ls`Input`, track.asyncEvents, this._interactionsHeaderLevel2, eventEntryType,
              false /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.Animation:
          this._appendAsyncEventsGroup(
              track, ls`Animation`, track.asyncEvents, this._interactionsHeaderLevel2, eventEntryType,
              false /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.Timings:
          const group = this._appendHeader(ls`Timings`, this._timingsHeader, true /* selectable */);
          group._track = track;
          this._appendPageMetrics();
          this._appendAsyncEventsGroup(
              track, null, track.asyncEvents, this._timingsHeader, eventEntryType, true /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.Console:
          this._appendAsyncEventsGroup(
              track, ls`Console`, track.asyncEvents, this._headerLevel1, eventEntryType, true /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.MainThread:
          if (track.forMainFrame) {
            const group = this._appendSyncEvents(
                track, track.events, track.url ? ls`Main \u2014 ${track.url}` : ls`Main`, this._headerLevel1,
                eventEntryType, true /* selectable */);
            if (group) {
              this._timelineData.selectedGroup = group;
            }
          } else {
            this._appendSyncEvents(
                track, track.events, track.url ? ls`Frame \u2014 ${track.url}` : ls`Subframe`, this._headerLevel1,
                eventEntryType, true /* selectable */);
          }
          break;
        case TimelineModel.TimelineModel.TrackType.Worker:
          this._appendSyncEvents(
              track, track.events, track.url ? ls`Worker \u2014 ${track.url}` : ls`Dedicated Worker`,
              this._headerLevel1, eventEntryType, true /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.Raster:
          if (!rasterCount) {
            this._appendHeader(ls`Raster`, this._headerLevel1, false /* selectable */);
          }
          ++rasterCount;
          this._appendSyncEvents(
              track, track.events, ls`Rasterizer Thread ${rasterCount}`, this._headerLevel2, eventEntryType,
              true /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.GPU:
          this._appendSyncEvents(
              track, track.events, ls`GPU`, this._headerLevel1, eventEntryType, true /* selectable */);
          break;
        case TimelineModel.TimelineModel.TrackType.Other:
          this._appendSyncEvents(
              track, track.events, track.name || ls`Thread`, this._headerLevel1, eventEntryType, true /* selectable */);
          this._appendAsyncEventsGroup(
              track, track.name, track.asyncEvents, this._headerLevel1, eventEntryType, true /* selectable */);
          break;
      }
    }
    if (this._timelineData.selectedGroup) {
      this._timelineData.selectedGroup.expanded = true;
    }

    for (let extensionIndex = 0; extensionIndex < this._extensionInfo.length; extensionIndex++) {
      this._innerAppendExtensionEvents(extensionIndex);
    }

    this._markers.sort((a, b) => a.startTime() - b.startTime());
    this._timelineData.markers = this._markers;
    this._flowEventIndexById.clear();
  }

  /**
   * @override
   * @return {number}
   */
  minimumBoundary() {
    return this._minimumBoundary;
  }

  /**
   * @override
   * @return {number}
   */
  totalTime() {
    return this._timeSpan;
  }

  /**
   * @param {number} startTime
   * @param {number} endTime
   * @param {!TimelineModel.TimelineModelFilter} filter
   * @return {!Array<number>}
   */
  search(startTime, endTime, filter) {
    const result = [];
    const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
    this.timelineData();
    for (let i = 0; i < this._entryData.length; ++i) {
      if (this._entryType(i) !== entryTypes.Event) {
        continue;
      }
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[i]);
      if (event.startTime > endTime) {
        continue;
      }
      if ((event.endTime || event.startTime) < startTime) {
        continue;
      }
      if (filter.accept(event)) {
        result.push(i);
      }
    }
    result.sort(
        (a, b) => SDK.TracingModel.Event.compareStartTime(
            /** @type {!SDK.TracingModel.Event} */ (this._entryData[a]),
            /** @type {!SDK.TracingModel.Event} */ (this._entryData[b])));
    return result;
  }

  /**
   * @param {?TimelineModel.TimelineModel.Track} track
   * @param {!Array<!SDK.TracingModel.Event>} events
   * @param {string} title
   * @param {!PerfUI.FlameChart.GroupStyle} style
   * @param {!Timeline.TimelineFlameChartDataProvider.EntryType} entryType
   * @param {boolean} selectable
   * @return {?PerfUI.FlameChart.Group}
   */
  _appendSyncEvents(track, events, title, style, entryType, selectable) {
    if (!events.length) {
      return null;
    }
    const isExtension = entryType === Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;
    const openEvents = [];
    const flowEventsEnabled = Root.Runtime.experiments.isEnabled('timelineFlowEvents');
    const blackboxingEnabled = !isExtension && Root.Runtime.experiments.isEnabled('blackboxJSFramesOnTimeline');
    let maxStackDepth = 0;
    let group = null;
    if (track && track.type === TimelineModel.TimelineModel.TrackType.MainThread) {
      group = this._appendHeader(title, style, selectable);
      group._track = track;
    }
    for (let i = 0; i < events.length; ++i) {
      const e = events[i];
      if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e)) {
        this._markers.push(new Timeline.TimelineFlameChartMarker(
            e.startTime, e.startTime - this._model.minimumRecordTime(),
            Timeline.TimelineUIUtils.markerStyleForEvent(e)));
      }
      if (!SDK.TracingModel.isFlowPhase(e.phase)) {
        if (!e.endTime && e.phase !== SDK.TracingModel.Phase.Instant) {
          continue;
        }
        if (SDK.TracingModel.isAsyncPhase(e.phase)) {
          continue;
        }
        if (!isExtension && !this._performanceModel.isVisible(e)) {
          continue;
        }
      }
      while (openEvents.length && openEvents.peekLast().endTime <= e.startTime) {
        openEvents.pop();
      }
      e._blackboxRoot = false;
      if (blackboxingEnabled && this._isBlackboxedEvent(e)) {
        const parent = openEvents.peekLast();
        if (parent && parent._blackboxRoot) {
          continue;
        }
        e._blackboxRoot = true;
      }
      if (!group) {
        group = this._appendHeader(title, style, selectable);
        if (selectable) {
          group._track = track;
        }
      }

      const level = this._currentLevel + openEvents.length;
      if (flowEventsEnabled) {
        this._appendFlowEvent(e, level);
      }
      const index = this._appendEvent(e, level);
      if (openEvents.length) {
        this._entryParent[index] = openEvents.peekLast();
      }
      if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e)) {
        this._timelineData.entryTotalTimes[this._entryData.length] = undefined;
      }

      maxStackDepth = Math.max(maxStackDepth, openEvents.length + 1);
      if (e.endTime) {
        openEvents.push(e);
      }
    }
    this._entryTypeByLevel.length = this._currentLevel + maxStackDepth;
    this._entryTypeByLevel.fill(entryType, this._currentLevel);
    this._currentLevel += maxStackDepth;
    return group;
  }

  /**
   * @param {!SDK.TracingModel.Event} event
   * @return {boolean}
   */
  _isBlackboxedEvent(event) {
    if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame) {
      return false;
    }
    const url = event.args['data']['url'];
    return url && this._isBlackboxedURL(url);
  }

  /**
   * @param {string} url
   * @return {boolean}
   */
  _isBlackboxedURL(url) {
    return Bindings.blackboxManager.isBlackboxedURL(url);
  }

  /**
   * @param {?TimelineModel.TimelineModel.Track} track
   * @param {?string} header
   * @param {!Array<!SDK.TracingModel.AsyncEvent>} events
   * @param {!PerfUI.FlameChart.GroupStyle} style
   * @param {!Timeline.TimelineFlameChartDataProvider.EntryType} entryType
   * @param {boolean} selectable
   * @return {?PerfUI.FlameChart.Group}
   */
  _appendAsyncEventsGroup(track, header, events, style, entryType, selectable) {
    if (!events.length) {
      return null;
    }
    const lastUsedTimeByLevel = [];
    let group = null;
    for (let i = 0; i < events.length; ++i) {
      const asyncEvent = events[i];
      if (!this._performanceModel.isVisible(asyncEvent)) {
        continue;
      }
      if (!group && header) {
        group = this._appendHeader(header, style, selectable);
        if (selectable) {
          group._track = track;
        }
      }
      const startTime = asyncEvent.startTime;
      let level;
      for (level = 0; level < lastUsedTimeByLevel.length && lastUsedTimeByLevel[level] > startTime; ++level) {
      }
      this._appendAsyncEvent(asyncEvent, this._currentLevel + level);
      lastUsedTimeByLevel[level] = asyncEvent.endTime;
    }
    this._entryTypeByLevel.length = this._currentLevel + lastUsedTimeByLevel.length;
    this._entryTypeByLevel.fill(entryType, this._currentLevel);
    this._currentLevel += lastUsedTimeByLevel.length;
    return group;
  }

  _appendInteractionRecords() {
    const interactionRecords = this._performanceModel.interactionRecords();
    if (!interactionRecords.length) {
      return;
    }
    this._appendHeader(ls`Interactions`, this._interactionsHeaderLevel1, false /* selectable */);
    for (const segment of interactionRecords) {
      const index = this._entryData.length;
      this._entryData.push(/** @type {!TimelineModel.TimelineIRModel.Phases} */ (segment.data));
      this._entryIndexToTitle[index] = /** @type {string} */ (segment.data);
      this._timelineData.entryLevels[index] = this._currentLevel;
      this._timelineData.entryTotalTimes[index] = segment.end - segment.begin;
      this._timelineData.entryStartTimes[index] = segment.begin;
    }
    this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartDataProvider.EntryType.InteractionRecord;
  }

  _appendPageMetrics() {
    this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartDataProvider.EntryType.Event;

    /** @type {!Array<!SDK.TracingModel.Event>} */
    const metricEvents = [];
    const lcpEvents = [];
    const timelineModel = this._performanceModel.timelineModel();
    for (const track of this._model.tracks()) {
      for (const event of track.events) {
        if (!timelineModel.isMarkerEvent(event)) {
          continue;
        }
        if (timelineModel.isLCPCandidateEvent(event) || timelineModel.isLCPInvalidateEvent(event)) {
          lcpEvents.push(event);
        } else {
          metricEvents.push(event);
        }
      }
    }

    // Only the LCP event with the largest candidate index is relevant.
    // Do not record an LCP event if it is an invalidate event.
    if (lcpEvents.length > 0) {
      /** @type {!Map<string, !SDK.TracingModel.Event>} */
      const lcpEventsByNavigationId = new Map();
      for (const e of lcpEvents) {
        const key = e.args['data']['navigationId'];
        const previousLastEvent = lcpEventsByNavigationId.get(key);

        if (!previousLastEvent || previousLastEvent.args['data']['candidateIndex'] < e.args['data']['candidateIndex']) {
          lcpEventsByNavigationId.set(key, e);
        }
      }

      const latestCandidates = Array.from(lcpEventsByNavigationId.values());
      const latestEvents = latestCandidates.filter(e => timelineModel.isLCPCandidateEvent(e));

      metricEvents.push(...latestEvents);
    }

    metricEvents.sort(SDK.TracingModel.Event.compareStartTime);
    const totalTimes = this._timelineData.entryTotalTimes;
    for (const event of metricEvents) {
      this._appendEvent(event, this._currentLevel);
      totalTimes[totalTimes.length - 1] = Number.NaN;
    }

    ++this._currentLevel;
  }

  _appendFrames() {
    const screenshots = this._performanceModel.filmStripModel().frames();
    const hasFilmStrip = !!screenshots.length;
    this._framesHeader.collapsible = hasFilmStrip;
    this._appendHeader(Common.UIString('Frames'), this._framesHeader, false /* selectable */);
    this._frameGroup = this._timelineData.groups.peekLast();
    const style = Timeline.TimelineUIUtils.markerStyleForFrame();

    this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartDataProvider.EntryType.Frame;
    for (const frame of this._performanceModel.frames()) {
      this._markers.push(new Timeline.TimelineFlameChartMarker(
          frame.startTime, frame.startTime - this._model.minimumRecordTime(), style));
      this._appendFrame(frame);
    }
    ++this._currentLevel;

    if (!hasFilmStrip) {
      return;
    }
    this._appendHeader('', this._screenshotsHeader, false /* selectable */);
    this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartDataProvider.EntryType.Screenshot;
    let prevTimestamp;
    for (const screenshot of screenshots) {
      this._entryData.push(screenshot);
      this._timelineData.entryLevels.push(this._currentLevel);
      this._timelineData.entryStartTimes.push(screenshot.timestamp);
      if (prevTimestamp) {
        this._timelineData.entryTotalTimes.push(screenshot.timestamp - prevTimestamp);
      }
      prevTimestamp = screenshot.timestamp;
    }
    if (screenshots.length) {
      this._timelineData.entryTotalTimes.push(this._model.maximumRecordTime() - prevTimestamp);
    }
    ++this._currentLevel;
  }

  /**
   * @param {number} entryIndex
   * @return {!Timeline.TimelineFlameChartDataProvider.EntryType}
   */
  _entryType(entryIndex) {
    return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]];
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {?Element}
   */
  prepareHighlightedEntryInfo(entryIndex) {
    let time = '';
    let title;
    let warning;
    const type = this._entryType(entryIndex);
    if (type === Timeline.TimelineFlameChartDataProvider.EntryType.Event) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      const totalTime = event.duration;
      const selfTime = event.selfTime;
      const /** @const */ eps = 1e-6;
      if (typeof totalTime === 'number') {
        time = Math.abs(totalTime - selfTime) > eps && selfTime > eps ?
            Common.UIString(
                '%s (self %s)', Number.millisToString(totalTime, true), Number.millisToString(selfTime, true)) :
            Number.millisToString(totalTime, true);
      }
      if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
        title = Timeline.TimelineUIUtils.eventTitle(event);
      } else {
        title = this.entryTitle(entryIndex);
      }
      warning = Timeline.TimelineUIUtils.eventWarning(event);
    } else if (type === Timeline.TimelineFlameChartDataProvider.EntryType.Frame) {
      const frame = /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[entryIndex]);
      time =
          Common.UIString('%s ~ %.0f\xa0fps', Number.preciseMillisToString(frame.duration, 1), (1000 / frame.duration));
      title = frame.idle ? Common.UIString('Idle Frame') : Common.UIString('Frame');
      if (frame.hasWarnings()) {
        warning = createElement('span');
        warning.textContent = Common.UIString('Long frame');
      }
    } else {
      return null;
    }
    const element = createElement('div');
    const root = UI.createShadowRootWithCoreStyles(element, 'timeline/timelineFlamechartPopover.css');
    const contents = root.createChild('div', 'timeline-flamechart-popover');
    contents.createChild('span', 'timeline-info-time').textContent = time;
    contents.createChild('span', 'timeline-info-title').textContent = title;
    if (warning) {
      warning.classList.add('timeline-info-warning');
      contents.appendChild(warning);
    }
    return element;
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {string}
   */
  entryColor(entryIndex) {
    // This is not annotated due to closure compiler failure to properly infer cache container's template type.
    function patchColorAndCache(cache, key, lookupColor) {
      let color = cache.get(key);
      if (color) {
        return color;
      }
      const parsedColor = Common.Color.parse(lookupColor(key));
      color = parsedColor.setAlpha(0.7).asString(Common.Color.Format.RGBA) || '';
      cache.set(key, color);
      return color;
    }

    const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
    const type = this._entryType(entryIndex);
    if (type === entryTypes.Event) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      if (this._model.isGenericTrace()) {
        return this._genericTraceEventColor(event);
      }
      if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
        return Timeline.TimelineUIUtils.markerStyleForEvent(event).color;
      }
      if (!SDK.TracingModel.isAsyncPhase(event.phase)) {
        return this._colorForEvent(event);
      }
      if (event.hasCategory(TimelineModel.TimelineModel.Category.Console) ||
          event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)) {
        return this._consoleColorGenerator.colorForID(event.name);
      }
      if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
        const phase =
            TimelineModel.TimelineIRModel.phaseForEvent(event) || TimelineModel.TimelineIRModel.Phases.Uncategorized;
        return patchColorAndCache(
            this._asyncColorByInteractionPhase, phase, Timeline.TimelineUIUtils.interactionPhaseColor);
      }
      const category = Timeline.TimelineUIUtils.eventStyle(event).category;
      return patchColorAndCache(this._asyncColorByCategory, category, () => category.color);
    }
    if (type === entryTypes.Frame) {
      return 'white';
    }
    if (type === entryTypes.InteractionRecord) {
      return 'transparent';
    }
    if (type === entryTypes.ExtensionEvent) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      return this._extensionColorGenerator.colorForID(event.name);
    }
    return '';
  }

  /**
   * @param {!SDK.TracingModel.Event} event
   * @return {string}
   */
  _genericTraceEventColor(event) {
    const key = event.categoriesString || event.name;
    return key ? `hsl(${String.hashCode(key) % 300 + 30}, 40%, 70%)` : '#ccc';
  }

  /**
   * @param {number} entryIndex
   * @param {!CanvasRenderingContext2D} context
   * @param {?string} text
   * @param {number} barX
   * @param {number} barY
   * @param {number} barWidth
   * @param {number} barHeight
   */
  _drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight) {
    const /** @const */ hPadding = 1;
    const frame = /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[entryIndex]);
    barX += hPadding;
    barWidth -= 2 * hPadding;
    context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1' : '#d7f0d1');
    context.fillRect(barX, barY, barWidth, barHeight);

    const frameDurationText = Number.preciseMillisToString(frame.duration, 1);
    const textWidth = context.measureText(frameDurationText).width;
    if (textWidth <= barWidth) {
      context.fillStyle = this.textColor(entryIndex);
      context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, barY + barHeight - 4);
    }
  }

  /**
   * @param {number} entryIndex
   * @param {!CanvasRenderingContext2D} context
   * @param {number} barX
   * @param {number} barY
   * @param {number} barWidth
   * @param {number} barHeight
   */
  async _drawScreenshot(entryIndex, context, barX, barY, barWidth, barHeight) {
    const screenshot = /** @type {!SDK.FilmStripModel.Frame} */ (this._entryData[entryIndex]);
    if (!this._screenshotImageCache.has(screenshot)) {
      this._screenshotImageCache.set(screenshot, null);
      const data = await screenshot.imageDataPromise();
      const image = await UI.loadImageFromData(data);
      this._screenshotImageCache.set(screenshot, image);
      this.dispatchEventToListeners(Timeline.TimelineFlameChartDataProvider.Events.DataChanged);
      return;
    }

    const image = this._screenshotImageCache.get(screenshot);
    if (!image) {
      return;
    }
    const imageX = barX + 1;
    const imageY = barY + 1;
    const imageHeight = barHeight - 2;
    const scale = imageHeight / image.naturalHeight;
    const imageWidth = Math.floor(image.naturalWidth * scale);
    context.save();
    context.beginPath();
    context.rect(barX, barY, barWidth, barHeight);
    context.clip();
    context.drawImage(image, imageX, imageY, imageWidth, imageHeight);
    context.strokeStyle = '#ccc';
    context.strokeRect(imageX - 0.5, imageY - 0.5, Math.min(barWidth - 1, imageWidth + 1), imageHeight);
    context.restore();
  }

  /**
   * @override
   * @param {number} entryIndex
   * @param {!CanvasRenderingContext2D} context
   * @param {?string} text
   * @param {number} barX
   * @param {number} barY
   * @param {number} barWidth
   * @param {number} barHeight
   * @param {number} unclippedBarX
   * @param {number} timeToPixels
   * @return {boolean}
   */
  decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixels) {
    const data = this._entryData[entryIndex];
    const type = this._entryType(entryIndex);
    const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;

    if (type === entryTypes.Frame) {
      this._drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight);
      return true;
    }

    if (type === entryTypes.Screenshot) {
      this._drawScreenshot(entryIndex, context, barX, barY, barWidth, barHeight);
      return true;
    }

    if (type === entryTypes.InteractionRecord) {
      const color = Timeline.TimelineUIUtils.interactionPhaseColor(
          /** @type {!TimelineModel.TimelineIRModel.Phases} */ (data));
      context.fillStyle = color;
      context.fillRect(barX, barY, barWidth - 1, 2);
      context.fillRect(barX, barY - 3, 2, 3);
      context.fillRect(barX + barWidth - 3, barY - 3, 2, 3);
      return false;
    }

    if (type === entryTypes.Event) {
      const event = /** @type {!SDK.TracingModel.Event} */ (data);
      if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
        const timeWaitingForMainThread = TimelineModel.TimelineData.forEvent(event).timeWaitingForMainThread;
        if (timeWaitingForMainThread) {
          context.fillStyle = 'hsla(0, 70%, 60%, 1)';
          const width = Math.floor(unclippedBarX - barX + timeWaitingForMainThread * timeToPixels);
          context.fillRect(barX, barY + barHeight - 3, width, 2);
        }
      }
      if (TimelineModel.TimelineData.forEvent(event).warning) {
        paintWarningDecoration(barX, barWidth - 1.5);
      }
    }

    /**
     * @param {number} x
     * @param {number} width
     */
    function paintWarningDecoration(x, width) {
      const /** @const */ triangleSize = 8;
      context.save();
      context.beginPath();
      context.rect(x, barY, width, barHeight);
      context.clip();
      context.beginPath();
      context.fillStyle = 'red';
      context.moveTo(x + width - triangleSize, barY);
      context.lineTo(x + width, barY);
      context.lineTo(x + width, barY + triangleSize);
      context.fill();
      context.restore();
    }

    return false;
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {boolean}
   */
  forceDecoration(entryIndex) {
    const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
    const type = this._entryType(entryIndex);
    if (type === entryTypes.Frame) {
      return true;
    }
    if (type === entryTypes.Screenshot) {
      return true;
    }

    if (type === entryTypes.Event) {
      const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
      return !!TimelineModel.TimelineData.forEvent(event).warning;
    }
    return false;
  }

  /**
   * @param {!{title: string, model: !SDK.TracingModel}} entry
   */
  appendExtensionEvents(entry) {
    this._extensionInfo.push(entry);
    if (this._timelineData) {
      this._innerAppendExtensionEvents(this._extensionInfo.length - 1);
    }
  }

  /**
   * @param {number} index
   */
  _innerAppendExtensionEvents(index) {
    const entry = this._extensionInfo[index];
    const entryType = Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;
    const allThreads = [].concat(...entry.model.sortedProcesses().map(process => process.sortedThreads()));
    if (!allThreads.length) {
      return;
    }

    const singleTrack =
        allThreads.length === 1 && (!allThreads[0].events().length || !allThreads[0].asyncEvents().length);
    if (!singleTrack) {
      this._appendHeader(entry.title, this._headerLevel1, false /* selectable */);
    }
    const style = singleTrack ? this._headerLevel2 : this._headerLevel1;
    let threadIndex = 0;
    for (const thread of allThreads) {
      const title = singleTrack ? entry.title : thread.name() || ls`Thread ${++threadIndex}`;
      this._appendAsyncEventsGroup(null, title, thread.asyncEvents(), style, entryType, false /* selectable */);
      this._appendSyncEvents(null, thread.events(), title, style, entryType, false /* selectable */);
    }
  }

  /**
   * @param {string} title
   * @param {!PerfUI.FlameChart.GroupStyle} style
   * @param {boolean} selectable
   * @return {!PerfUI.FlameChart.Group}
   */
  _appendHeader(title, style, selectable) {
    const group = {startLevel: this._currentLevel, name: title, style: style, selectable: selectable};
    this._timelineData.groups.push(group);
    return group;
  }

  /**
   * @param {!SDK.TracingModel.Event} event
   * @param {number} level
   * @return {number}
   */
  _appendEvent(event, level) {
    const index = this._entryData.length;
    this._entryData.push(event);
    this._timelineData.entryLevels[index] = level;
    this._timelineData.entryTotalTimes[index] =
        event.duration || Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;
    this._timelineData.entryStartTimes[index] = event.startTime;
    event[Timeline.TimelineFlameChartDataProvider._indexSymbol] = index;
    return index;
  }

  /**
   * @param {!SDK.TracingModel.AsyncEvent} asyncEvent
   * @param {number} level
   */
  _appendAsyncEvent(asyncEvent, level) {
    if (SDK.TracingModel.isNestableAsyncPhase(asyncEvent.phase)) {
      // FIXME: also add steps once we support event nesting in the FlameChart.
      this._appendEvent(asyncEvent, level);
      return;
    }
    const steps = asyncEvent.steps;
    // If we have past steps, put the end event for each range rather than start one.
    const eventOffset = steps.length > 1 && steps[1].phase === SDK.TracingModel.Phase.AsyncStepPast ? 1 : 0;
    for (let i = 0; i < steps.length - 1; ++i) {
      const index = this._entryData.length;
      this._entryData.push(steps[i + eventOffset]);
      const startTime = steps[i].startTime;
      this._timelineData.entryLevels[index] = level;
      this._timelineData.entryTotalTimes[index] = steps[i + 1].startTime - startTime;
      this._timelineData.entryStartTimes[index] = startTime;
    }
  }

  /**
   * @param {!SDK.TracingModel.Event} event
   * @param {number} level
   */
  _appendFlowEvent(event, level) {
    const timelineData = this._timelineData;
    /**
     * @param {!SDK.TracingModel.Event} event
     * @return {number}
     */
    function pushStartFlow(event) {
      const flowIndex = timelineData.flowStartTimes.length;
      timelineData.flowStartTimes.push(event.startTime);
      timelineData.flowStartLevels.push(level);
      return flowIndex;
    }

    /**
     * @param {!SDK.TracingModel.Event} event
     * @param {number} flowIndex
     */
    function pushEndFlow(event, flowIndex) {
      timelineData.flowEndTimes[flowIndex] = event.startTime;
      timelineData.flowEndLevels[flowIndex] = level;
    }

    switch (event.phase) {
      case SDK.TracingModel.Phase.FlowBegin:
        this._flowEventIndexById.set(event.id, pushStartFlow(event));
        break;
      case SDK.TracingModel.Phase.FlowStep:
        pushEndFlow(event, this._flowEventIndexById.get(event.id));
        this._flowEventIndexById.set(event.id, pushStartFlow(event));
        break;
      case SDK.TracingModel.Phase.FlowEnd:
        pushEndFlow(event, this._flowEventIndexById.get(event.id));
        this._flowEventIndexById.delete(event.id);
        break;
    }
  }

  /**
   * @param {!TimelineModel.TimelineFrame} frame
   */
  _appendFrame(frame) {
    const index = this._entryData.length;
    this._entryData.push(frame);
    this._entryIndexToTitle[index] = Number.millisToString(frame.duration, true);
    this._timelineData.entryLevels[index] = this._currentLevel;
    this._timelineData.entryTotalTimes[index] = frame.duration;
    this._timelineData.entryStartTimes[index] = frame.startTime;
  }

  /**
   * @param {number} entryIndex
   * @return {?Timeline.TimelineSelection}
   */
  createSelection(entryIndex) {
    const type = this._entryType(entryIndex);
    let timelineSelection = null;
    if (type === Timeline.TimelineFlameChartDataProvider.EntryType.Event) {
      timelineSelection = Timeline.TimelineSelection.fromTraceEvent(
          /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]));
    } else if (type === Timeline.TimelineFlameChartDataProvider.EntryType.Frame) {
      timelineSelection = Timeline.TimelineSelection.fromFrame(
          /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[entryIndex]));
    }
    if (timelineSelection) {
      this._lastSelection = new Timeline.TimelineFlameChartView.Selection(timelineSelection, entryIndex);
    }
    return timelineSelection;
  }

  /**
   * @override
   * @param {number} value
   * @param {number=} precision
   * @return {string}
   */
  formatValue(value, precision) {
    return Number.preciseMillisToString(value, precision);
  }

  /**
   * @override
   * @param {number} entryIndex
   * @return {boolean}
   */
  canJumpToEntry(entryIndex) {
    return false;
  }

  /**
   * @param {?Timeline.TimelineSelection} selection
   * @return {number}
   */
  entryIndexForSelection(selection) {
    if (!selection || selection.type() === Timeline.TimelineSelection.Type.Range) {
      return -1;
    }

    if (this._lastSelection && this._lastSelection.timelineSelection.object() === selection.object()) {
      return this._lastSelection.entryIndex;
    }
    const index = this._entryData.indexOf(
        /** @type {!SDK.TracingModel.Event|!TimelineModel.TimelineFrame|!TimelineModel.TimelineIRModel.Phases} */
        (selection.object()));
    if (index !== -1) {
      this._lastSelection = new Timeline.TimelineFlameChartView.Selection(selection, index);
    }
    return index;
  }

  /**
   * @param {number} entryIndex
   * @return {boolean}
   */
  buildFlowForInitiator(entryIndex) {
    if (this._lastInitiatorEntry === entryIndex) {
      return false;
    }
    this._lastInitiatorEntry = entryIndex;
    let event = this.eventByIndex(entryIndex);
    const td = this._timelineData;
    td.flowStartTimes = [];
    td.flowStartLevels = [];
    td.flowEndTimes = [];
    td.flowEndLevels = [];
    while (event) {
      // Find the closest ancestor with an initiator.
      let initiator;
      for (; event; event = this._eventParent(event)) {
        initiator = TimelineModel.TimelineData.forEvent(event).initiator();
        if (initiator) {
          break;
        }
      }
      if (!initiator) {
        break;
      }
      const eventIndex = event[Timeline.TimelineFlameChartDataProvider._indexSymbol];
      const initiatorIndex = initiator[Timeline.TimelineFlameChartDataProvider._indexSymbol];
      td.flowStartTimes.push(initiator.endTime || initiator.startTime);
      td.flowStartLevels.push(td.entryLevels[initiatorIndex]);
      td.flowEndTimes.push(event.startTime);
      td.flowEndLevels.push(td.entryLevels[eventIndex]);
      event = initiator;
    }
    return true;
  }

  /**
   * @param {!SDK.TracingModel.Event} event
   * @return {?SDK.TracingModel.Event}
   */
  _eventParent(event) {
    return this._entryParent[event[Timeline.TimelineFlameChartDataProvider._indexSymbol]] || null;
  }

  /**
   * @param {number} entryIndex
   * @return {?SDK.TracingModel.Event}
   */
  eventByIndex(entryIndex) {
    return entryIndex >= 0 && this._entryType(entryIndex) === Timeline.TimelineFlameChartDataProvider.EntryType.Event ?
        /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]) :
        null;
  }

  /**
   * @param {function(!SDK.TracingModel.Event):string} colorForEvent
   */
  setEventColorMapping(colorForEvent) {
    this._colorForEvent = colorForEvent;
  }
};

Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.001;
Timeline.TimelineFlameChartDataProvider._indexSymbol = Symbol('index');

/** @enum {symbol} */
Timeline.TimelineFlameChartDataProvider.Events = {
  DataChanged: Symbol('DataChanged')
};

/** @enum {symbol} */
Timeline.TimelineFlameChartDataProvider.EntryType = {
  Frame: Symbol('Frame'),
  Event: Symbol('Event'),
  InteractionRecord: Symbol('InteractionRecord'),
  ExtensionEvent: Symbol('ExtensionEvent'),
  Screenshot: Symbol('Screenshot'),
};
