// Copyright 2017 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.

/**
 * @implements {SDK.SDKModelObserver}
 * @unrestricted
 */
export class PerformanceMonitorImpl extends UI.HBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('performance_monitor/performanceMonitor.css');
    this.contentElement.classList.add('perfmon-pane');
    /** @type {!Array<!{timestamp: number, metrics: !Map<string, number>}>} */
    this._metricsBuffer = [];
    /** @const */
    this._pixelsPerMs = 10 / 1000;
    /** @const */
    this._pollIntervalMs = 500;
    /** @const */
    this._scaleHeight = 16;
    /** @const */
    this._graphHeight = 90;
    this._gridColor = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.08)', UI.ThemeSupport.ColorUsage.Foreground);
    this._controlPane = new PerformanceMonitor.PerformanceMonitor.ControlPane(this.contentElement);
    const chartContainer = this.contentElement.createChild('div', 'perfmon-chart-container');
    this._canvas = /** @type {!HTMLCanvasElement} */ (chartContainer.createChild('canvas'));
    this._canvas.tabIndex = -1;
    UI.ARIAUtils.setAccessibleName(
        this._canvas, Common.UIString('Graphs displaying a real-time view of performance metrics'));
    this.contentElement.createChild('div', 'perfmon-chart-suspend-overlay fill').createChild('div').textContent =
        Common.UIString('Paused');
    this._controlPane.addEventListener(
        PerformanceMonitor.PerformanceMonitor.ControlPane.Events.MetricChanged, this._recalcChartHeight, this);
    SDK.targetManager.observeModels(SDK.PerformanceMetricsModel, this);
  }

  /**
   * @override
   */
  wasShown() {
    if (!this._model) {
      return;
    }
    SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
    this._model.enable();
    this._suspendStateChanged();
  }

  /**
   * @override
   */
  willHide() {
    if (!this._model) {
      return;
    }
    SDK.targetManager.removeEventListener(
        SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
    this._stopPolling();
    this._model.disable();
  }

  /**
   * @override
   * @param {!SDK.PerformanceMetricsModel} model
   */
  modelAdded(model) {
    if (this._model) {
      return;
    }
    this._model = model;
    if (this.isShowing()) {
      this.wasShown();
    }
  }

  /**
   * @override
   * @param {!SDK.PerformanceMetricsModel} model
   */
  modelRemoved(model) {
    if (this._model !== model) {
      return;
    }
    if (this.isShowing()) {
      this.willHide();
    }
    this._model = null;
  }

  _suspendStateChanged() {
    const suspended = SDK.targetManager.allTargetsSuspended();
    if (suspended) {
      this._stopPolling();
    } else {
      this._startPolling();
    }
    this.contentElement.classList.toggle('suspended', suspended);
  }

  _startPolling() {
    this._startTimestamp = 0;
    this._pollTimer = setInterval(() => this._poll(), this._pollIntervalMs);
    this.onResize();
    animate.call(this);

    /**
     * @this {PerformanceMonitor.PerformanceMonitor}
     */
    function animate() {
      this._draw();
      this._animationId = this.contentElement.window().requestAnimationFrame(animate.bind(this));
    }
  }

  _stopPolling() {
    clearInterval(this._pollTimer);
    this.contentElement.window().cancelAnimationFrame(this._animationId);
    this._metricsBuffer = [];
  }

  async _poll() {
    const data = await this._model.requestMetrics();
    const timestamp = data.timestamp;
    const metrics = data.metrics;
    this._metricsBuffer.push({timestamp, metrics: metrics});
    const millisPerWidth = this._width / this._pixelsPerMs;
    // Multiply by 2 as the pollInterval has some jitter and to have some extra samples if window is resized.
    const maxCount = Math.ceil(millisPerWidth / this._pollIntervalMs * 2);
    if (this._metricsBuffer.length > maxCount * 2)  // Multiply by 2 to have a hysteresis.
    {
      this._metricsBuffer.splice(0, this._metricsBuffer.length - maxCount);
    }
    this._controlPane.updateMetrics(metrics);
  }

  _draw() {
    const ctx = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getContext('2d'));
    ctx.save();
    ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
    ctx.clearRect(0, 0, this._width, this._height);
    ctx.save();
    ctx.translate(0, this._scaleHeight);  // Reserve space for the scale bar.
    for (const chartInfo of this._controlPane.charts()) {
      if (!this._controlPane.isActive(chartInfo.metrics[0].name)) {
        continue;
      }
      this._drawChart(ctx, chartInfo, this._graphHeight);
      ctx.translate(0, this._graphHeight);
    }
    ctx.restore();
    this._drawHorizontalGrid(ctx);
    ctx.restore();
  }

  /**
   * @param {!CanvasRenderingContext2D} ctx
   */
  _drawHorizontalGrid(ctx) {
    const labelDistanceSeconds = 10;
    const lightGray = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.02)', UI.ThemeSupport.ColorUsage.Foreground);
    ctx.font = '10px ' + Host.fontFamily();
    ctx.fillStyle = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.55)', UI.ThemeSupport.ColorUsage.Foreground);
    const currentTime = Date.now() / 1000;
    for (let sec = Math.ceil(currentTime);; --sec) {
      const x = this._width - ((currentTime - sec) * 1000 - this._pollIntervalMs) * this._pixelsPerMs;
      if (x < -50) {
        break;
      }
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, this._height);
      if (sec >= 0 && sec % labelDistanceSeconds === 0) {
        ctx.fillText(new Date(sec * 1000).toLocaleTimeString(), x + 4, 12);
      }
      ctx.strokeStyle = sec % labelDistanceSeconds ? lightGray : this._gridColor;
      ctx.stroke();
    }
  }

  /**
   * @param {!CanvasRenderingContext2D} ctx
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} chartInfo
   * @param {number} height
   */
  _drawChart(ctx, chartInfo, height) {
    ctx.save();
    ctx.rect(0, 0, this._width, height);
    ctx.clip();
    const bottomPadding = 8;
    const extraSpace = 1.05;
    const max = this._calcMax(chartInfo) * extraSpace;
    const stackedChartBaseLandscape = chartInfo.stacked ? new Map() : null;
    const paths = [];
    for (let i = chartInfo.metrics.length - 1; i >= 0; --i) {
      const metricInfo = chartInfo.metrics[i];
      paths.push({
        path: this._buildMetricPath(
            chartInfo, metricInfo, height - bottomPadding, max, i ? stackedChartBaseLandscape : null),
        color: metricInfo.color
      });
    }
    const backgroundColor =
        Common.Color.parse(UI.themeSupport.patchColorText('white', UI.ThemeSupport.ColorUsage.Background));
    for (const path of paths.reverse()) {
      const color = path.color;
      ctx.save();
      ctx.fillStyle = backgroundColor.blendWith(Common.Color.parse(color).setAlpha(0.2)).asString(null);
      ctx.fill(path.path);
      ctx.strokeStyle = color;
      ctx.lineWidth = 0.5;
      ctx.stroke(path.path);
      ctx.restore();
    }
    ctx.fillStyle = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.55)', UI.ThemeSupport.ColorUsage.Foreground);
    ctx.font = `10px  ${Host.fontFamily()}`;
    ctx.fillText(chartInfo.title, 8, 10);
    this._drawVerticalGrid(ctx, height - bottomPadding, max, chartInfo);
    ctx.restore();
  }

  /**
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} chartInfo
   * @return {number}
   */
  _calcMax(chartInfo) {
    if (chartInfo.max) {
      return chartInfo.max;
    }
    const width = this._width;
    const startTime = performance.now() - this._pollIntervalMs - width / this._pixelsPerMs;
    let max = -Infinity;
    for (const metricInfo of chartInfo.metrics) {
      for (let i = this._metricsBuffer.length - 1; i >= 0; --i) {
        const metrics = this._metricsBuffer[i];
        const value = metrics.metrics.get(metricInfo.name);
        max = Math.max(max, value);
        if (metrics.timestamp < startTime) {
          break;
        }
      }
    }
    if (!this._metricsBuffer.length) {
      return 10;
    }

    const base10 = Math.pow(10, Math.floor(Math.log10(max)));
    max = Math.ceil(max / base10 / 2) * base10 * 2;

    const alpha = 0.2;
    chartInfo.currentMax = max * alpha + (chartInfo.currentMax || max) * (1 - alpha);
    return chartInfo.currentMax;
  }

  /**
   * @param {!CanvasRenderingContext2D} ctx
   * @param {number} height
   * @param {number} max
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} info
   */
  _drawVerticalGrid(ctx, height, max, info) {
    let base = Math.pow(10, Math.floor(Math.log10(max)));
    const firstDigit = Math.floor(max / base);
    if (firstDigit !== 1 && firstDigit % 2 === 1) {
      base *= 2;
    }
    let scaleValue = Math.floor(max / base) * base;

    const span = max;
    const topPadding = 18;
    const visibleHeight = height - topPadding;
    ctx.fillStyle = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.55)', UI.ThemeSupport.ColorUsage.Foreground);
    ctx.strokeStyle = this._gridColor;
    ctx.beginPath();
    for (let i = 0; i < 2; ++i) {
      const y = calcY(scaleValue);
      const labelText = PerformanceMonitor.PerformanceMonitor.MetricIndicator._formatNumber(scaleValue, info);
      ctx.moveTo(0, y);
      ctx.lineTo(4, y);
      ctx.moveTo(ctx.measureText(labelText).width + 12, y);
      ctx.lineTo(this._width, y);
      ctx.fillText(labelText, 8, calcY(scaleValue) + 3);
      scaleValue /= 2;
    }
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(0, height + 0.5);
    ctx.lineTo(this._width, height + 0.5);
    ctx.strokeStyle = UI.themeSupport.patchColorText('rgba(0, 0, 0, 0.2)', UI.ThemeSupport.ColorUsage.Foreground);
    ctx.stroke();
    /**
     * @param {number} value
     * @return {number}
     */
    function calcY(value) {
      return Math.round(height - visibleHeight * value / span) + 0.5;
    }
  }

  /**
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} chartInfo
   * @param {!PerformanceMonitor.PerformanceMonitor.MetricInfo} metricInfo
   * @param {number} height
   * @param {number} scaleMax
   * @param {?Map<number, number>} stackedChartBaseLandscape
   * @return {!Path2D}
   */
  _buildMetricPath(chartInfo, metricInfo, height, scaleMax, stackedChartBaseLandscape) {
    const path = new Path2D();
    const topPadding = 18;
    const visibleHeight = height - topPadding;
    if (visibleHeight < 1) {
      return path;
    }
    const span = scaleMax;
    const metricName = metricInfo.name;
    const pixelsPerMs = this._pixelsPerMs;
    const startTime = performance.now() - this._pollIntervalMs - this._width / pixelsPerMs;
    const smooth = chartInfo.smooth;

    let x = 0;
    let lastY = 0;
    let lastX = 0;
    if (this._metricsBuffer.length) {
      x = (this._metricsBuffer[0].timestamp - startTime) * pixelsPerMs;
      path.moveTo(x, calcY(0));
      path.lineTo(this._width + 5, calcY(0));
      lastY = calcY(this._metricsBuffer.peekLast().metrics.get(metricName));
      lastX = this._width + 5;
      path.lineTo(lastX, lastY);
    }
    for (let i = this._metricsBuffer.length - 1; i >= 0; --i) {
      const metrics = this._metricsBuffer[i];
      const timestamp = metrics.timestamp;
      let value = metrics.metrics.get(metricName);
      if (stackedChartBaseLandscape) {
        value += stackedChartBaseLandscape.get(timestamp) || 0;
        value = Number.constrain(value, 0, 1);
        stackedChartBaseLandscape.set(timestamp, value);
      }
      const y = calcY(value);
      x = (timestamp - startTime) * pixelsPerMs;
      if (smooth) {
        const midX = (lastX + x) / 2;
        path.bezierCurveTo(midX, lastY, midX, y, x, y);
      } else {
        path.lineTo(x, lastY);
        path.lineTo(x, y);
      }
      lastX = x;
      lastY = y;
      if (timestamp < startTime) {
        break;
      }
    }
    return path;

    /**
     * @param {number} value
     * @return {number}
     */
    function calcY(value) {
      return Math.round(height - visibleHeight * value / span) + 0.5;
    }
  }

  /**
   * @override
   */
  onResize() {
    super.onResize();
    this._width = this._canvas.offsetWidth;
    this._canvas.width = Math.round(this._width * window.devicePixelRatio);
    this._recalcChartHeight();
  }

  _recalcChartHeight() {
    let height = this._scaleHeight;
    for (const chartInfo of this._controlPane.charts()) {
      if (this._controlPane.isActive(chartInfo.metrics[0].name)) {
        height += this._graphHeight;
      }
    }
    this._height = Math.ceil(height * window.devicePixelRatio);
    this._canvas.height = this._height;
    this._canvas.style.height = `${this._height / window.devicePixelRatio}px`;
  }
}

/** @enum {symbol} */
export const Format = {
  Percent: Symbol('Percent'),
  Bytes: Symbol('Bytes'),
};

export class ControlPane extends Common.Object {
  /**
   * @param {!Element} parent
   */
  constructor(parent) {
    super();
    this.element = parent.createChild('div', 'perfmon-control-pane');

    this._enabledChartsSetting =
        Common.settings.createSetting('perfmonActiveIndicators2', ['TaskDuration', 'JSHeapTotalSize', 'Nodes']);
    /** @type {!Set<string>} */
    this._enabledCharts = new Set(this._enabledChartsSetting.get());
    const format = PerformanceMonitor.PerformanceMonitor.Format;

    /** @type {!Array<!PerformanceMonitor.PerformanceMonitor.ChartInfo>} */
    this._chartsInfo = [
      {
        title: Common.UIString('CPU usage'),
        metrics: [
          {name: 'TaskDuration', color: '#999'}, {name: 'ScriptDuration', color: 'orange'},
          {name: 'LayoutDuration', color: 'blueviolet'}, {name: 'RecalcStyleDuration', color: 'violet'}
        ],
        format: format.Percent,
        smooth: true,
        stacked: true,
        color: 'red',
        max: 1
      },
      {
        title: Common.UIString('JS heap size'),
        metrics: [{name: 'JSHeapTotalSize', color: '#99f'}, {name: 'JSHeapUsedSize', color: 'blue'}],
        format: format.Bytes,
        color: 'blue'
      },
      {title: Common.UIString('DOM Nodes'), metrics: [{name: 'Nodes', color: 'green'}]},
      {title: Common.UIString('JS event listeners'), metrics: [{name: 'JSEventListeners', color: 'yellowgreen'}]},
      {title: Common.UIString('Documents'), metrics: [{name: 'Documents', color: 'darkblue'}]},
      {title: Common.UIString('Document Frames'), metrics: [{name: 'Frames', color: 'darkcyan'}]},
      {title: Common.UIString('Layouts / sec'), metrics: [{name: 'LayoutCount', color: 'hotpink'}]},
      {title: Common.UIString('Style recalcs / sec'), metrics: [{name: 'RecalcStyleCount', color: 'deeppink'}]}
    ];
    for (const info of this._chartsInfo) {
      for (const metric of info.metrics) {
        metric.color = UI.themeSupport.patchColorText(metric.color, UI.ThemeSupport.ColorUsage.Foreground);
      }
    }

    /** @type {!Map<string, !PerformanceMonitor.PerformanceMonitor.MetricIndicator>} */
    this._indicators = new Map();
    for (const chartInfo of this._chartsInfo) {
      const chartName = chartInfo.metrics[0].name;
      const active = this._enabledCharts.has(chartName);
      const indicator = new PerformanceMonitor.PerformanceMonitor.MetricIndicator(
          this.element, chartInfo, active, this._onToggle.bind(this, chartName));
      this._indicators.set(chartName, indicator);
    }
  }

  /**
   * @param {string} chartName
   * @param {boolean} active
   */
  _onToggle(chartName, active) {
    if (active) {
      this._enabledCharts.add(chartName);
    } else {
      this._enabledCharts.delete(chartName);
    }
    this._enabledChartsSetting.set(Array.from(this._enabledCharts));
    this.dispatchEventToListeners(PerformanceMonitor.PerformanceMonitor.ControlPane.Events.MetricChanged);
  }

  /**
   * @return {!Array<!PerformanceMonitor.PerformanceMonitor.ChartInfo>}
   */
  charts() {
    return this._chartsInfo;
  }

  /**
   * @param {string} metricName
   * @return {boolean}
   */
  isActive(metricName) {
    return this._enabledCharts.has(metricName);
  }

  /**
   * @param {!Map<string, number>} metrics
   */
  updateMetrics(metrics) {
    for (const name of this._indicators.keys()) {
      if (metrics.has(name)) {
        this._indicators.get(name).setValue(metrics.get(name));
      }
    }
  }
}

/** @enum {symbol} */
export const Events = {
  MetricChanged: Symbol('MetricChanged')
};

export class MetricIndicator {
  /**
   * @param {!Element} parent
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} info
   * @param {boolean} active
   * @param {function(boolean)} onToggle
   */
  constructor(parent, info, active, onToggle) {
    const color = info.color || info.metrics[0].color;
    this._info = info;
    this._active = active;
    this._onToggle = onToggle;
    this.element = parent.createChild('div', 'perfmon-indicator');
    this._swatchElement = UI.Icon.create('smallicon-checkmark-square', 'perfmon-indicator-swatch');
    this._swatchElement.style.backgroundColor = color;
    this.element.appendChild(this._swatchElement);
    this.element.createChild('div', 'perfmon-indicator-title').textContent = info.title;
    this._valueElement = this.element.createChild('div', 'perfmon-indicator-value');
    this._valueElement.style.color = color;
    this.element.addEventListener('click', () => this._toggleIndicator());
    this.element.addEventListener('keypress', event => this._handleKeypress(event));
    this.element.classList.toggle('active', active);
    UI.ARIAUtils.markAsCheckbox(this.element);
    UI.ARIAUtils.setChecked(this.element, this._active);
    this.element.tabIndex = 0;
  }

  /**
   * @param {number} value
   * @param {!PerformanceMonitor.PerformanceMonitor.ChartInfo} info
   * @return {string}
   */
  static _formatNumber(value, info) {
    if (!PerformanceMonitor.PerformanceMonitor.MetricIndicator._numberFormatter) {
      PerformanceMonitor.PerformanceMonitor.MetricIndicator._numberFormatter =
          new Intl.NumberFormat('en-US', {maximumFractionDigits: 1});
      PerformanceMonitor.PerformanceMonitor.MetricIndicator._percentFormatter =
          new Intl.NumberFormat('en-US', {maximumFractionDigits: 1, style: 'percent'});
    }
    switch (info.format) {
      case PerformanceMonitor.PerformanceMonitor.Format.Percent:
        return PerformanceMonitor.PerformanceMonitor.MetricIndicator._percentFormatter.format(value);
      case PerformanceMonitor.PerformanceMonitor.Format.Bytes:
        return Number.bytesToString(value);
      default:
        return PerformanceMonitor.PerformanceMonitor.MetricIndicator._numberFormatter.format(value);
    }
  }

  /**
   * @param {number} value
   */
  setValue(value) {
    this._valueElement.textContent =
        PerformanceMonitor.PerformanceMonitor.MetricIndicator._formatNumber(value, this._info);
  }

  _toggleIndicator() {
    this._active = !this._active;
    this.element.classList.toggle('active', this._active);
    UI.ARIAUtils.setChecked(this.element, this._active);
    this._onToggle(this._active);
  }

  /**
   * @param {!Event} event
   */
  _handleKeypress(event) {
    const keyboardEvent = /** @type {!KeyboardEvent} */ (event);
    if (keyboardEvent.key === ' ' || keyboardEvent.key === 'Enter') {
      this._toggleIndicator();
    }
  }
}

export const _format = new Intl.NumberFormat('en-US', {maximumFractionDigits: 1});

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

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

/**
 * @constructor
 */
PerformanceMonitor.PerformanceMonitor = PerformanceMonitorImpl;

/**
 * @typedef {!{
 *   name: string,
 *   color: string
 * }}
 */
PerformanceMonitor.PerformanceMonitor.MetricInfo;

PerformanceMonitor.PerformanceMonitor.Format = Format;

/**
 * @typedef {!{
  *   title: string,
  *   metrics: !Array<!PerformanceMonitor.PerformanceMonitor.MetricInfo>,
  *   max: (number|undefined),
  *   currentMax: (number|undefined),
  *   format: (!Format|undefined),
  *   smooth: (boolean|undefined)
  * }}
  */
PerformanceMonitor.PerformanceMonitor.ChartInfo;

/**
 * @constructor
 */
PerformanceMonitor.PerformanceMonitor.ControlPane = ControlPane;

/** @enum {symbol} */
PerformanceMonitor.PerformanceMonitor.ControlPane.Events = Events;

/**
 * @constructor
 */
PerformanceMonitor.PerformanceMonitor.MetricIndicator = MetricIndicator;
PerformanceMonitor.PerformanceMonitor.MetricIndicator._format = _format;
