/*
 * Copyright (C) 2012 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.CountersGraph = class extends UI.VBox {
  /**
   * @param {!Timeline.TimelineModeViewDelegate} delegate
   */
  constructor(delegate) {
    super();
    this.element.id = 'memory-graphs-container';

    this._delegate = delegate;
    this._calculator = new Timeline.CountersGraph.Calculator();

    // Create selectors
    this._header = new UI.HBox();
    this._header.element.classList.add('timeline-memory-header');
    this._header.show(this.element);
    this._toolbar = new UI.Toolbar('timeline-memory-toolbar');
    this._header.element.appendChild(this._toolbar.element);

    this._graphsContainer = new UI.VBox();
    this._graphsContainer.show(this.element);
    const canvasWidget = new UI.VBoxWithResizeCallback(this._resize.bind(this));
    canvasWidget.show(this._graphsContainer.element);
    this._createCurrentValuesBar();
    this._canvasContainer = canvasWidget.element;
    this._canvasContainer.id = 'memory-graphs-canvas-container';
    this._canvas = this._canvasContainer.createChild('canvas');
    this._canvas.id = 'memory-counters-graph';

    this._canvasContainer.addEventListener('mouseover', this._onMouseMove.bind(this), true);
    this._canvasContainer.addEventListener('mousemove', this._onMouseMove.bind(this), true);
    this._canvasContainer.addEventListener('mouseleave', this._onMouseLeave.bind(this), true);
    this._canvasContainer.addEventListener('click', this._onClick.bind(this), true);
    // We create extra timeline grid here to reuse its event dividers.
    this._timelineGrid = new PerfUI.TimelineGrid();
    this._canvasContainer.appendChild(this._timelineGrid.dividersElement);

    this._counters = [];
    this._counterUI = [];

    this._countersByName = {};
    this._countersByName['jsHeapSizeUsed'] = this._createCounter(
        Common.UIString('JS Heap'), Common.UIString('JS Heap: %s'), 'hsl(220, 90%, 43%)', Number.bytesToString);
    this._countersByName['documents'] =
        this._createCounter(Common.UIString('Documents'), Common.UIString('Documents: %s'), 'hsl(0, 90%, 43%)');
    this._countersByName['nodes'] =
        this._createCounter(Common.UIString('Nodes'), Common.UIString('Nodes: %s'), 'hsl(120, 90%, 43%)');
    this._countersByName['jsEventListeners'] =
        this._createCounter(Common.UIString('Listeners'), Common.UIString('Listeners: %s'), 'hsl(38, 90%, 43%)');
    this._gpuMemoryCounter = this._createCounter(
        Common.UIString('GPU Memory'), Common.UIString('GPU Memory [KB]: %s'), 'hsl(300, 90%, 43%)',
        Number.bytesToString);
    this._countersByName['gpuMemoryUsedKB'] = this._gpuMemoryCounter;
  }

  /**
   * @param {?Timeline.PerformanceModel} model
   * @param {?TimelineModel.TimelineModel.Track} track
   */
  setModel(model, track) {
    if (this._model !== model) {
      if (this._model) {
        this._model.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
      }
      this._model = model;
      if (this._model) {
        this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
      }
    }
    this._calculator.setZeroTime(model ? model.timelineModel().minimumRecordTime() : 0);
    for (let i = 0; i < this._counters.length; ++i) {
      this._counters[i].reset();
      this._counterUI[i].reset();
    }
    this.scheduleRefresh();
    this._track = track;
    if (!track) {
      return;
    }
    const events = track.syncEvents();
    for (let i = 0; i < events.length; ++i) {
      const event = events[i];
      if (event.name !== TimelineModel.TimelineModel.RecordType.UpdateCounters) {
        continue;
      }

      const counters = event.args.data;
      if (!counters) {
        return;
      }
      for (const name in counters) {
        const counter = this._countersByName[name];
        if (counter) {
          counter.appendSample(event.startTime, counters[name]);
        }
      }

      const gpuMemoryLimitCounterName = 'gpuMemoryLimitKB';
      if (gpuMemoryLimitCounterName in counters) {
        this._gpuMemoryCounter.setLimit(counters[gpuMemoryLimitCounterName]);
      }
    }
  }

  _createCurrentValuesBar() {
    this._currentValuesBar = this._graphsContainer.element.createChild('div');
    this._currentValuesBar.id = 'counter-values-bar';
  }

  /**
   * @param {string} uiName
   * @param {string} uiValueTemplate
   * @param {string} color
   * @param {function(number):string=} formatter
   * @return {!Timeline.CountersGraph.Counter}
   */
  _createCounter(uiName, uiValueTemplate, color, formatter) {
    const counter = new Timeline.CountersGraph.Counter();
    this._counters.push(counter);
    this._counterUI.push(
        new Timeline.CountersGraph.CounterUI(this, uiName, uiValueTemplate, color, counter, formatter));
    return counter;
  }

  /**
   * @return {?Element}
   */
  resizerElement() {
    return this._header.element;
  }

  _resize() {
    const parentElement = this._canvas.parentElement;
    this._canvas.width = parentElement.clientWidth * window.devicePixelRatio;
    this._canvas.height = parentElement.clientHeight * window.devicePixelRatio;
    this._calculator.setDisplayWidth(this._canvas.width);
    this.refresh();
  }

  /**
   * @param {!Common.Event} event
   */
  _onWindowChanged(event) {
    const window = /** @type {!Timeline.PerformanceModel.Window} */ (event.data.window);
    this._calculator.setWindow(window.left, window.right);
    this.scheduleRefresh();
  }

  scheduleRefresh() {
    UI.invokeOnceAfterBatchUpdate(this, this.refresh);
  }

  draw() {
    this._clear();
    for (const counter of this._counters) {
      counter._calculateVisibleIndexes(this._calculator);
      counter._calculateXValues(this._canvas.width);
    }
    for (const counterUI of this._counterUI) {
      counterUI._drawGraph(this._canvas);
    }
  }

  /**
   * @param {!Event} event
   */
  _onClick(event) {
    const x = event.x - this._canvasContainer.totalOffsetLeft();
    let minDistance = Infinity;
    let bestTime;
    for (const counterUI of this._counterUI) {
      if (!counterUI.counter.times.length) {
        continue;
      }
      const index = counterUI._recordIndexAt(x);
      const distance = Math.abs(x * window.devicePixelRatio - counterUI.counter.x[index]);
      if (distance < minDistance) {
        minDistance = distance;
        bestTime = counterUI.counter.times[index];
      }
    }
    if (bestTime !== undefined) {
      this._delegate.selectEntryAtTime(
          this._track.events.length ? this._track.events : this._track.asyncEvents, bestTime);
    }
  }

  /**
   * @param {!Event} event
   */
  _onMouseLeave(event) {
    delete this._markerXPosition;
    this._clearCurrentValueAndMarker();
  }

  _clearCurrentValueAndMarker() {
    for (let i = 0; i < this._counterUI.length; i++) {
      this._counterUI[i]._clearCurrentValueAndMarker();
    }
  }

  /**
   * @param {!Event} event
   */
  _onMouseMove(event) {
    const x = event.x - this._canvasContainer.totalOffsetLeft();
    this._markerXPosition = x;
    this._refreshCurrentValues();
  }

  _refreshCurrentValues() {
    if (this._markerXPosition === undefined) {
      return;
    }
    for (let i = 0; i < this._counterUI.length; ++i) {
      this._counterUI[i].updateCurrentValue(this._markerXPosition);
    }
  }

  refresh() {
    this._timelineGrid.updateDividers(this._calculator);
    this.draw();
    this._refreshCurrentValues();
  }

  _clear() {
    const ctx = this._canvas.getContext('2d');
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  }
};

/**
 * @unrestricted
 */
Timeline.CountersGraph.Counter = class {
  constructor() {
    this.times = [];
    this.values = [];
  }

  /**
   * @param {number} time
   * @param {number} value
   */
  appendSample(time, value) {
    if (this.values.length && this.values.peekLast() === value) {
      return;
    }
    this.times.push(time);
    this.values.push(value);
  }

  reset() {
    this.times = [];
    this.values = [];
  }

  /**
   * @param {number} value
   */
  setLimit(value) {
    this._limitValue = value;
  }

  /**
   * @return {!{min: number, max: number}}
   */
  _calculateBounds() {
    let maxValue;
    let minValue;
    for (let i = this._minimumIndex; i <= this._maximumIndex; i++) {
      const value = this.values[i];
      if (minValue === undefined || value < minValue) {
        minValue = value;
      }
      if (maxValue === undefined || value > maxValue) {
        maxValue = value;
      }
    }
    minValue = minValue || 0;
    maxValue = maxValue || 1;
    if (this._limitValue) {
      if (maxValue > this._limitValue * 0.5) {
        maxValue = Math.max(maxValue, this._limitValue);
      }
      minValue = Math.min(minValue, this._limitValue);
    }
    return {min: minValue, max: maxValue};
  }

  /**
   * @param {!Timeline.CountersGraph.Calculator} calculator
   */
  _calculateVisibleIndexes(calculator) {
    const start = calculator.minimumBoundary();
    const end = calculator.maximumBoundary();

    // Maximum index of element whose time <= start.
    this._minimumIndex = Number.constrain(this.times.upperBound(start) - 1, 0, this.times.length - 1);

    // Minimum index of element whose time >= end.
    this._maximumIndex = Number.constrain(this.times.lowerBound(end), 0, this.times.length - 1);

    // Current window bounds.
    this._minTime = start;
    this._maxTime = end;
  }

  /**
   * @param {number} width
   */
  _calculateXValues(width) {
    if (!this.values.length) {
      return;
    }

    const xFactor = width / (this._maxTime - this._minTime);

    this.x = new Array(this.values.length);
    for (let i = this._minimumIndex + 1; i <= this._maximumIndex; i++) {
      this.x[i] = xFactor * (this.times[i] - this._minTime);
    }
  }
};

/**
 * @unrestricted
 */
Timeline.CountersGraph.CounterUI = class {
  /**
   * @param {!Timeline.CountersGraph} countersPane
   * @param {string} title
   * @param {string} currentValueLabel
   * @param {string} graphColor
   * @param {!Timeline.CountersGraph.Counter} counter
   * @param {(function(number): string)|undefined} formatter
   */
  constructor(countersPane, title, currentValueLabel, graphColor, counter, formatter) {
    this._countersPane = countersPane;
    this.counter = counter;
    this._formatter = formatter || Number.withThousandsSeparator;

    this._setting = Common.settings.createSetting('timelineCountersGraph-' + title, true);
    this._setting.setTitle(title);
    this._filter = new UI.ToolbarSettingCheckbox(this._setting, title);
    this._filter.inputElement.classList.add('-theme-preserve');
    const color = Common.Color.parse(graphColor).setAlpha(0.5).asString(Common.Color.Format.RGBA);
    if (color) {
      this._filter.element.backgroundColor = color;
      this._filter.element.borderColor = 'transparent';
    }
    this._filter.inputElement.addEventListener('click', this._toggleCounterGraph.bind(this));
    countersPane._toolbar.appendToolbarItem(this._filter);
    this._range = this._filter.element.createChild('span', 'range');

    this._value = countersPane._currentValuesBar.createChild('span', 'memory-counter-value');
    this._value.style.color = graphColor;
    this.graphColor = graphColor;
    this.limitColor = Common.Color.parse(graphColor).setAlpha(0.3).asString(Common.Color.Format.RGBA);
    this.graphYValues = [];
    this._verticalPadding = 10;

    this._currentValueLabel = currentValueLabel;
    this._marker = countersPane._canvasContainer.createChild('div', 'memory-counter-marker');
    this._marker.style.backgroundColor = graphColor;
    this._clearCurrentValueAndMarker();
  }

  reset() {
    this._range.textContent = '';
  }

  /**
   * @param {number} minValue
   * @param {number} maxValue
   */
  setRange(minValue, maxValue) {
    const min = this._formatter(minValue);
    const max = this._formatter(maxValue);
    this._range.textContent = Common.UIString('[%s\xa0\u2013\xa0%s]', min, max);
  }

  /**
   * @param {!Common.Event} event
   */
  _toggleCounterGraph(event) {
    this._value.classList.toggle('hidden', !this._filter.checked());
    this._countersPane.refresh();
  }

  /**
   * @param {number} x
   * @return {number}
   */
  _recordIndexAt(x) {
    return this.counter.x.upperBound(
               x * window.devicePixelRatio, null, this.counter._minimumIndex + 1, this.counter._maximumIndex + 1) -
        1;
  }

  /**
   * @param {number} x
   */
  updateCurrentValue(x) {
    if (!this.visible() || !this.counter.values.length || !this.counter.x) {
      return;
    }
    const index = this._recordIndexAt(x);
    const value = Number.withThousandsSeparator(this.counter.values[index]);
    this._value.textContent = Common.UIString(this._currentValueLabel, value);
    const y = this.graphYValues[index] / window.devicePixelRatio;
    this._marker.style.left = x + 'px';
    this._marker.style.top = y + 'px';
    this._marker.classList.remove('hidden');
  }

  _clearCurrentValueAndMarker() {
    this._value.textContent = '';
    this._marker.classList.add('hidden');
  }

  /**
   * @param {!HTMLCanvasElement} canvas
   */
  _drawGraph(canvas) {
    const ctx = canvas.getContext('2d');
    const width = canvas.width;
    const height = canvas.height - 2 * this._verticalPadding;
    if (height <= 0) {
      this.graphYValues = [];
      return;
    }
    const originY = this._verticalPadding;
    const counter = this.counter;
    const values = counter.values;

    if (!values.length) {
      return;
    }

    const bounds = counter._calculateBounds();
    const minValue = bounds.min;
    const maxValue = bounds.max;
    this.setRange(minValue, maxValue);

    if (!this.visible()) {
      return;
    }

    const yValues = this.graphYValues;
    const maxYRange = maxValue - minValue;
    const yFactor = maxYRange ? height / (maxYRange) : 1;

    ctx.save();
    ctx.lineWidth = window.devicePixelRatio;
    if (ctx.lineWidth % 2) {
      ctx.translate(0.5, 0.5);
    }
    ctx.beginPath();
    let value = values[counter._minimumIndex];
    let currentY = Math.round(originY + height - (value - minValue) * yFactor);
    ctx.moveTo(0, currentY);
    let i = counter._minimumIndex;
    for (; i <= counter._maximumIndex; i++) {
      const x = Math.round(counter.x[i]);
      ctx.lineTo(x, currentY);
      const currentValue = values[i];
      if (typeof currentValue !== 'undefined') {
        value = currentValue;
      }
      currentY = Math.round(originY + height - (value - minValue) * yFactor);
      ctx.lineTo(x, currentY);
      yValues[i] = currentY;
    }
    yValues.length = i;
    ctx.lineTo(width, currentY);
    ctx.strokeStyle = this.graphColor;
    ctx.stroke();
    if (counter._limitValue) {
      const limitLineY = Math.round(originY + height - (counter._limitValue - minValue) * yFactor);
      ctx.moveTo(0, limitLineY);
      ctx.lineTo(width, limitLineY);
      ctx.strokeStyle = this.limitColor;
      ctx.stroke();
    }
    ctx.closePath();
    ctx.restore();
  }

  /**
   * @return {boolean}
   */
  visible() {
    return this._filter.checked();
  }
};

/**
 * @implements {PerfUI.TimelineGrid.Calculator}
 * @unrestricted
 */
Timeline.CountersGraph.Calculator = class {
  /**
   * @param {number} time
   */
  setZeroTime(time) {
    this._zeroTime = time;
  }

  /**
   * @override
   * @param {number} time
   * @return {number}
   */
  computePosition(time) {
    return (time - this._minimumBoundary) / this.boundarySpan() * this._workingArea;
  }

  setWindow(minimumBoundary, maximumBoundary) {
    this._minimumBoundary = minimumBoundary;
    this._maximumBoundary = maximumBoundary;
  }

  /**
   * @param {number} clientWidth
   */
  setDisplayWidth(clientWidth) {
    this._workingArea = clientWidth;
  }

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

  /**
   * @override
   * @return {number}
   */
  maximumBoundary() {
    return this._maximumBoundary;
  }

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

  /**
   * @override
   * @return {number}
   */
  zeroTime() {
    return this._zeroTime;
  }

  /**
   * @override
   * @return {number}
   */
  boundarySpan() {
    return this._maximumBoundary - this._minimumBoundary;
  }
};
