/*
 * Copyright (C) 2013 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.
 */

/**
 * @unrestricted
 */
Timeline.TimelineEventOverview = class extends PerfUI.TimelineOverviewBase {
  /**
   * @param {string} id
   * @param {?string} title
   */
  constructor(id, title) {
    super();
    this.element.id = 'timeline-overview-' + id;
    this.element.classList.add('overview-strip');
    /** @type {?Timeline.PerformanceModel} */
    this._model = null;
    if (title)
      this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;
  }

  /**
   * @param {?Timeline.PerformanceModel} model
   */
  setModel(model) {
    this._model = model;
  }

  /**
   * @param {number} begin
   * @param {number} end
   * @param {number} position
   * @param {number} height
   * @param {string} color
   */
  _renderBar(begin, end, position, height, color) {
    const x = begin;
    const width = end - begin;
    const ctx = this.context();
    ctx.fillStyle = color;
    ctx.fillRect(x, position, width, height);
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewInput = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('input', null);
  }

  /**
   * @override
   */
  update() {
    super.update();
    if (!this._model)
      return;
    const height = this.height();
    const descriptors = Timeline.TimelineUIUtils.eventDispatchDesciptors();
    /** @type {!Map.<string,!Timeline.TimelineUIUtils.EventDispatchTypeDescriptor>} */
    const descriptorsByType = new Map();
    let maxPriority = -1;
    for (const descriptor of descriptors) {
      for (const type of descriptor.eventTypes)
        descriptorsByType.set(type, descriptor);
      maxPriority = Math.max(maxPriority, descriptor.priority);
    }

    const minWidth = 2 * window.devicePixelRatio;
    const timeOffset = this._model.timelineModel().minimumRecordTime();
    const timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
    const canvasWidth = this.width();
    const scale = canvasWidth / timeSpan;

    for (let priority = 0; priority <= maxPriority; ++priority) {
      for (const track of this._model.timelineModel().tracks()) {
        for (let i = 0; i < track.events.length; ++i) {
          const event = track.events[i];
          if (event.name !== TimelineModel.TimelineModel.RecordType.EventDispatch)
            continue;
          const descriptor = descriptorsByType.get(event.args['data']['type']);
          if (!descriptor || descriptor.priority !== priority)
            continue;
          const start = Number.constrain(Math.floor((event.startTime - timeOffset) * scale), 0, canvasWidth);
          const end = Number.constrain(Math.ceil((event.endTime - timeOffset) * scale), 0, canvasWidth);
          const width = Math.max(end - start, minWidth);
          this._renderBar(start, start + width, 0, height, descriptor.color);
        }
      }
    }
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewNetwork = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('network', Common.UIString('NET'));
  }

  /**
   * @override
   */
  update() {
    super.update();
    if (!this._model)
      return;
    const timelineModel = this._model.timelineModel();
    const bandHeight = this.height() / 2;
    const timeOffset = timelineModel.minimumRecordTime();
    const timeSpan = timelineModel.maximumRecordTime() - timeOffset;
    const canvasWidth = this.width();
    const scale = canvasWidth / timeSpan;
    const highPath = new Path2D();
    const lowPath = new Path2D();
    const priorities = Protocol.Network.ResourcePriority;
    const highPrioritySet = new Set([priorities.VeryHigh, priorities.High, priorities.Medium]);
    for (const request of timelineModel.networkRequests()) {
      const path = highPrioritySet.has(request.priority) ? highPath : lowPath;
      const s = Math.max(Math.floor((request.startTime - timeOffset) * scale), 0);
      const e = Math.min(Math.ceil((request.endTime - timeOffset) * scale + 1), canvasWidth);
      path.rect(s, 0, e - s, bandHeight - 1);
    }
    const ctx = this.context();
    ctx.save();
    ctx.fillStyle = 'hsl(214, 60%, 60%)';
    ctx.fill(/** @type {?} */ (highPath));
    ctx.translate(0, bandHeight);
    ctx.fillStyle = 'hsl(214, 80%, 80%)';
    ctx.fill(/** @type {?} */ (lowPath));
    ctx.restore();
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewCPUActivity = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('cpu-activity', Common.UIString('CPU'));
    this._backgroundCanvas = this.element.createChild('canvas', 'fill background');
  }

  /**
   * @override
   */
  resetCanvas() {
    super.resetCanvas();
    this._backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio;
    this._backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio;
  }

  /**
   * @override
   */
  update() {
    super.update();
    if (!this._model)
      return;
    const timelineModel = this._model.timelineModel();
    const /** @const */ quantSizePx = 4 * window.devicePixelRatio;
    const width = this.width();
    const height = this.height();
    const baseLine = height;
    const timeOffset = timelineModel.minimumRecordTime();
    const timeSpan = timelineModel.maximumRecordTime() - timeOffset;
    const scale = width / timeSpan;
    const quantTime = quantSizePx / scale;
    const categories = Timeline.TimelineUIUtils.categories();
    const categoryOrder = ['idle', 'loading', 'painting', 'rendering', 'scripting', 'other'];
    const otherIndex = categoryOrder.indexOf('other');
    const idleIndex = 0;
    console.assert(idleIndex === categoryOrder.indexOf('idle'));
    for (let i = idleIndex + 1; i < categoryOrder.length; ++i)
      categories[categoryOrder[i]]._overviewIndex = i;

    const backgroundContext = this._backgroundCanvas.getContext('2d');
    for (const track of timelineModel.tracks()) {
      if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame)
        drawThreadEvents(this.context(), track.events);
      else
        drawThreadEvents(backgroundContext, track.events);
    }
    applyPattern(backgroundContext);

    /**
     * @param {!CanvasRenderingContext2D} ctx
     * @param {!Array<!SDK.TracingModel.Event>} events
     */
    function drawThreadEvents(ctx, events) {
      const quantizer = new Timeline.Quantizer(timeOffset, quantTime, drawSample);
      let x = 0;
      const categoryIndexStack = [];
      const paths = [];
      const lastY = [];
      for (let i = 0; i < categoryOrder.length; ++i) {
        paths[i] = new Path2D();
        paths[i].moveTo(0, height);
        lastY[i] = height;
      }

      /**
       * @param {!Array<number>} counters
       */
      function drawSample(counters) {
        let y = baseLine;
        for (let i = idleIndex + 1; i < categoryOrder.length; ++i) {
          const h = (counters[i] || 0) / quantTime * height;
          y -= h;
          paths[i].bezierCurveTo(x, lastY[i], x, y, x + quantSizePx / 2, y);
          lastY[i] = y;
        }
        x += quantSizePx;
      }

      /**
       * @param {!SDK.TracingModel.Event} e
       */
      function onEventStart(e) {
        const index = categoryIndexStack.length ? categoryIndexStack.peekLast() : idleIndex;
        quantizer.appendInterval(e.startTime, index);
        categoryIndexStack.push(Timeline.TimelineUIUtils.eventStyle(e).category._overviewIndex || otherIndex);
      }

      /**
       * @param {!SDK.TracingModel.Event} e
       */
      function onEventEnd(e) {
        quantizer.appendInterval(e.endTime, categoryIndexStack.pop());
      }

      TimelineModel.TimelineModel.forEachEvent(events, onEventStart, onEventEnd);
      quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex);  // Kick drawing the last bucket.
      for (let i = categoryOrder.length - 1; i > 0; --i) {
        paths[i].lineTo(width, height);
        ctx.fillStyle = categories[categoryOrder[i]].color;
        ctx.fill(paths[i]);
      }
    }

    /**
     * @param {!CanvasRenderingContext2D} ctx
     */
    function applyPattern(ctx) {
      const step = 4 * window.devicePixelRatio;
      ctx.save();
      ctx.lineWidth = step / Math.sqrt(8);
      for (let x = 0.5; x < width + height; x += step) {
        ctx.moveTo(x, 0);
        ctx.lineTo(x - height, height);
      }
      ctx.globalCompositeOperation = 'destination-out';
      ctx.stroke();
      ctx.restore();
    }
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewResponsiveness = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('responsiveness', null);
  }

  /**
   * @override
   */
  update() {
    super.update();
    if (!this._model)
      return;
    const height = this.height();

    const timeOffset = this._model.timelineModel().minimumRecordTime();
    const timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
    const scale = this.width() / timeSpan;
    const frames = this._model.frames();
    // This is due to usage of new signatures of fill() and storke() that closure compiler does not recognize.
    const ctx = /** @type {!Object} */ (this.context());
    const fillPath = new Path2D();
    const markersPath = new Path2D();
    for (let i = 0; i < frames.length; ++i) {
      const frame = frames[i];
      if (!frame.hasWarnings())
        continue;
      paintWarningDecoration(frame.startTime, frame.duration);
    }

    for (const track of this._model.timelineModel().tracks()) {
      const events = track.events;
      for (let i = 0; i < events.length; ++i) {
        if (!TimelineModel.TimelineData.forEvent(events[i]).warning)
          continue;
        paintWarningDecoration(events[i].startTime, events[i].duration);
      }
    }

    ctx.fillStyle = 'hsl(0, 80%, 90%)';
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 2 * window.devicePixelRatio;
    ctx.fill(fillPath);
    ctx.stroke(markersPath);

    /**
     * @param {number} time
     * @param {number} duration
     */
    function paintWarningDecoration(time, duration) {
      const x = Math.round(scale * (time - timeOffset));
      const w = Math.round(scale * duration);
      fillPath.rect(x, 0, w, height);
      markersPath.moveTo(x + w, 0);
      markersPath.lineTo(x + w, height);
    }
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('filmstrip', null);
    this.reset();
  }

  /**
   * @override
   */
  update() {
    super.update();
    const frames = this._model ? this._model.filmStripModel().frames() : [];
    if (!frames.length)
      return;

    const drawGeneration = Symbol('drawGeneration');
    this._drawGeneration = drawGeneration;
    this._imageByFrame(frames[0]).then(image => {
      if (this._drawGeneration !== drawGeneration)
        return;
      if (!image || !image.naturalWidth || !image.naturalHeight)
        return;
      const imageHeight = this.height() - 2 * Timeline.TimelineFilmStripOverview.Padding;
      const imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);
      const popoverScale = Math.min(200 / image.naturalWidth, 1);
      this._emptyImage = new Image(image.naturalWidth * popoverScale, image.naturalHeight * popoverScale);
      this._drawFrames(imageWidth, imageHeight);
    });
  }

  /**
   * @param {!SDK.FilmStripModel.Frame} frame
   * @return {!Promise<?HTMLImageElement>}
   */
  _imageByFrame(frame) {
    let imagePromise = this._frameToImagePromise.get(frame);
    if (!imagePromise) {
      imagePromise = frame.imageDataPromise().then(data => UI.loadImageFromData(data));
      this._frameToImagePromise.set(frame, imagePromise);
    }
    return imagePromise;
  }

  /**
   * @param {number} imageWidth
   * @param {number} imageHeight
   */
  _drawFrames(imageWidth, imageHeight) {
    if (!imageWidth || !this._model)
      return;
    const filmStripModel = this._model.filmStripModel();
    if (!filmStripModel.frames().length)
      return;
    const padding = Timeline.TimelineFilmStripOverview.Padding;
    const width = this.width();
    const zeroTime = filmStripModel.zeroTime();
    const spanTime = filmStripModel.spanTime();
    const scale = spanTime / width;
    const context = this.context();
    const drawGeneration = this._drawGeneration;

    context.beginPath();
    for (let x = padding; x < width; x += imageWidth + 2 * padding) {
      const time = zeroTime + (x + imageWidth / 2) * scale;
      const frame = filmStripModel.frameByTimestamp(time);
      if (!frame)
        continue;
      context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);
      this._imageByFrame(frame).then(drawFrameImage.bind(this, x));
    }
    context.strokeStyle = '#ddd';
    context.stroke();

    /**
     * @param {number} x
     * @param {?HTMLImageElement} image
     * @this {Timeline.TimelineFilmStripOverview}
     */
    function drawFrameImage(x, image) {
      // Ignore draws deferred from a previous update call.
      if (this._drawGeneration !== drawGeneration || !image)
        return;
      context.drawImage(image, x, 1, imageWidth, imageHeight);
    }
  }

  /**
   * @override
   * @param {number} x
   * @return {!Promise<?Element>}
   */
  overviewInfoPromise(x) {
    if (!this._model || !this._model.filmStripModel().frames().length)
      return Promise.resolve(/** @type {?Element} */ (null));

    const time = this.calculator().positionToTime(x);
    const frame = this._model.filmStripModel().frameByTimestamp(time);
    if (frame === this._lastFrame)
      return Promise.resolve(this._lastElement);
    const imagePromise = frame ? this._imageByFrame(frame) : Promise.resolve(this._emptyImage);
    return imagePromise.then(createFrameElement.bind(this));

    /**
     * @this {Timeline.TimelineFilmStripOverview}
     * @param {?HTMLImageElement} image
     * @return {?Element}
     */
    function createFrameElement(image) {
      const element = createElementWithClass('div', 'frame');
      if (image)
        element.createChild('div', 'thumbnail').appendChild(image);
      this._lastFrame = frame;
      this._lastElement = element;
      return element;
    }
  }

  /**
   * @override
   */
  reset() {
    this._lastFrame = undefined;
    this._lastElement = null;
    /** @type {!Map<!SDK.FilmStripModel.Frame,!Promise<!HTMLImageElement>>} */
    this._frameToImagePromise = new Map();
    this._imageWidth = 0;
  }
};

Timeline.TimelineFilmStripOverview.Padding = 2;

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewFrames = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('framerate', Common.UIString('FPS'));
  }

  /**
   * @override
   */
  update() {
    super.update();
    if (!this._model)
      return;
    const frames = this._model.frames();
    if (!frames.length)
      return;
    const height = this.height();
    const /** @const */ padding = 1 * window.devicePixelRatio;
    const /** @const */ baseFrameDurationMs = 1e3 / 60;
    const visualHeight = height - 2 * padding;
    const timeOffset = this._model.timelineModel().minimumRecordTime();
    const timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
    const scale = this.width() / timeSpan;
    const baseY = height - padding;
    const ctx = this.context();
    const bottomY = baseY + 10 * window.devicePixelRatio;
    let x = 0;
    let y = bottomY;

    const lineWidth = window.devicePixelRatio;
    const offset = lineWidth & 1 ? 0.5 : 0;
    const tickDepth = 1.5 * window.devicePixelRatio;
    ctx.beginPath();
    ctx.moveTo(0, y);
    for (let i = 0; i < frames.length; ++i) {
      const frame = frames[i];
      x = Math.round((frame.startTime - timeOffset) * scale) + offset;
      ctx.lineTo(x, y);
      ctx.lineTo(x, y + tickDepth);
      y = frame.idle ? bottomY :
                       Math.round(baseY - visualHeight * Math.min(baseFrameDurationMs / frame.duration, 1)) - offset;
      ctx.lineTo(x, y + tickDepth);
      ctx.lineTo(x, y);
    }
    const lastFrame = frames.peekLast();
    x = Math.round((lastFrame.startTime + lastFrame.duration - timeOffset) * scale) + offset;
    ctx.lineTo(x, y);
    ctx.lineTo(x, bottomY);
    ctx.fillStyle = 'hsl(110, 50%, 88%)';
    ctx.strokeStyle = 'hsl(110, 50%, 60%)';
    ctx.lineWidth = lineWidth;
    ctx.fill();
    ctx.stroke();
  }
};

/**
 * @unrestricted
 */
Timeline.TimelineEventOverviewMemory = class extends Timeline.TimelineEventOverview {
  constructor() {
    super('memory', Common.UIString('HEAP'));
    this._heapSizeLabel = this.element.createChild('div', 'memory-graph-label');
  }

  resetHeapSizeLabels() {
    this._heapSizeLabel.textContent = '';
  }

  /**
   * @override
   */
  update() {
    super.update();
    const ratio = window.devicePixelRatio;

    if (!this._model) {
      this.resetHeapSizeLabels();
      return;
    }

    const tracks = this._model.timelineModel().tracks().filter(
        track => track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame);
    const trackEvents = tracks.map(track => track.events);

    const lowerOffset = 3 * ratio;
    let maxUsedHeapSize = 0;
    let minUsedHeapSize = 100000000000;
    const minTime = this._model.timelineModel().minimumRecordTime();
    const maxTime = this._model.timelineModel().maximumRecordTime();

    /**
     * @param {!SDK.TracingModel.Event} event
     * @return {boolean}
     */
    function isUpdateCountersEvent(event) {
      return event.name === TimelineModel.TimelineModel.RecordType.UpdateCounters;
    }
    for (let i = 0; i < trackEvents.length; i++)
      trackEvents[i] = trackEvents[i].filter(isUpdateCountersEvent);

    /**
     * @param {!SDK.TracingModel.Event} event
     */
    function calculateMinMaxSizes(event) {
      const counters = event.args.data;
      if (!counters || !counters.jsHeapSizeUsed)
        return;
      maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);
      minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);
    }
    for (let i = 0; i < trackEvents.length; i++)
      trackEvents[i].forEach(calculateMinMaxSizes);
    minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);

    const lineWidth = 1;
    const width = this.width();
    const height = this.height() - lowerOffset;
    const xFactor = width / (maxTime - minTime);
    const yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1);

    const histogram = new Array(width);

    /**
     * @param {!SDK.TracingModel.Event} event
     */
    function buildHistogram(event) {
      const counters = event.args.data;
      if (!counters || !counters.jsHeapSizeUsed)
        return;
      const x = Math.round((event.startTime - minTime) * xFactor);
      const y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);
      // TODO(alph): use sum instead of max.
      histogram[x] = Math.max(histogram[x] || 0, y);
    }
    for (let i = 0; i < trackEvents.length; i++)
      trackEvents[i].forEach(buildHistogram);

    const ctx = this.context();
    const heightBeyondView = height + lowerOffset + lineWidth;

    ctx.translate(0.5, 0.5);
    ctx.beginPath();
    ctx.moveTo(-lineWidth, heightBeyondView);
    let y = 0;
    let isFirstPoint = true;
    let lastX = 0;
    for (let x = 0; x < histogram.length; x++) {
      if (typeof histogram[x] === 'undefined')
        continue;
      if (isFirstPoint) {
        isFirstPoint = false;
        y = histogram[x];
        ctx.lineTo(-lineWidth, height - y);
      }
      const nextY = histogram[x];
      if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1)
        ctx.lineTo(x, height - y);
      y = nextY;
      ctx.lineTo(x, height - y);
      lastX = x;
    }
    ctx.lineTo(width + lineWidth, height - y);
    ctx.lineTo(width + lineWidth, heightBeyondView);
    ctx.closePath();

    ctx.fillStyle = 'hsla(220, 90%, 70%, 0.2)';
    ctx.fill();
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = 'hsl(220, 90%, 70%)';
    ctx.stroke();

    this._heapSizeLabel.textContent =
        Common.UIString('%s \u2013 %s', Number.bytesToString(minUsedHeapSize), Number.bytesToString(maxUsedHeapSize));
  }
};

/**
 * @unrestricted
 */
Timeline.Quantizer = class {
  /**
   * @param {number} startTime
   * @param {number} quantDuration
   * @param {function(!Array<number>)} callback
   */
  constructor(startTime, quantDuration, callback) {
    this._lastTime = startTime;
    this._quantDuration = quantDuration;
    this._callback = callback;
    this._counters = [];
    this._remainder = quantDuration;
  }

  /**
   * @param {number} time
   * @param {number} group
   */
  appendInterval(time, group) {
    let interval = time - this._lastTime;
    if (interval <= this._remainder) {
      this._counters[group] = (this._counters[group] || 0) + interval;
      this._remainder -= interval;
      this._lastTime = time;
      return;
    }
    this._counters[group] = (this._counters[group] || 0) + this._remainder;
    this._callback(this._counters);
    interval -= this._remainder;
    while (interval >= this._quantDuration) {
      const counters = [];
      counters[group] = this._quantDuration;
      this._callback(counters);
      interval -= this._quantDuration;
    }
    this._counters = [];
    this._counters[group] = interval;
    this._lastTime = time;
    this._remainder = this._quantDuration - interval;
  }
};
