<!DOCTYPE html>
<!--
Copyright (c) 2013 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.
-->

<link rel="stylesheet" href="/tracing/ui/extras/chrome/cc/picture_ops_chart_view.css">

<link rel="import" href="/tracing/ui/base/dom_helpers.html">

<script>
'use strict';

tr.exportTo('tr.ui.e.chrome.cc', function() {
  var BAR_PADDING = 1;
  var BAR_WIDTH = 5;
  var CHART_PADDING_LEFT = 65;
  var CHART_PADDING_RIGHT = 30;
  var CHART_PADDING_BOTTOM = 35;
  var CHART_PADDING_TOP = 20;
  var AXIS_PADDING_LEFT = 55;
  var AXIS_PADDING_RIGHT = 30;
  var AXIS_PADDING_BOTTOM = 35;
  var AXIS_PADDING_TOP = 20;
  var AXIS_TICK_SIZE = 5;
  var AXIS_LABEL_PADDING = 5;
  var VERTICAL_TICKS = 5;
  var HUE_CHAR_CODE_ADJUSTMENT = 5.7;

  /**
   * Provides a chart showing the cumulative time spent in Skia operations
   * during picture rasterization.
   *
   * @constructor
   */
  var PictureOpsChartView =
      tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-view');

  PictureOpsChartView.prototype = {
    __proto__: HTMLUnknownElement.prototype,

    decorate: function() {
      this.picture_ = undefined;
      this.pictureOps_ = undefined;
      this.opCosts_ = undefined;

      this.chartScale_ = window.devicePixelRatio;

      this.chart_ = document.createElement('canvas');
      this.chartCtx_ = this.chart_.getContext('2d');
      this.appendChild(this.chart_);

      this.selectedOpIndex_ = undefined;
      this.chartWidth_ = 0;
      this.chartHeight_ = 0;
      this.dimensionsHaveChanged_ = true;

      this.currentBarMouseOverTarget_ = undefined;

      this.ninetyFifthPercentileCost_ = 0;
      this.totalOpCost_ = 0;

      this.chart_.addEventListener('click', this.onClick_.bind(this));
      this.chart_.addEventListener('mousemove', this.onMouseMove_.bind(this));

      this.usePercentileScale_ = false;
      this.usePercentileScaleCheckbox_ = tr.ui.b.createCheckBox(
          this, 'usePercentileScale',
          'PictureOpsChartView.usePercentileScale', false,
          'Limit to 95%-ile');
      this.usePercentileScaleCheckbox_.classList.add('use-percentile-scale');
      this.appendChild(this.usePercentileScaleCheckbox_);
    },

    get dimensionsHaveChanged() {
      return this.dimensionsHaveChanged_;
    },

    set dimensionsHaveChanged(dimensionsHaveChanged) {
      this.dimensionsHaveChanged_ = dimensionsHaveChanged;
    },

    get usePercentileScale() {
      return this.usePercentileScale_;
    },

    set usePercentileScale(usePercentileScale) {
      this.usePercentileScale_ = usePercentileScale;
      this.drawChartContents_();
    },

    get numOps() {
      return this.opCosts_.length;
    },

    get selectedOpIndex() {
      return this.selectedOpIndex_;
    },

    set selectedOpIndex(selectedOpIndex) {
      if (selectedOpIndex < 0) throw new Error('Invalid index');
      if (selectedOpIndex >= this.numOps) throw new Error('Invalid index');

      this.selectedOpIndex_ = selectedOpIndex;
    },

    get picture() {
      return this.picture_;
    },

    set picture(picture) {
      this.picture_ = picture;
      this.pictureOps_ = picture.tagOpsWithTimings(picture.getOps());
      this.currentBarMouseOverTarget_ = undefined;
      this.processPictureData_();
      this.dimensionsHaveChanged = true;
    },

    processPictureData_: function() {
      if (this.pictureOps_ === undefined)
        return;

      var totalOpCost = 0;

      // Take a copy of the picture ops data for sorting.
      this.opCosts_ = this.pictureOps_.map(function(op) {
        totalOpCost += op.cmd_time;
        return op.cmd_time;
      });
      this.opCosts_.sort();

      var ninetyFifthPercentileCostIndex = Math.floor(
          this.opCosts_.length * 0.95);
      this.ninetyFifthPercentileCost_ =
          this.opCosts_[ninetyFifthPercentileCostIndex];
      this.maxCost_ = this.opCosts_[this.opCosts_.length - 1];

      this.totalOpCost_ = totalOpCost;
    },

    extractBarIndex_: function(e) {

      var index = undefined;

      if (this.pictureOps_ === undefined ||
          this.pictureOps_.length === 0)
        return index;

      var x = e.offsetX;
      var y = e.offsetY;

      var totalBarWidth = (BAR_WIDTH + BAR_PADDING) * this.pictureOps_.length;

      var chartLeft = CHART_PADDING_LEFT;
      var chartTop = 0;
      var chartBottom = this.chartHeight_ - CHART_PADDING_BOTTOM;
      var chartRight = chartLeft + totalBarWidth;

      if (x < chartLeft || x > chartRight || y < chartTop || y > chartBottom)
        return index;

      index = Math.floor((x - chartLeft) / totalBarWidth *
          this.pictureOps_.length);

      index = tr.b.clamp(index, 0, this.pictureOps_.length - 1);

      return index;
    },

    onClick_: function(e) {

      var barClicked = this.extractBarIndex_(e);

      if (barClicked === undefined)
        return;

      // If we click on the already selected item we should deselect.
      if (barClicked === this.selectedOpIndex)
        this.selectedOpIndex = undefined;
      else
        this.selectedOpIndex = barClicked;

      e.preventDefault();

      tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
    },

    onMouseMove_: function(e) {

      var lastBarMouseOverTarget = this.currentBarMouseOverTarget_;
      this.currentBarMouseOverTarget_ = this.extractBarIndex_(e);

      if (this.currentBarMouseOverTarget_ === lastBarMouseOverTarget)
        return;

      this.drawChartContents_();
    },

    scrollSelectedItemIntoViewIfNecessary: function() {

      if (this.selectedOpIndex === undefined)
        return;

      var width = this.offsetWidth;
      var left = this.scrollLeft;
      var right = left + width;
      var targetLeft = CHART_PADDING_LEFT +
          (BAR_WIDTH + BAR_PADDING) * this.selectedOpIndex;

      if (targetLeft > left && targetLeft < right)
        return;

      this.scrollLeft = (targetLeft - width * 0.5);
    },

    updateChartContents: function() {

      if (this.dimensionsHaveChanged)
        this.updateChartDimensions_();

      this.drawChartContents_();
    },

    updateChartDimensions_: function() {

      if (!this.pictureOps_)
        return;

      var width = CHART_PADDING_LEFT + CHART_PADDING_RIGHT +
          ((BAR_WIDTH + BAR_PADDING) * this.pictureOps_.length);

      if (width < this.offsetWidth)
        width = this.offsetWidth;

      // Allow the element to be its natural size as set by flexbox, then lock
      // the width in before we set the width of the canvas.
      this.chartWidth_ = width;
      this.chartHeight_ = this.getBoundingClientRect().height;

      // Scale up the canvas according to the devicePixelRatio, then reduce it
      // down again via CSS. Finally we apply a scale to the canvas so that
      // things are drawn at the correct size.
      this.chart_.width = this.chartWidth_ * this.chartScale_;
      this.chart_.height = this.chartHeight_ * this.chartScale_;

      this.chart_.style.width = this.chartWidth_ + 'px';
      this.chart_.style.height = this.chartHeight_ + 'px';

      this.chartCtx_.scale(this.chartScale_, this.chartScale_);

      this.dimensionsHaveChanged = false;
    },

    drawChartContents_: function() {

      this.clearChartContents_();

      if (this.pictureOps_ === undefined ||
          this.pictureOps_.length === 0 ||
          this.pictureOps_[0].cmd_time === undefined) {

        this.showNoTimingDataMessage_();
        return;
      }

      this.drawSelection_();
      this.drawBars_();
      this.drawChartAxes_();
      this.drawLinesAtTickMarks_();
      this.drawLineAtBottomOfChart_();

      if (this.currentBarMouseOverTarget_ === undefined)
        return;

      this.drawTooltip_();
    },

    drawSelection_: function() {

      if (this.selectedOpIndex === undefined)
        return;

      var width = (BAR_WIDTH + BAR_PADDING) * this.selectedOpIndex;
      this.chartCtx_.fillStyle = 'rgb(223, 235, 230)';
      this.chartCtx_.fillRect(CHART_PADDING_LEFT, CHART_PADDING_TOP,
          width, this.chartHeight_ - CHART_PADDING_TOP - CHART_PADDING_BOTTOM);
    },

    drawChartAxes_: function() {

      var min = this.opCosts_[0];
      var max = this.opCosts_[this.opCosts_.length - 1];
      var height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;

      var tickYInterval = height / (VERTICAL_TICKS - 1);
      var tickYPosition = 0;
      var tickValInterval = (max - min) / (VERTICAL_TICKS - 1);
      var tickVal = 0;

      this.chartCtx_.fillStyle = '#333';
      this.chartCtx_.strokeStyle = '#777';
      this.chartCtx_.save();

      // Translate half a pixel to avoid blurry lines.
      this.chartCtx_.translate(0.5, 0.5);

      // Sides.
      this.chartCtx_.beginPath();
      this.chartCtx_.moveTo(AXIS_PADDING_LEFT, AXIS_PADDING_TOP);
      this.chartCtx_.lineTo(AXIS_PADDING_LEFT, this.chartHeight_ -
          AXIS_PADDING_BOTTOM);
      this.chartCtx_.lineTo(this.chartWidth_ - AXIS_PADDING_RIGHT,
          this.chartHeight_ - AXIS_PADDING_BOTTOM);
      this.chartCtx_.stroke();
      this.chartCtx_.closePath();

      // Y-axis ticks.
      this.chartCtx_.translate(AXIS_PADDING_LEFT, AXIS_PADDING_TOP);

      this.chartCtx_.font = '10px Arial';
      this.chartCtx_.textAlign = 'right';
      this.chartCtx_.textBaseline = 'middle';

      this.chartCtx_.beginPath();
      for (var t = 0; t < VERTICAL_TICKS; t++) {

        tickYPosition = Math.round(t * tickYInterval);
        tickVal = (max - t * tickValInterval).toFixed(4);

        this.chartCtx_.moveTo(0, tickYPosition);
        this.chartCtx_.lineTo(-AXIS_TICK_SIZE, tickYPosition);
        this.chartCtx_.fillText(tickVal,
            -AXIS_TICK_SIZE - AXIS_LABEL_PADDING, tickYPosition);

      }

      this.chartCtx_.stroke();
      this.chartCtx_.closePath();

      this.chartCtx_.restore();
    },

    drawLinesAtTickMarks_: function() {

      var height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;
      var width = this.chartWidth_ - AXIS_PADDING_LEFT - AXIS_PADDING_RIGHT;
      var tickYInterval = height / (VERTICAL_TICKS - 1);
      var tickYPosition = 0;

      this.chartCtx_.save();

      this.chartCtx_.translate(AXIS_PADDING_LEFT + 0.5, AXIS_PADDING_TOP + 0.5);
      this.chartCtx_.beginPath();
      this.chartCtx_.strokeStyle = 'rgba(0,0,0,0.05)';

      for (var t = 0; t < VERTICAL_TICKS; t++) {
        tickYPosition = Math.round(t * tickYInterval);

        this.chartCtx_.moveTo(0, tickYPosition);
        this.chartCtx_.lineTo(width, tickYPosition);
        this.chartCtx_.stroke();
      }

      this.chartCtx_.restore();
      this.chartCtx_.closePath();
    },

    drawLineAtBottomOfChart_: function() {
      this.chartCtx_.strokeStyle = '#AAA';
      this.chartCtx_.beginPath();
      this.chartCtx_.moveTo(0, this.chartHeight_ - 0.5);
      this.chartCtx_.lineTo(this.chartWidth_, this.chartHeight_ - 0.5);
      this.chartCtx_.stroke();
      this.chartCtx_.closePath();
    },

    drawTooltip_: function() {

      var tooltipData = this.pictureOps_[this.currentBarMouseOverTarget_];
      var tooltipTitle = tooltipData.cmd_string;
      var tooltipTime = tooltipData.cmd_time.toFixed(4);
      var toolTipTimePercentage =
          ((tooltipData.cmd_time / this.totalOpCost_) * 100).toFixed(2);

      var tooltipWidth = 120;
      var tooltipHeight = 40;
      var chartInnerWidth = this.chartWidth_ - CHART_PADDING_RIGHT -
          CHART_PADDING_LEFT;
      var barWidth = BAR_WIDTH + BAR_PADDING;
      var tooltipOffset = Math.round((tooltipWidth - barWidth) * 0.5);

      var left = CHART_PADDING_LEFT + this.currentBarMouseOverTarget_ *
          barWidth - tooltipOffset;
      var top = Math.round((this.chartHeight_ - tooltipHeight) * 0.5);

      this.chartCtx_.save();

      this.chartCtx_.shadowOffsetX = 0;
      this.chartCtx_.shadowOffsetY = 5;
      this.chartCtx_.shadowBlur = 4;
      this.chartCtx_.shadowColor = 'rgba(0,0,0,0.4)';

      this.chartCtx_.strokeStyle = '#888';
      this.chartCtx_.fillStyle = '#EEE';
      this.chartCtx_.fillRect(left, top, tooltipWidth, tooltipHeight);

      this.chartCtx_.shadowColor = 'transparent';
      this.chartCtx_.translate(0.5, 0.5);
      this.chartCtx_.strokeRect(left, top, tooltipWidth, tooltipHeight);

      this.chartCtx_.restore();

      this.chartCtx_.fillStyle = '#222';
      this.chartCtx_.textAlign = 'left';
      this.chartCtx_.textBaseline = 'top';
      this.chartCtx_.font = '800 12px Arial';
      this.chartCtx_.fillText(tooltipTitle, left + 8, top + 8);

      this.chartCtx_.fillStyle = '#555';
      this.chartCtx_.font = '400 italic 10px Arial';
      this.chartCtx_.fillText(tooltipTime + 'ms (' +
          toolTipTimePercentage + '%)', left + 8, top + 22);
    },

    drawBars_: function() {

      var op;
      var opColor = 0;
      var opHeight = 0;
      var opWidth = BAR_WIDTH + BAR_PADDING;
      var opHover = false;

      var bottom = this.chartHeight_ - CHART_PADDING_BOTTOM;
      var maxHeight = this.chartHeight_ - CHART_PADDING_BOTTOM -
          CHART_PADDING_TOP;

      var maxValue;
      if (this.usePercentileScale)
        maxValue = this.ninetyFifthPercentileCost_;
      else
        maxValue = this.maxCost_;

      for (var b = 0; b < this.pictureOps_.length; b++) {

        op = this.pictureOps_[b];
        opHeight = Math.round(
            (op.cmd_time / maxValue) * maxHeight);
        opHeight = Math.max(opHeight, 1);
        opHover = (b === this.currentBarMouseOverTarget_);
        opColor = this.getOpColor_(op.cmd_string, opHover);

        if (b === this.selectedOpIndex)
          this.chartCtx_.fillStyle = '#FFFF00';
        else
          this.chartCtx_.fillStyle = opColor;

        this.chartCtx_.fillRect(CHART_PADDING_LEFT + b * opWidth,
            bottom - opHeight, BAR_WIDTH, opHeight);
      }

    },

    getOpColor_: function(opName, hover) {

      var characters = opName.split('');

      var hue = characters.reduce(this.reduceNameToHue, 0) % 360;
      var saturation = 30;
      var lightness = hover ? '75%' : '50%';

      return 'hsl(' + hue + ', ' + saturation + '%, ' + lightness + '%)';
    },

    reduceNameToHue: function(previousValue, currentValue, index, array) {
      // Get the char code and apply a magic adjustment value so we get
      // pretty colors from around the rainbow.
      return Math.round(previousValue + currentValue.charCodeAt(0) *
          HUE_CHAR_CODE_ADJUSTMENT);
    },

    clearChartContents_: function() {
      this.chartCtx_.clearRect(0, 0, this.chartWidth_, this.chartHeight_);
    },

    showNoTimingDataMessage_: function() {
      this.chartCtx_.font = '800 italic 14px Arial';
      this.chartCtx_.fillStyle = '#333';
      this.chartCtx_.textAlign = 'center';
      this.chartCtx_.textBaseline = 'middle';
      this.chartCtx_.fillText('No timing data available.',
          this.chartWidth_ * 0.5, this.chartHeight_ * 0.5);
    }
  };

  return {
    PictureOpsChartView: PictureOpsChartView
  };
});
</script>
