<!DOCTYPE html>
<!--
Copyright 2016 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.
-->
<!--
The chart-container element represents one chart and all related functionality,
including a legend listing different traces that can be plotted on the same
chart, a revision range selecting mini-chart at the bottom, and all of the alert
triaging functionality in the chart.
-->

<link rel="import" href="/components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="/components/iron-icon/iron-icon.html">
<link rel="import" href="/components/paper-button/paper-button.html">

<link rel="import" href="/dashboard/elements/alert-icon.html">
<link rel="import" href="/dashboard/elements/chart-legend.html">
<link rel="import" href="/dashboard/elements/chart-slider.html">
<link rel="import" href="/dashboard/elements/chart-title.html">
<link rel="import" href="/dashboard/elements/chart-tooltip.html">
<link rel="import" href="/dashboard/static/graph.html">
<link rel="import" href="/dashboard/static/simple_xhr.html">
<link rel="import" href="/dashboard/static/testselection.html">
<link rel="import" href="/dashboard/static/uri.html">

<dom-module name="chart-container">

  <template>
    <style include="iron-flex iron-flex-alignment iron-flex-factors">
    #container {
      width: 100%;
      display: flex;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
      align-items: center;
      -webkit-align-items: center;
      position: relative;
      min-width: 845px;  /* Minimum width of plot plus width of chart-legend. */
    }

    #container[compact] {
      min-width: 670px;  /* Minimum width of plot plus width of compacted chart-legend. */
    }

    #horizontal {
      display: flex;
      display: -webkit-flex;
      width: 100%;
      position: relative;
    }

    #chart-yaxis-label {
      transform: rotate(-90deg) translate(-50%);
      -webkit-transform: rotate(-90deg) translate(-50%);
      transform-origin: 0 0;
      -webkit-transform-origin: 0 0;
      top: 50%;
      position: absolute;
      padding-top: 5px;
      background-color: white;
      z-index: 1000;
    }

    #plots-container {
      -webkit-flex-grow: 1;
      flex-grow: 1;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
    }

    #plot {
      -webkit-flex-grow: 1;
      flex-grow: 1;
      height: 240px;
      min-width: 500px;
    }

    #slider {
      width: 100%;
      height: 60px;
    }

    #warning {
      position: absolute;
      left: 80px;
      top: 15px;
      z-index: 2000;
      font-size: 16px;
      font-weight: bold;
      color: #dd4b39;
    }

    #original {
      position: absolute;
      top: 10px;
      margin-left: -15px;
    }

    #loading-div {
      position: relative;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: flex;
      display: -webkit-flex;
      align-items: center;
      -webkit-align-items: center;
      justify-content: center;
      -webkit-justify-content: center;
    }

    #alert-icon-container {
      width: 0px;
      height: 0px;
      left: 0px;
      top: 0px;
      position: relative;
    }

    alert-icon {
      position: absolute;
      margin-top: -5px;
      margin-left: -6px;
      z-index: 1000;
    }

    #close-chart {
      color: #e91e63;
    }

    #close-chart > iron-icon {
      margin-right: 4px;
    }

    #top-bar {
      width: 100%;
    }
    </style>

    <div id="container" compact$="{{showCompact}}">
      <div id="top-bar" class="layout horizontal">
        <div class="layout horizontal center-justified flex">
          <chart-title id="title" series-group-list="{{seriesGroupList}}"
                       test-suites="{{testSuites}}"></chart-title>
        </div>
        <div class="layout horizontal center">
          <paper-button id="close-chart" on-click="closeChartClicked">
            Close
          </paper-button>
        </div>
      </div>
      <div id="horizontal">
        <div id="chart-yaxis-container">
          <div id="chart-yaxis-label">{{chartYAxisLabel}}</div>
        </div>
        <div id="alert-icon-container"></div>
        <chart-tooltip id="tooltip"
                       xsrf-token="{{xsrfToken}}"></chart-tooltip>

        <div id="plots-container" on-mouseleave="onMouseLeave">
          <div id="plot">
            <div id="loading-div">
              <img src="//www.google.com/images/loading.gif">
            </div>
          </div>
          <chart-slider id="slider" on-revisionrange="onRevisionRange"></chart-slider>
        </div>

        <div id="warning">
          <template is="dom-repeat" items="{{warnings}}">
            <span>{{item}}</span><br>
          </template>
        </div>

        <a hidden id="original"
           on-click="onViewOriginal"
           href="javascript:void(0);">View original graph</a>

        <chart-legend id="legend"
                      series-group-list="{{seriesGroupList}}"
                      indices-to-graph="{{indicesToGraph}}"
                      collapse-legend="{{collapseLegend}}"
                      on-dragstart="legendSeriesDragStart"
                      on-dragend="legendSeriesDragEnd"
                      delta-absolute="{{deltaAbsolute}}"
                      delta-percent="{{deltaPercent}}"
                      show-delta="{{showDelta}}">
      </div>

    </div>
  </template>
  <script>
    'use strict';
    (function() {

      // Minimum multiple standard deviation for a value to be considered
      // an outlier.
      var MULTIPLE_OF_STD_DEV = 5;

      // Regex for links in series annotation which are shown in tooltip.
      var TOOLTIP_LINK_REGEX = /\[(.+?)\]\((.+?)\)/g;

      /**
       * Gets the mean for list of numbers.
       *
       * @return {number} A number.
       */
      function calculateMean(values) {
        var len = values.length;
        var sum = values.reduce(function(v1, v2) { return v1 + v2;}, 0);
        return sum / len;
        var squaredDevianceSum = values.reduce(
            function(v1, v2) {return v1 + Math.pow(v2 - mean, 2);}, 0);
        var variance = squaredDevianceSum / len;
        var std = Math.sqrt(variance);
        return {mean: mean, std: std};
      }

      /**
       * Gets standard deviation for list of numbers and a mean.
       *
       * @return {number} A number.
       */
      function calculateStdDev(values, mean) {
        var squaredDevianceSum = values.reduce(
            function(v1, v2) {return v1 + Math.pow(v2 - mean, 2);}, 0);
        var variance = squaredDevianceSum / values.length;
        return Math.sqrt(variance);
      }

      /**
       * Finds outliers in a series, along with their directions.
       *
       * An outlier is defined as a value that deviates from the mean by over
       * MULTIPLE_OF_STD_DEV times the standard deviation. An outlier direction
       * is either 1 for positive, -1 for negative and 0 for non-outlier.
       *
       * Example:
       * Input values: [50, 50, 50, 100, 50, 10, 50, 50, 50]
       * Output directions: [0, 0, 0, 1, 0, -1, 0, 0, 0]
       *
       * @param {Array.<number>} values List of numbers.
       * @return {Array.<number>} List of outlier directions.
       */
      function getOutlierDirections(values) {
        var mean = calculateMean(values);
        var stddev = calculateStdDev(values, mean);
        var outlierDirections = [];
        for (var i = 0; i < values.length; i++) {
          var direction = 0;
          var value = values[i];
          var multDevFromMean = Math.abs(value - mean) / stddev;
          if (multDevFromMean > MULTIPLE_OF_STD_DEV) {
            if (value >= mean) {
              direction = 1;
            }
            direction = -1;
          }
          outlierDirections.push(direction);
        }
        return outlierDirections;
      }

      /**
       * Returns a date corresponding to the given timestamp, or null.
       * @param {string} rev A string that may contain a timestamp.
       * @return {?Date} A date object if a timestamp was given, or
       *     null.
       */
      function getDateDisplay(rev) {
        var timestampSecondsRegex = /^[\d]{10}$/;
        var timestampMillisecondsRegex = /^[\d]{13}$/;
        var d = null;
        if (timestampSecondsRegex.test(rev)) {
          d = new Date(rev * 1000);
        } else if (timestampMillisecondsRegex.test(rev)) {
          d = new Date(rev);
        }
        if (d) {
          return d.toLocaleString();
        }
        return null;
      };

      /**
       * Returns a string to display, given a string that contains a
       * revision. This will be different depending on whether the given
       * revision is a git hash, a timestamp, or other.
       * Note: this is similar to the getDisplayRevision function for the
       * embed page (defined in static/embed.js)
       * @param {string|boolean} rev A string containing a "revision".
       *     False may also be passed, in which case it doesn't matter what
       * @return {string} A string to display for the given revision.
       */
      function getDisplayRevision(rev) {
        // Truncate git sha1 to 7 chars.
        var gitRegex = /^[a-f0-9]{40}$/;
        if (gitRegex.test(rev)) {
          return rev.substring(0, 7);
        }
        var d = getDateDisplay(rev);
        if (d) {
          return d;
        }
        return rev;
      };

      /**
       * Formats numbers in a human-readable way.
       * @param {number|string} val A number or string.
       * @return {string} A string.
       */
      function formatNumber(val) {
        var num = Number(val);
        var options = {
          minimumSignificantDigits: 2,
          maximumSignificantDigits: 6
        };
        return num.toLocaleString('en-US', options);
      };

      /**
       * Deep compares two dictionary parameters.
       * This function converts dictionary parameters to sorted list of pairs
       * of key and values and compares their JSON string.
       * @param {Object} param1 An object.
       * @param {Object} param2 An object.
       * @return {boolean} True if equal, otherwise false.
       */
      function graphParamEquals(param1, param2) {
        if (!param1 || !param2) {
          return param1 == param2;
        }
        param1 = Object.keys(param1).sort().map(function(k) {
          return [k, param1[k]];
        });
        param2 = Object.keys(param2).sort().map(function(k) {
          return [k, param2[k]];
        });
        return JSON.stringify(param1) == JSON.stringify(param2);
      };

      function arrayUnique(array) {
        var dict = {};
        array.forEach(function(item) {
          dict[item] = true;
        });
        return Object.keys(dict);
      };

      Polymer({

        is: 'chart-container',
        properties: {
          SERIES_SELECTION_OPTIONS: {
            type: Array,
            value: () => ['important', 'all', 'none']
          },

          // Default values for reverting series highlighting.
          DEFAULT_SERIES_PROPERTIES: {
            type: Object,
            value: () => ({
              lineWidth: 2,
              opacity: 1,
              fill: 0.2,
              shadowSize: 3
            })
          },

          DEFAULT_JSON_PROPERTIES: {
            type: Object,
            value: () => ({
              annotations: {
                series: {}
              },
              data: {},
              error_bars: {},
              warning: null
            })
          },

          // Amount of time before a warning is shown for tests with no new
          // data.
          STALE_DATA_DELTA_MS: {
            type: Number,
            value: 7 * 86400000
          },

          alertKey: { notify: true },
          collapseLegend: {
            type: Boolean,
            value: false,
            notify: true,
            observer: 'collapseLegendChanged'
          },
          indicesToGraph: {
            type: Array,
            value: () => [],
          },
          // TODO(chrisphan): Make seriesGroupList a class.
          // A list of series group dictionary. A series group contains test
          // path and list of test information. This is displayed in
          // chart-legend, where each test is a checkable series.
          // seriesGroupList has the form:
          //   [{
          //         'path': 'ChromiumPerf/linux/dromaeo/Total',
          //         'tests': [{
          //              name: 'Total',
          //              direction: 'Lower is better',
          //              units: 'm/s',
          //              description: 'Total time',
          //              etc.
          //         }]
          //   }]
          seriesGroupList: {
            notify: true,
            type: Array,
            value: () => [],
          },

          // Data series index of the point that was most recently clicked.
          currentItem: {
            value: null
          },

          // Meta-data about tests, which will be displayed in the legend.
          legendTests: {
            type: Array,
            value: () => []
          },

          // Text to display next to the y-axis.
          chartYAxisLabel: {
            value: '',
            type: String
          },

          // Y-axis delta of current zoom selection, as an absolute number
          // and as a percentage of the original selection.
          deltaAbsolute: {
            value: 0,
            type: Number
          },
          deltaPercent: {
            value: 0,
            type: Number
          },

          // Information about the last selection range.
          lastSelectedDelta: { value: null },

          // Whether or not the user is currently selecting a range.
          selecting: {
            type: Boolean,
            value: false
          },

          // Y-axis start value in the last selection range.
          firstSelectedValue: {
            type: Number,
            value: 0
          },

          // Whether or not the tooltip is "sticky". Sticky means that it will
          // stay visible when the user is no longer hovering over the point.
          stickyTooltip: {
            type: Boolean,
            value: false
          },

          // Map of series indexes to arrays with revision information.
          revisionMap: {
            type: Object,
            value: null
          },

          // Whether or not the chart can currently be drawn.
          drawable: {
            type: Boolean,
            value: false
          },

          // The Flot Plot object, returned by $.plot.
          chart: {
            value: null
          },

          // Timeout ID of the timer used by this.resizeHandler.
          resizeTimer: { value: null },

          // Maintain the next series index as new graph json comes in.
          nextSeriesIndex: { value: null },

          // Whether this chart-container allows a series group to be dropped
          // on-to it.
          droppable: {
            type: Boolean,
            value: true
          },

          // Whether to show delta in chart-legend.
          showDelta: {
            type: Boolean,
            value: false
          },

          // Chart options to be given when initializing the Flot chart.
          // See: https://github.com/flot/flot/blob/master/API.md#plot-options
          chartOptions: {
            type: Object,
            value: () => ({
              grid: {
                hoverable: true,
                clickable: true,
                borderWidth: 1,
                borderColor: 'rgba(0, 0, 0, 0.5)'
              },
              crosshair: {
                mode: 'xy',
                color: 'rgba(34, 34, 34, 0.3)',
                lineWidth: 0.3
              },
              xaxis: {},
              yaxis: {
                labelWidth: 60
              },
              selection: {
                mode: 'y'
              }
            })
          },

          // Warning text to be shown over the chart, if any.
          warnings: {
            type: Array,
            value: () => [],
            observer: 'warningsChanged'
          },

          graphParams: {
            type: Object,
            value: () => ({})
          },

          // List of XMLHttpRequests sent for graph json.
          graphJsonRequests: {
            type: Array,
            value: () => []
          },

          isInternalUser: { notify: true },
          onUri: { observer: 'onUriChanged' },
          revisionInfo: { notify: true },
          showCompact: { notify: true },
          testSuites: { notify: true },
          xsrfToken: { notify: true }
        },
        observers: [
          'indicesToGraphChanged(indicesToGraph.splices)'
        ],

        /**
         * Initializes the chart-container element and all of its properties.
         *
         * This is a custom element lifecycle callback that's called when an
         * instance of the element is ready.
         * http://www.polymer-project.org/polymer.html#lifecyclemethods
         *
         * We use 'ready' instead of 'created' to know when the element has its
         * bindings, Shadow DOM has been created, and its on-* handlers and
         * property observers have been set up.
         * See https://github.com/Polymer/polymer/releases/tag/v0.0.20131025
         */
        ready: function() {

          // Handler for the 'resize' event.
          this.resizeHandler = this.onResize.bind(this);

          // The data fetched from the graph_json handler for this chart.
          this.json = deepCopy(this.DEFAULT_JSON_PROPERTIES);

          this.chartOptions.xaxis.tickFormatter = this.formatXAxis.bind(this);
          this.chartOptions.yaxis.tickFormatter = this.formatYAxis.bind(this);

          this.$.legend.addEventListener(
              'seriesmouseover', this.seriesMouseover.bind(this), true);
          this.$.legend.addEventListener(
              'seriesmouseout', this.seriesMouseout.bind(this), true);

          this.$.tooltip.addEventListener(
              'triaged', this.onBugTriaged.bind(this), true);
          this.$.tooltip.addEventListener(
              'alertChangedRevisions', this.onAlertChangedRevisions.bind(this),
              true);

          this.$.legend.addEventListener(
              'seriesgroupclosed', this.onSeriesGroupClosed.bind(this), true);

          this.$.title.addEventListener(
              'titleclicked', this.onTitleClicked.bind(this), true);

          window.addEventListener('resize', this.resizeHandler);

          this.initializePlotEventListeners();

          window.addEventListener('urichange', this.onUriChanged.bind(this));
        },

        /**
         * Binds event handlers for events that are fired by Flot.
         */
        initializePlotEventListeners: function() {
          var plot = $(this.$.plot);
          plot.bind('plotselected', this.onPlotSelected.bind(this));
          plot.bind('plotselecting', this.onPlotSelecting.bind(this));
          plot.bind('plotunselected', this.onPlotUnselected.bind(this));
          plot.bind('plotclick', this.onPlotClick.bind(this));
          plot.bind('plothover', this.onPlotHover.bind(this));
        },

        /**
         * Adds series group to graph.
         *
         * If test path already exist, it will be ignored.
         *
         * @param {Array.<Array>} testPathAndSelected A list of
         *     pair of test path and a list of selected series.
         * @return {boolean} collapse Whether unchecked and unimportant
         *     series should start off hidden.
         */
        addSeriesGroup: function(testPathAndSelected, collapse) {
          // Checks if test path already exists.
          var testPathSet = {};
          this.seriesGroupList.forEach(function(group) {
            testPathSet[group.path] = true;
          });

          testPathAndSelected = testPathAndSelected.filter(function(value) {
            return !(value[0] in testPathSet);
          });
          if (testPathAndSelected.length == 0) {
            return;
          }

          // We want to send two requests, one for selected and unselected
          // series, so there would be a quicker response for the selected
          // series. But, if the selected series is unknown, we default to
          // send an unselected series.
          var selectedTestPathDict = {};
          var unSelectedTestPathDict = {};
          for (var i = 0; i < testPathAndSelected.length; i++) {
            var testPath = testPathAndSelected[i][0];
            var selectedTraces = testPathAndSelected[i][1];
            selectedTraces = arrayUnique(selectedTraces);
            var seriesGroup = {
              path: testPath,
              tests: [],
              collapse: collapse,
              numPendingRequests: 0
            };
            if (selectedTraces.length > 0) {
              var selected = selectedTraces[0];
              if (this.SERIES_SELECTION_OPTIONS.indexOf(selected) != -1) {
                seriesGroup.selection = selectedTraces[0];
                selectedTestPathDict[testPath] = [];
              } else {
                // Create test data here for selected traces so they can
                // be initially shown in chart legend.
                for (var j = 0; j < selectedTraces.length; j++) {
                  var testData = {
                    name: selectedTraces[j],
                    selected: true
                  };
                  seriesGroup.tests.push(testData);
                }
                selectedTestPathDict[testPath] = selectedTraces;
                unSelectedTestPathDict[testPath] = selectedTraces;
              }
            } else {
              unSelectedTestPathDict[testPath] = [];
            }
            this.push('seriesGroupList', seriesGroup);
          }
          if (Object.keys(selectedTestPathDict).length > 0) {
            this.sendGraphJsonRequest(selectedTestPathDict, true);
          }
          if (Object.keys(unSelectedTestPathDict).length > 0) {
            this.sendGraphJsonRequest(unSelectedTestPathDict, false);
          }
          this.updateSlider();
          this.$.title.update();
        },

        /**
         * Sends a request for graph JSON.
         *
         * @param {Object} testPathDict Dictionary of test path to list of
         *     selected series.
         * @return {boolean} isSelected Whether this request is for selected
         *     or unselected series.
         */
        sendGraphJsonRequest: function(testPathDict, isSelected) {
          var params = JSON.parse(JSON.stringify(this.graphParams));
          params['test_path_dict'] = testPathDict;
          if (isSelected) {
            params['is_selected'] = true;
          }

          this.updateSeriesGroupLoadingCounter(
              Object.keys(testPathDict), true);

          var req = simple_xhr.send(
              '/graph_json',
              {'graphs': JSON.stringify(params)},
              function(json) {
                if (this.jsonHasData(json)) {
                  this.updateJson(json, isSelected);
                } else if (isSelected) {
                  this.addWarnings('No data available.');
                  this.checkForInternalUser();
                  this.updateChart();
                }

                this.updateSeriesGroupLoadingCounter(
                    Object.keys(testPathDict), false);
                this.$['loading-div'].style.display = 'none';
              }.bind(this),
              function(error) {
                if (error) {
                  this.addWarnings('Failed to fetch graph data.');
                  this.checkForInternalUser();
                  console.warn(error);
                }
                this.updateSeriesGroupLoadingCounter(
                    Object.keys(testPathDict), false);
                this.$['loading-div'].style.display = 'none';
              }.bind(this)
          );
          this.graphJsonRequests.push(req);
        },

        jsonHasData: function(json) {
          if (!'data' in json) {
            return;
          }
          var seriesIndices = Object.keys(json.data);
          return (seriesIndices.length > 0 &&
                  json.data[seriesIndices[0]]['data'].length > 0);
        },

        /**
         * Update loading counter for all series groups in a testPaths.
         *
         * @param {Array} testPaths List of test paths.
         * @param {boolean} increment True to add one, False to subtract one.
         */
        updateSeriesGroupLoadingCounter: function(testPaths, increment) {
          var testPathToGroupIndex = {};
          for (var i = 0; i < this.seriesGroupList.length; i++) {
            testPathToGroupIndex[this.seriesGroupList[i].path] = i;
          }

          var delta = (increment) ? 1 : -1;
          testPaths.forEach(function(testPath) {
            var index = testPathToGroupIndex[testPath];
            this.set('seriesGroupList.' + index + '.numPendingRequests',
                     this.seriesGroupList[index].numPendingRequests + delta);
          }.bind(this));
        },

        checkForInternalUser: function() {
          if (!this.isInternalUser) {
             this.addWarnings(
               'Note that some data is only available when logged in.');
          }
        },

        /**
         * Adds a warning message if it doesn't exist.
         */
        addWarnings: function(warning) {
          for (var i = 0; i < this.warnings.length; i++) {
            if (this.warnings[i].indexOf(warning) == 0) {
              return;
            }
          }
          this.warnings.push(warning);
        },

        /**
         * Adds warnings for selected series that are stale or have no data.
         */
        updateWarningsForSelectedSeries: function() {
          this.warnings = this.warnings.filter(function(value) {
            return (value.indexOf('Graph out of date!') == -1 &&
                    value.indexOf('No data available.') == -1);
          });

          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            var series = this.json.annotations[index];
            if (!series) {
              this.warnings.push('No data available.');
            }
          }

          var hasRevParams = ('rev' in this.graphParams ||
                              'start_rev' in this.graphParams ||
                              'end_rev' in this.graphParams);
          if (hasRevParams) {
            return;
          }
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            var timestamp = this.getSeriesLatestTimestamp(index);
            if (timestamp != null) {
              var currentTime = new Date().getTime();
              if (timestamp < currentTime - this.STALE_DATA_DELTA_MS) {
                this.warnings.push('Graph out of date! Last data received: ' +
                                   new Date(timestamp).toISOString());
                break;
              }
            }
          }
        },

        getSeriesLatestTimestamp: function(seriesIndex) {
          var series = this.json.annotations[seriesIndex];
          if (series) {
            var lastIndex = Math.max.apply(Math, Object.keys(series));
            if ('timestamp' in series[lastIndex]) {
              return series[lastIndex]['timestamp'];
            }
          }
          return null;
        },

        /**
         * Updates graph data for newJson.
         *
         * Merge newJson with this.json and update this.seriesGroupList.
         *
         * @param {Object} newJson JSON data from /graph_json request.
         * @param {boolean} isSelected Whether this should be selected or
         *     unselected set of series.
         */
        updateJson: function(newJson, isSelected) {
          if (!this.nextSeriesIndex) {
            this.nextSeriesIndex = Object.keys(this.json.data).length;
          }

          var testPathToSeriesIndex = {};
          var series = this.json.annotations.series;
          for (var i in series) {
            testPathToSeriesIndex[series[i].path] = parseInt(i);
          }

          var newSeries = {};
          for (var index in newJson.data) {
            var testPath = newJson.annotations.series[index].path;
            var nextIndex = null;
            if (testPath in testPathToSeriesIndex) {
              nextIndex = testPathToSeriesIndex[testPath];
            } else {
              nextIndex = this.nextSeriesIndex;
              this.nextSeriesIndex++;
            }

            var color = graph.stringToColor(testPath);
            newJson.data[index].color = color;
            this.updateJsonDataIndex(newJson.data[index], nextIndex);
            this.json.data[nextIndex] = newJson.data[index];

            // Flot's getData() method can return the data series out of order,
            // so maintain an index so that we can get back to the original
            // data series on click and hover events.
            this.json.data[nextIndex].index = nextIndex;

            this.json.annotations.series[nextIndex] =
                newJson.annotations.series[index];
            this.json.annotations[nextIndex] = newJson.annotations[index];
            newSeries[nextIndex] = newJson.annotations.series[index];

            this.updateErrorBarsIndex(newJson['error_bars'][index], nextIndex,
                                      color);
            this.json['error_bars'][nextIndex] = newJson['error_bars'][index];
          }

          this.updateForNewSeries(newSeries, isSelected);
        },

        /**
         * Updates chart for new list of series.
         *
         * @param {Array} series A list of series data.
         * @param {boolean} isSelected Whether this should be selected or
         *     unselected set of series.
         */
        updateForNewSeries: function(series, isSelected) {
          if (!this.drawable) {
            // Cache the new series until the chart is drawable.
            this.newDrawableSeries = this.newDrawableSeries || [];
            this.newDrawableSeries.push([series, isSelected]);
            return;
          }

          this.$['loading-div'].style.display = 'none';

          if (Object.keys(series).length == 0) {
            return;
          }

          var testList = [];
          for (var i in series) {
            i = parseInt(i);
            var test = {
              name: series[i].name,
              path: series[i].path,
              direction: series[i].better,
              units: series[i].units,
              description: series[i].description,
              color: this.json.data[i].color,
              index: i,
              important: testselection.isImportant(
                  series[i].path.split('/').slice(2).join('/'),
                  this.testSuites)
            };

            testList.push(test);
          }

          this.updateSeriesGroupList(testList);
          this.updateSlider();
          this.updateYAxisLabel();
          this.updateSmartAutoscaleMap();

          if (isSelected) {
            this.updateIndicesToGraph();
          }
        },

        /**
         * Updates this.seriesGroupList for a list of series object.
         *
         * @param {Array} testList List of test object.
         */
        updateSeriesGroupList: function(testList) {
          var testPathToGroupIndex = {};
          for (var i = 0; i < this.seriesGroupList.length; i++) {
            testPathToGroupIndex[this.seriesGroupList[i].path] = i;
          }

          for (var i = 0; i < testList.length; i++) {
            var test = testList[i];
            var seriesGroupIndex = null;
            if (test.path in testPathToGroupIndex) {
              seriesGroupIndex = testPathToGroupIndex[test.path];
            } else {
              var parentPath = test.path.substring(0,
                  test.path.lastIndexOf('/'));
              if (parentPath in testPathToGroupIndex) {
                seriesGroupIndex = testPathToGroupIndex[parentPath];
              }
            }
            if (seriesGroupIndex != null) {
              this.updateSeriesGroup(seriesGroupIndex, test);
            }
          }
        },

        /**
         * Updates a given test in seriesGroup or adds test if not found.
         *
         * At the time that this function is called, tests in a series
         * group are either partially created or not yet added. This
         * function replaces the existing test in its series group
         * with passed |test|, or inserts if it doesn't exist.
         *
         * @param {Number} seriesGroupIndex An index in the series group object.
         * @param {Object} newTest Contains information about a series
         * displayed in chart-legend.
         */
        updateSeriesGroup: function(seriesGroupIndex, newTest) {
          // Update series if its data has not been loaded.
          var testIndex = this.getTestIndexInSeriesGroup(
              seriesGroupIndex, newTest.name);
          if (testIndex != null) {
            for (var key in newTest) {
              this.set('seriesGroupList.' + seriesGroupIndex + '.tests.' +
                       testIndex + '.' + key,
                       newTest[key]);
            }
          } else {
            this.addTestToSeriesGroup(seriesGroupIndex, newTest);
            testIndex = this.getTestIndexInSeriesGroup(
                seriesGroupIndex, newTest.name);
          }

          if (this.seriesGroupList[seriesGroupIndex].selection == 'all' ||
              this.seriesGroupList[seriesGroupIndex].selection == 'important' &&
              newTest.important) {
            this.set('seriesGroupList.' + seriesGroupIndex + '.tests.' +
                     testIndex + '.selected', true);
          }
        },

        /**
         * Adds a test to seriesGroup and determines if it should be hidden.
         */
        addTestToSeriesGroup: function(seriesGroupIndex, test) {
          var seriesGroup = this.seriesGroupList[seriesGroupIndex];
          if (seriesGroup.collapse && !test.selected && !test.important) {
            test.hidden = true;
            if (seriesGroup.numHidden == undefined) {
              this.set('seriesGroupList.' + seriesGroupIndex + '.numHidden', 0);
            }
            this.set('seriesGroupList.' + seriesGroupIndex + '.numHidden',
                     seriesGroup.numHidden + 1);
          }
          this.push('seriesGroupList.' + seriesGroupIndex + '.tests', test);
          this.set('seriesGroupList.' + seriesGroupIndex + '.tests',
                   seriesGroup.tests.sort(this.compareTest));
        },

        getTestIndexInSeriesGroup: function(seriesGroupIndex, name) {
          var tests = this.seriesGroupList[seriesGroupIndex].tests;
          for (var i = 0; i < tests.length; i++) {
            if (name == tests[i].name) {
              return i;
            }
          }
          return null;
        },

        /**
         * Reloads chart with current graph parameters and seriesGroupList.
         *
         * This is called on graph revision range changed.
         */
        reloadChart: function() {
          this.graphJsonRequests.forEach(function(request) {
            request.abort();
          });
          this.hideTooltipEvenIfSticky();
          this.clearAlertIcons();
          this.$['loading-div'].style.display = '';
          this.set('indicesToGraph', []);
          this.json.warnings = [];
          this.warnings = [];

          // Create params out of seriesGroupList to make /graph_json request.
          var selectedTestPathDict = {};
          var unSelectedTestPathDict = {};
          for (var i = 0; i < this.seriesGroupList.length; i++) {
            var testPath = this.seriesGroupList[i].path;
            var tests = this.seriesGroupList[i].tests;
            var selectedTraces = [];
            for (var j = 0; j < tests.length; j++) {
              var test = tests[j];
              if (test.selected) {
                selectedTraces.push(test.name);
              } else {
                // Disable unselected series in chart-legend during loading.
                test.index = undefined;
              }
            }
            if (selectedTraces.length > 0) {
              selectedTestPathDict[testPath] = selectedTraces;
              unSelectedTestPathDict[testPath] = selectedTraces;
            } else {
              unSelectedTestPathDict[testPath] = [];
            }
          }

          if (Object.keys(selectedTestPathDict).length > 0) {
            this.sendGraphJsonRequest(selectedTestPathDict, true);
          }
          if (Object.keys(unSelectedTestPathDict).length > 0) {
            this.sendGraphJsonRequest(unSelectedTestPathDict, false);
          }
        },

        updateJsonDataIndex: function(jsonData, index) {
          jsonData.index = 'line_' + index;
          jsonData.id = 'line_' + index;
        },

        updateErrorBarsIndex: function(errorBarsData, index, color) {
          var top = errorBarsData[0];
          var bottom = errorBarsData[1];
          top.id = 'top_' + index;
          top.fillBetween = 'line_' + index;
          top.color = color;
          bottom.fillBetween = 'bottom_' + index;
          bottom.fillBetween = 'line_' + index;
          bottom.color = color;
        },

        /**
         * Updates the list of indices of traces to plot with seriesGroupList.
         */
        updateIndicesToGraph: function() {
          this.set('indicesToGraph', []);
          for (var i = 0; i < this.seriesGroupList.length; i++) {
            var tests = this.seriesGroupList[i].tests;
            for (var j = 0; j < tests.length; j++) {
              if (tests[j].selected && tests[j].index != undefined) {
                this.push('indicesToGraph', tests[j].index);
              }
            }
          }
        },

        /**
         * Sorts by tests by important and then by name.
         */
        compareTest: function(testA, testB) {
          if (testA.important && !testB.important) {
            return -1;
          }
          if (testB.important && !testA.important) {
            return 1;
          }
          if (testA.name > testB.name) {
            return 1;
          }
          if (testA.name < testB.name) {
            return -1;
          }
          return 0;
        },

        updateSlider: function() {
          if (this.seriesGroupList.length == 0 ||
              this.seriesGroupList[0].tests.length == 0) {
            return;
          }
          var firstTestPath = this.seriesGroupList[0].tests[0].path;
          if (firstTestPath && firstTestPath != this.$.slider.testpath) {
            this.$.slider.testpath = firstTestPath;
          }
        },

        /**
         * A custom element lifecycle callback, called when an instance of the
         * element is removed from the DOM.
         * See: http://www.polymer-project.org/polymer.html#lifecyclemethods
         */
        detached: function() {
          this.drawable = false;
          window.removeEventListener('resize', this.resizeHandler);
        },

        attached: function() {
          this.drawable = true;
          // This likely only happens in the unit test, but if series have
          // been added before the element became drawable, update now.
          if (this.newDrawableSeries) {
            for (var drawableSeries of this.newDrawableSeries) {
              this.updateForNewSeries(drawableSeries[0], drawableSeries[1]);
            }
          }
        },

        /**
         * Handler for the click event of X button on the top-right corner.
         */
        closeChartClicked: function() {
          Polymer.dom(Polymer.dom(this).parentNode).removeChild(this);
          this.fire('chartclosed', {
            target: this,
            stateName: 'chartclosed',
            params: {
              seriesGroupList: this.seriesGroupList
            }
          });
        },

        /**
         * Handler for 'revisionrange' event, fired when revision range
         * changes.
         *
         * This event is fired by the chart-revision-range element. When this
         * event is fired, it indicates that a new start and end revision have
         * been selected.
         *
         * @param {Event} event The revisionrange event.
         * @param {Object} detail The detail object given when firing the
         *     event. This is set in graph.js and it contains 'start_rev' and
         *     'end_rev'.
         */
        onRevisionRange: function(event, detail) {
          var newGraphParams = deepCopy(this.graphParams);
          newGraphParams['rev'] = null;
          newGraphParams['num_points'] = null;
          newGraphParams['start_rev'] = detail.start_rev;
          newGraphParams['end_rev'] = detail.end_rev;
          this.graphParams = newGraphParams;
          this.reloadChart();
          this.fireChartStateChangedEvent(null);
        },

        /**
         * Sets the Y-axis label based on the units of the data.
         */
        updateYAxisLabel: function() {
          // If the series annotations are properly populated, then there will
          // be at least one entry and it will have the properties 'units' and
          // 'better'. All traces in one chart should have the same units.
          var series = this.json.annotations.series;
          var seriesIndices = Object.keys(series);
          if (seriesIndices.length == 0) {
            return;
          }
          // For now get the first series sorted by index.
          seriesIndices.sort(function(a, b) {
            return a - b;
          });
          var seriesData = series[seriesIndices[0]];

          if (seriesData.units) {
            this.chartYAxisLabel = seriesData.units;
            // Some unit names have improvement direction information in them.
            if (seriesData.units.indexOf('is better') == -1 &&
                seriesData.better) {
              this.chartYAxisLabel += ' (' + seriesData.better.toLowerCase();
              this.chartYAxisLabel += ' is better)';
            }
          }
        },

        /**
         * Updates the map of series index to the adjusted scale.
         *
         * This map is used to update y-axis scale base on selected traces.
         */
        updateSmartAutoscaleMap: function() {
          this.yAxisScaleMap = {};
          for (var seriesIndex in this.json.data) {
            var data = this.json.data[seriesIndex].data;
            var values = [];
            for (var dataIndex = 0; dataIndex < data.length; dataIndex++) {
              values.push(data[dataIndex][1]);
            }
            if (values.length > 0) {
              var scale = this.determineMinMax(seriesIndex, values);
              this.yAxisScaleMap[seriesIndex] = scale;
            }
          }
        },

        /**
         * Determines a min and a max from a list of numbers without outliers.
         *
         * @param {number} seriesIndex Index into the data series list
         *     (this.json.data).
         * @param {Array.<number>} values List of series data values.
         * @return {Object} An object containing min and max number.
         */
        determineMinMax: function(seriesIndex, values) {
          values = values.filter(function(v) {
            return v != null;
          });
          var outlierDirections = getOutlierDirections(values);

          // Exclude value that is a stand-alone spike which has either
          // outlier direction 1 or -1 in between zeros. Also include
          // points that has an Anomaly.
          var resultValues = [];
          for (var i = 0; i < outlierDirections.length; i++) {
            var direction = outlierDirections[i];
            if (direction == 0 || this.hasAnomaly(seriesIndex, i)) {
              resultValues.push(values[i]);
            } else if (i > 0 && i < outlierDirections.length - 1) {
              if (direction == outlierDirections[i - 1] ||
                  direction == outlierDirections[i + 1]) {
                resultValues.push(values[i]);
              }
            }
          }
          return {'min': Math.min.apply(Math, resultValues),
                  'max': Math.max.apply(Math, resultValues)};
        },

        /**
         * Checks whether a series at a point has an anomaly.
         */
        hasAnomaly: function(seriesIndex, dataIndex) {
          var annotations = this.json.annotations;
          if (!annotations[seriesIndex] ||
              !annotations[seriesIndex][dataIndex] ||
              !annotations[seriesIndex][dataIndex]['g_anomaly']) {
            return false;
          }
          return true;
        },

        /**
         * Sets scale for chart's y-axis for graphs in indicesToGraph.
         * This function sets values in this.chartOptions based on the
         * contents of this.yAxisScaleMap.
         */
        setSmartAutoscale: function() {
          if (!this.indicesToGraph.length || this.indicesToGraph.length <= 0 ||
              !this.yAxisScaleMap) {
            return;
          }

          // Get the min/max of the min/max of all graphs in indicesToGraph.
          var firstIndex = this.indicesToGraph[0];
          if (!(firstIndex in this.yAxisScaleMap)) {
            return;
          }
          var min = this.yAxisScaleMap[firstIndex].min;
          var max = this.yAxisScaleMap[firstIndex].max;
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var scale = this.yAxisScaleMap[this.indicesToGraph[i]];
            if (scale && scale.min < min) {
              min = scale.min;
            }
            if (scale && scale.max > max) {
              max = scale.max;
            }
          }
          this.chartOptions.yaxis.min = min;
          this.chartOptions.yaxis.max = max;
          this.addAxisMargin(this.chartOptions.yaxis);
        },

        /**
         * Adds margins to axis so lines don't touch the chart's borders.
         * Same as how flot does it.
         *
         * @param {Object} axis An object containing min and max number.
         */
        addAxisMargin: function(axis) {
          var margin = 0.2; // Flot's default for autoscaleMargin.
          var min = axis.min, max = axis.max;
          var delta = max - min;
          if (delta == 0.0) {
            min -= axis.min == 0 ? 1 : margin;
            max += axis.max == 0 ? 1 : margin;
          } else {
            min -= delta * margin;
            if (min < 0 && axis.min >= 0)
              min = 0;
            max += delta * margin;
            if (max > 0 && axis.max <= 0)
              max = 0;
          }
          axis.min = min;
          axis.max = max;
        },

        /**
         * This method is called when the property 'indicesToGraph' changes.
         * @param {?Array.<number>} oldValue Old value of indicesToGraph.
         */
        indicesToGraphChanged: function() {
          this.updateChart();
          this.$.title.update();
        },

        /**
         * This method is called when the property 'warning' changes.
         * If there's a warning, we want to update the background color of the
         * chart.
         */
        warningsChanged: function() {
          var backgroundColor = ((this.warnings.length) ? '#e6e6e6' : null);
          this.chartOptions.grid.backgroundColor = backgroundColor;
          if (this.chart) {
            this.chart.getOptions().grid.backgroundColor = backgroundColor;
            this.chart.setupGrid();
            this.chart.draw();
          }
        },

        /**
         * Updates the currently displayed chart.
         */
        updateChart: function() {
          if (!this.drawable) {
            return;
          }

          var data = this.getDataForFlot();
          if (data.length == 0) {
            data = [[]];
            this.chart = $.plot(this.$.plot, data, this.chartOptions);
            this.clearAlertIcons();
            return;
          }

          var startRev = uri.getParameter('start_rev');
          var endRev = uri.getParameter('end_rev');
          var firstSeriesIsEmpty = data[0].data.length == 0;
          if (startRev && endRev && firstSeriesIsEmpty) {
            this.warnings.push('Data not available for revision range ' +
                               startRev + ':' + endRev + '.');
          }

          var isNotZoomedIn = this.$.original.hidden;
          if (isNotZoomedIn) {
            this.setSmartAutoscale();
          }

          this.createFixedXAxis(data);
          this.chart = $.plot(this.$.plot, data, this.chartOptions);
          this.showAlerts();
          this.updateWarningsForSelectedSeries();
        },

        /**
         * Puts together the array of series to pass to Flot's $.plot function.
         * The data to plot is based on this.json and this.indicesToGraph.
         * @return {Array.<Object>} Data to plot. This could be an empty array.
         */
        getDataForFlot: function() {
          if (!this.jsonHasData(this.json)) {
            console.debug('getDataForFlot: this.json not set.');
            return [];
          }
          if (!this.json['error_bars']) {
            console.debug('getDataForFlot: data or error bars not set.');
            return [];
          }

          var data = [];
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            if (index >= 0 && this.json.data[index]) {
              data.push(deepCopy(this.json.data[index]));
            } else {
              console.debug('getDataForFlot: indicesToGraph: ',
                            this.indicesToGraph);
              return [];
            }
          }

          // Add in error bars after data.
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            if (index >= 0 && this.json['error_bars'][index]) {
              data.push(deepCopy(this.json['error_bars'][index][0]));
              data.push(deepCopy(this.json['error_bars'][index][1]));
            } else {
              console.debug('getDataForFlot: indicesToGraph: ',
                            this.indicesToGraph);
              return [];
            }
          }
          return data;
        },

        /**
         * Modifies the given series data so that the X-values are indexes
         * instead of revision numbers. This is called before plotting.
         *
         * We want a fixed x-axis, with points evenly spaced. Flot has
         * functions to scale the x-axis, but they break vertical zooming.
         * So we plot a copy of the JSON we get from the server, with the
         * revisions reordered starting from 0 and incrementing once for each
         * rev.
         *
         * We start by getting a list of all the revisions, and ordering them
         * from 0-N. Because there can be gaps in the graphs, we want to look
         * at all the charts, even ones that are not plotted, so that the gaps
         * are accounted for accurately.
         *
         * TODO(qyearsley): This function has at least two separate
         * responsibilities: constructing this.revisionMap and actually
         * changing the X-values. These could be separated out.
         *
         * @param {Array.<Object>} data Flot graph data.
         */
        createFixedXAxis: function(data) {
          // Make a map of all revisions for all data series to a series index
          // and data index.
          var allRevisions = {};
          if (!this.json ||
              !this.json.data ||
              this.indicesToGraph.length == 0) {
            console.debug('createFixedXAxis: !this.json, !this.json.data or ' +
                          'this.indicesToGraph.length == 0');
            return;
          }

          // Only create axis for selected series.
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            var series = this.json.data[index];
            var numPoints = series.data.length;
            for (var dataIndex = 0; dataIndex < numPoints; dataIndex++) {
              var revision = series.data[dataIndex][0];
              allRevisions[revision] = [series.index, dataIndex];
            }
          }

          // Make an ordered list of all revision numbers for any series.
          var orderedRevisions = Object.keys(allRevisions).sort(function(a, b) {
            return a - b;
          });
          if (orderedRevisions.length == 0) {
            // If there's no data to plot, then this array will be empty.
            return;
          }
          this.$.slider.startrev = orderedRevisions[0];
          this.$.slider.endrev = orderedRevisions[orderedRevisions.length - 1];

          // We keep a map of the ordered revision index to the [revision,
          // series index, data index] so that it's easy to show the right
          // label on the X-axis. This is updated here but used in formatXAxis.
          this.revisionMap = {};

          // We also want to make a reverse-lookup object which maps values in
          // in |orderedRevisions| to their indexes. This will be used below.
          var revisionToIndexMap = {};

          for (var i = 0; i < orderedRevisions.length; i++) {
            var rev = orderedRevisions[i];
            this.revisionMap[i] =
                [rev, allRevisions[rev][0], allRevisions[rev][1]];
            revisionToIndexMap[rev] = i;
          }

          // Now that we have all the data we need cached, update the revisions
          // for each of the data points that will be shown on the graph.
          for (var seriesIndex = 0; seriesIndex < data.length; seriesIndex++) {
            var series = data[seriesIndex];
            var numPoints = series.data.length;
            for (var dataIndex = 0; dataIndex < numPoints; dataIndex++) {
              var revision = series.data[dataIndex][0];
              series.data[dataIndex][0] = revisionToIndexMap[revision];
            }
          }
          this.chartOptions.xaxis.minTickSize = orderedRevisions.length / 10;
        },

        /**
         * Formats numbers that are displayed at ticks on the X-axis.
         *
         * If there are annotations for the first data series and for this point
         * there is a revision type specified by "a_default_rev", then we can
         * display that on the x-axis. Otherwise, we can just use the revision
         * (point ID) as-is.
         *
         * Note: This is similar to xAxisTickFormatter in embed.js.
         *
         * @param {number} val An X-value.
         * @param {Object} axis Not used.
         * @return {string} A string that should be shown on the X-axis.
         */
        formatXAxis: function(val, axis) {
          var lookupIndex = Math.round(Math.max(val, 0));
          if (!this.revisionMap) {
            // this.revisionMap may not yet be set by this.createFixedXAxis.
            return '';
          }
          var lookup = this.revisionMap[lookupIndex];
          if (!lookup) {
            return '';
          }
          var rev = lookup[0];
          var seriesIndex = lookup[1];
          var dataIndex = lookup[2];

          var annotations = this.json.annotations;
          if (annotations[seriesIndex] && annotations[seriesIndex][dataIndex]) {
            var annotation = annotations[seriesIndex][dataIndex];
            var defaultRev = annotation['a_default_rev'];
            if (defaultRev && annotation[defaultRev]) {
              return getDisplayRevision(annotation[defaultRev]);
            }
          }
          return getDisplayRevision(rev);
        },

        /**
         * Formats numbers that are displayed at ticks on the Y-axis.
         * @param {(number|string)} val A Y-value.
         * @param {Object} axis Not used.
         * @return {string} A string.
         */
        formatYAxis: function(val, axis) {
          return formatNumber(val);
        },

        /**
         * Adds all of the alert icons to the chart and sets their positions.
         */
        showAlerts: function() {
          this.clearAlertIcons();
          var minHeight = this.chart.getAxes().yaxis.min;
          var maxHeight = this.chart.getAxes().yaxis.max;
          var xOffset = this.chartOptions.yaxis.labelWidth;
          var flotData = this.chart.getData();
          var annotations = this.json.annotations;
          for (var flotIndex = 0; flotIndex < flotData.length; flotIndex++) {
            var jsonSeriesIndex = flotData[flotIndex].index;
            if (jsonSeriesIndex == null || !annotations[jsonSeriesIndex]) {
              continue;
            }
            var dataLength = flotData[flotIndex].data.length;
            for (var dataIndex = 0; dataIndex < dataLength; dataIndex++) {
              var a = annotations[jsonSeriesIndex][dataIndex];
              if (!annotations[jsonSeriesIndex][dataIndex] ||
                  !annotations[jsonSeriesIndex][dataIndex]['g_anomaly'] ||
                  flotData[flotIndex].data[dataIndex][1] < minHeight ||
                  flotData[flotIndex].data[dataIndex][1] > maxHeight) {
                continue;
              }

              var flotPoint = flotData[flotIndex].data[dataIndex];
              var left = xOffset + Math.round(
                  flotData[flotIndex].xaxis.p2c(flotPoint[0]));
              var top = Math.round(
                  flotData[flotIndex].yaxis.p2c(flotPoint[1]));

              var alertIcon = document.createElement('alert-icon');
              alertIcon.initialize(
                annotations[jsonSeriesIndex][dataIndex]['g_anomaly'],
                this.alertKey);
              Polymer.dom(
                  this.$['alert-icon-container']).appendChild(alertIcon);
              alertIcon.setPosition(top, left);

              alertIcon.onmouseover = this.onAlertMouseOver.bind(
                  this, flotIndex, dataIndex);
              alertIcon.onclick = this.onAlertClick.bind(
                  this, flotIndex, dataIndex);
            }
          }
        },

        clearAlertIcons: function() {
          Polymer.dom(this.$['alert-icon-container']).innerHTML = '';
        },

        /**
         * Handler for 'onSeriesGroupClosed' event.
         */
        onSeriesGroupClosed: function(event) {
          var groupIndex = event.detail.groupIndex;
          var seriesGroup = this.splice('seriesGroupList', groupIndex, 1)[0];

          var tests = seriesGroup.tests;
          for (var i = 0; i < tests.length; i++) {
            var indexToRemove = tests[i].index;
            delete this.json.data[indexToRemove];
            delete this.json.annotations.series[indexToRemove];
            delete this.json.annotations[indexToRemove];
            delete this.json['error_bars'][indexToRemove];
            if (this.indicesToGraph.indexOf(indexToRemove) != -1) {
              this.splice('indicesToGraph',
                  this.indicesToGraph.indexOf(indexToRemove), 1);
            }
          }
          this.updateSlider();
          this.updateYAxisLabel();
          this.updateSmartAutoscaleMap();
          this.updateChart();
          this.fireChartStateChangedEvent(this.seriesGroupList);
        },

        /**
         * Handler for 'titleclicked' event fired from chart-title.
         * This function clears out current chart data and re-adds a
         * series group from the test path created from clicked title
         * parts.
         */
        onTitleClicked: function(event, detail) {
          var titleParts = event.detail.titleParts;
          var partIndex = event.detail.partIndex;
          var testPath = titleParts.slice(0, partIndex + 1).join('/');
          this.json = deepCopy(this.DEFAULT_JSON_PROPERTIES);
          this.set('seriesGroupList', []);
          this.set('indicesToGraph', []);
          this.addSeriesGroup([[testPath, []]], true);
          this.fireChartStateChangedEvent(this.seriesGroupList);
        },

        /**
         * Handler for 'mouseleave' event, hides the tooltip.
         */
        onMouseLeave: function(event) {
          this.hideTooltip();
        },

        /**
         * Handler for 'plotselected' event, fired when a plot selection is
         * made.
         * For more information about selection in flot, see:
         * http://www.flotcharts.org/flot/jquery.flot.selection.js
         * @param {Event} event Event object.
         * @param {Object} ranges Object containing the selected range.
         */
        onPlotSelected: function(event, ranges) {
          this.selecting = false;
          this.lastSelectedDelta = ranges;
        },

        /**
         * Handler for 'plotselecting' event, fired repeatedly when selecting.
         * @param {Event} event Event object.
         * @param {Object} ranges An object containing the selected range.
         */
        onPlotSelecting: function(event, ranges) {
          if (!ranges) {
            return;
          }
          if (!this.selecting) {
            this.firstSelectedValue = ranges.yaxis.from;
            this.selecting = true;
          }

          this.showDelta = true;

          var delta = Math.abs(ranges.yaxis.to - ranges.yaxis.from);
          this.deltaAbsolute = delta.toFixed(2);
          this.deltaPercent =
              (delta * 100 / this.firstSelectedValue).toFixed(2);
        },

        /**
         * Handler for 'plotunselected' event, fired when selection is
         * cancelled.
         */
        onPlotUnselected: function() {
          this.selecting = false;
          this.showDelta = false;
        },

        /**
         * Handler for the 'plotclick' event, fired when the chart is clicked.
         * @param {Event} event Event object.
         * @param {Object} pos An object which contains the keys "x" and "y".
         * @param {Object} item An object of the item clicked, null otherwise.
         */
        onPlotClick: function(event, pos, item) {
          if (this.lastSelectedDelta) {
            var from = this.lastSelectedDelta.yaxis.from;
            var to = this.lastSelectedDelta.yaxis.to;
            if (pos.y == from || pos.y == to) {
              // Flot sends a spurious click event at the end of the selection.
              return;
            }
            var min = Math.min(from, to), max = Math.max(from, to);
            if (pos.y > min && pos.y < max) {
              this.chartOptions.yaxis.min = min;
              this.chartOptions.yaxis.max = max;
              this.$.original.hidden = false;
              this.updateChart();
              this.$.original.style.left =
                  (this.$.plot.offsetWidth - 120) + 'px';
            }
            this.lastSelectedDelta = null;
          } else if (item && item.dataIndex != this.currentItem) {
            // Clicked on a new data point.
            // Show revision history and sticky tooltip.
            this.stickyTooltip = true;
            this.currentItem = item.dataIndex;
            this.showTooltip(item.seriesIndex, item.dataIndex);
          } else {
            // Hide the tooltip if the user clicked the same point again
            // or clicked an empty place on the graph.
            this.hideTooltipEvenIfSticky();
          }
        },

        /**
         * Brings up the triage dialog when an alert circle is clicked.
         * @param {number} flotSeriesIndex Index into the flot data series
         *     array `this.chart.getData()`.
         * @param {number} dataIndex Index into an array of points.
         * @param {Event} The click event.
         */
        onAlertClick: function(flotSeriesIndex, dataIndex, event) {
          // Note: this.chart.getData() returns a list of series objects
          // (including series objects for error regions).
          var jsonSeriesIndex = this.chart.getData()[flotSeriesIndex].index;
          if (jsonSeriesIndex == null) {
            return;
          }
          var data = this.json.data[jsonSeriesIndex].data;

          // Populate the nudgeList array with information about nearby
          // revisions. Each entry in the nudgeList is an object with basic
          // information about a point.
          var nudgeList = [];
          for (var i = Math.max(1, dataIndex - 5);
               i < Math.min(dataIndex + 5, data.length - 1);
               i++) {
            // Get annotation information about this nearby point.
            // This might be null if there are gaps in the data series.
            // In that case, we can just not add the point to the nudge list.
            var annotation = this.json.annotations[jsonSeriesIndex][i];
            if (!annotation) {
              continue;
            }
            var displayRevision = data[i][0];
            if (annotation['a_default_rev']) {
              displayRevision = annotation[annotation.a_default_rev];
            }
            displayRevision = getDisplayRevision(displayRevision);
            var amount = ' 0: ';
            if (i < dataIndex) {
              amount = '-' + (dataIndex - i) + ': ';
            } else if (i > dataIndex) {
              amount = '+' + (i - dataIndex) + ': ';
            }
            nudgeList.push({
              startRevision: data[i - 1][0] + 1,
              endRevision: data[i][0],
              displayEndRevision: displayRevision,
              value: Math.round(data[i][1] * 100) / 100,
              selected: i == dataIndex,
              dataIndex: i,
              amount: amount
            });
          }

          // Get the anomaly info object, and add a few fields.
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];
          var anomalyInfo = annotation.g_anomaly;
          anomalyInfo['nudgeList'] = nudgeList;
          anomalyInfo['seriesIndex'] = jsonSeriesIndex;
          anomalyInfo['dataIndex'] = dataIndex;

          // The alerts and triaged lists are attributes of chart-tooltip
          // which are used for showing information about anomalies. The alerts
          // list is also used for showing the triage dialog.
          var alerts = null, triaged = null;
          if (anomalyInfo.bug_id) {
            triaged = [anomalyInfo];
          } else {
            alerts = [anomalyInfo];
          }

          this.stickyTooltip = true;
          this.showTooltip(flotSeriesIndex, dataIndex, alerts, triaged);
        },

        /**
         * Brings up the tooltip when an alert circle is moused over.
         * @param {number} flotSeriesIndex Index into the flot data series
         *     array `this.chart.getData()`.
         * @param {number} dataIndex Index into an array of points.
         * @param {Event} The click event.
         */
        onAlertMouseOver: function(flotSeriesIndex, dataIndex, event) {
          if (!this.stickyTooltip)
            this.showTooltip(flotSeriesIndex, dataIndex);
        },
        /**
         * Updates the interface when a bug is triaged.
         * This is the event handler for a 'triaged' event on the
         * chart-tooltip.
         */
        onBugTriaged: function(event) {
          var jsonSeriesIndex = event.detail.alerts[0].seriesIndex;
          var dataIndex = event.detail.alerts[0].dataIndex;
          var bugId = event.detail.bugid;

          // Update the bug id locally.
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];
          annotation['g_anomaly']['bug_id'] = bugId;
          this.$.tooltip.bugId = bugId;
          if (!bugId) {
            this.$.tooltip.alerts = this.$.tooltip.triagedAlerts;
            this.$.tooltip.triagedAlerts = null;
          } else {
            this.$.tooltip.alertInvalidOrIgnored = bugId < 0;
            this.$.tooltip.triagedAlerts = this.$.tooltip.alerts;
            this.$.tooltip.alerts = null;
            var data = this.json.annotations[jsonSeriesIndex][dataIndex];
            this.$.tooltip.alertKey = data['g_anomaly'].key;
          }
          // Refresh the anomalies to make the one with the new bug id black.
          this.showAlerts();
        },

        /**
         * Handler for the alertChangedRevisions event.
         *
         * The alertChangedRevisions event is fired from the triage dialog when
         * an alert is nudged.
         */
        onAlertChangedRevisions: function(event) {
          var jsonSeriesIndex = event.detail.alerts[0].seriesIndex;
          var dataIndex = event.detail.alerts[0].dataIndex;
          var newDataIndex = event.detail.newDataIndex;
          var seriesAnnotations = this.json.annotations[jsonSeriesIndex];
          var alertInfo = seriesAnnotations[dataIndex]['g_anomaly'];
          alertInfo['start_revision'] = event.detail.startRev;
          alertInfo['end_revision'] = event.detail.endRev;
          seriesAnnotations[dataIndex]['g_anomaly'] = null;
          seriesAnnotations[newDataIndex]['g_anomaly'] = alertInfo;
          this.showAlerts();
        },

        /**
         * Handler for the 'plothover' event, fired when the mouse is hovering
         * over the plot area. If the user is hovering over a point, we want to
         * show the tooltip for that point.
         * @param {Event} event Event object.
         * @param {Object} pos Position object.
         * @param {Object} item Item being hovered over.
         */
        onPlotHover: function(event, pos, item) {
          // If the current tooltip is sticky, just leave it.
          if (this.stickyTooltip) {
            return;
          }
          // If the current tooltip isn't sticky but we're hovering over
          // nothing, hide the tooltip.
          if (!item) {
            this.hideTooltip();
            return;
          }
          // If the current tooltip isn't sticky and we're over a data point,
          // show the tooltip.
          this.showTooltip(item.seriesIndex, item.dataIndex);
        },

        /**
         * Displays a tooltip for the given point on the graph.
         *
         * TODO(qyearsley): Refactor. See catapult:#1348.
         *
         * NOTE: Instead of taking lists of alerts and triaged alerts, it
         * would be possible for this function to just take one alert, since
         * there should never generally be more than one alert at one point.
         *
         * @param {number} flotSeriesIndex The index of the series in
         *     `this.chart.getData()`.
         * @param {number} dataIndex The index of the data in the series.
         * @param {Array=} opt_alerts Array of alerts.
         * @param {Array=} opt_triaged A boolean.
         */
        showTooltip: function(
            flotSeriesIndex, dataIndex, opt_alerts, opt_triaged) {
          // Reset the properties of the tooltip so that nothing is left over
          // from the last time that showTooltip was called on another point.
          this.resetTooltip();

          // Don't show the tooltip if we're selecting a range on the y axis.
          if (this.selecting) {
            return;
          }

          var flotData = this.chart.getData();
          var jsonSeriesIndex = this.chart.getData()[flotSeriesIndex].index;
          if (jsonSeriesIndex == null) {
            console.warn('showTooltip returned after ' + jsonSeriesIndex +
                         ' was null for flotSeriesIndex ' + flotSeriesIndex);
            return;
          }

          // Set the main properties of the tooltip.
          var series = this.json.annotations.series[jsonSeriesIndex];
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];

          // In the data from this.chart.getData(), the series indexes are
          // different, and the point x-values are all converted to indexes.
          var pointFromChart = flotData[flotSeriesIndex].data[dataIndex];

          // The data from /graph_json is the data as it originally came,
          // and the x-values are the original Row IDs.
          var seriesFromJson = this.json.data[jsonSeriesIndex];
          var pointFromJson = seriesFromJson.data[dataIndex];

          var xValue = pointFromChart[0];
          var pointId = pointFromJson[0];
          var yValue = pointFromJson[1];

          this.$.tooltip.testPath = series.path;
          this.$.tooltip.value = formatNumber(yValue);
          if (annotation.error > 0) {
            this.$.tooltip.stddev = formatNumber(annotation.error);
          }
          this.$.tooltip.pointId = pointId;
          this.$.tooltip.revisions = this.getRevisions(
              jsonSeriesIndex, dataIndex);
          this.$.tooltip.links = this.getTooltipLinks(annotation, series.path,
                                                      pointId);
          if (annotation.timestamp) {
            var d = new Date(annotation.timestamp);
            this.$.tooltip.timestamp = d.toISOString();
          }

          // Set the alert-related properties of the tooltip.
          if (opt_alerts === undefined)
            opt_alerts = null;
          this.$.tooltip.alerts = opt_alerts;
          if (opt_triaged === undefined)
            opt_triaged = null;
          this.$.tooltip.triagedAlerts = opt_triaged;
          if (annotation['g_anomaly']) {
            if (annotation.g_anomaly['bug_id']) {
              this.$.tooltip.bugId = annotation['g_anomaly']['bug_id'];
              this.$.tooltip.alertInvalidOrIgnored =
                  annotation['g_anomaly']['bug_id'] < 0;
              this.$.tooltip.alertKey = annotation['g_anomaly']['key'];
            }
            this.$.tooltip.recovered = annotation['g_anomaly']['recovered'];
          }

          var traceRerunInfo = [];
          if (annotation['a_trace_rerun_options']) {
            for (var i in annotation['a_trace_rerun_options']) {
              var currentOption = annotation['a_trace_rerun_options'][i];
              traceRerunInfo.push({
                  'name': i,
                  'option': currentOption
              });
            }
          } else {
              traceRerunInfo.push({
                  'name': 'Default Trace Profiler',
                  'option': '--profiler=trace'
              });
          }
          this.$.tooltip.bisectInfo = {
            canBisect: series.can_bisect,
            badRev: this.getRevisionForBisect(jsonSeriesIndex, dataIndex),
            goodRev: this.getRevisionForBisect(jsonSeriesIndex, dataIndex - 1),
            testPath: series.path,
            traceRerunInfo: traceRerunInfo
          };

          // Un-hide and position the tooltip box.
          var top = flotData[flotSeriesIndex].yaxis.p2c(yValue);
          var left = flotData[flotSeriesIndex].xaxis.p2c(xValue) +
              this.chartOptions.yaxis.labelWidth;
          this.$.tooltip.openAtPosition(top, left);
        },

        /**
         * Reset the chart-tooltip's properties.
         */
        resetTooltip: function() {
          this.$.tooltip.testPath = null;
          this.$.tooltip.value = null;
          this.$.tooltip.stddev = null;
          this.$.tooltip.pointId = null;
          this.$.tooltip.revisions = null;
          this.$.tooltip.links = null;
          this.$.tooltip.alerts = null;
          this.$.tooltip.triagedAlerts = null;
          this.$.tooltip.bugId = null;
          this.$.tooltip.alertKey = null;
          this.$.tooltip.recovered = null;
          this.$.tooltip.timestamp = null;
          this.$.tooltip.bisectInfo = null;
        },

        /**
         * Gets a revision value to use when populating the bisect form.
         *
         * @param {number} jsonSeriesIndex An index in this.json.data.
         * @param {number} dataIndex The index of the point in the series.
         * @return {?(number|string)} A revision to put in the bisect form.
         */
        getRevisionForBisect: function(jsonSeriesIndex, dataIndex) {
          // If the data point contains a default revision type, use that.
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];
          if (!annotation) {
            return null;
          }
          var defaultRevType = annotation['a_default_rev'];
          if (defaultRevType && annotation[defaultRevType]) {
            return annotation[defaultRevType];
          }

          // Otherwise, use the x-value of the point (aka the point ID).
          var point = this.json.data[jsonSeriesIndex].data[dataIndex];
          if (point && point[0]) {
            return point[0];
          }
          return null;
        },

        /**
         * Hides the tooltip only if it's not sticky.
         */
        hideTooltip: function() {
          if (this.stickyTooltip) {
            return;
          }
          this.$.tooltip.close();
        },

        /**
         * Force-hides the tooltip.
         */
        hideTooltipEvenIfSticky: function() {
          this.stickyTooltip = false;
          this.hideTooltip();
        },

        /**
         * Gets a list of obj about links to put in the tooltip.
         * @param {Object} annotation Annotation object for this point.
         * @param {string} testPath Test path.
         * @param {number} pointId Main revision at the given point.
         * @return {Array.<Object>} List of objects with properties text and
         *     url.
         */
        getTooltipLinks: function(annotation, testPath, pointId) {
          var links = [];
          for (var key in annotation) {
            if (key == 'g_anomaly') {
              var debugUrl = '/debug_alert?test_path=' + testPath +
                             '&rev=' + pointId;
              links.push({
                  'text': 'Debug alert',
                  'url': debugUrl
              });
            } else if (key == 'a_tracing_uri') {
              links.push({
                  'text': 'Trace',
                  'url': annotation['a_tracing_uri']
              });
            } else if (key.indexOf('a_') === 0) {
              var match = TOOLTIP_LINK_REGEX.exec(annotation[key]);
              if (match) {
                links.push({
                    'text': match[1],
                    'url': match[2]
                });
              }
            }
          }
          return links;
        },

        /**
         * Returns an array of revision range info objects for the given point.
         *
         * This array is used to show revision ranges and change log links in
         * the tooltip.
         * Example format for the returned array:
         *   [
         *     {
         *       name: "Chrome Revision",
         *       start: 216441,
         *       end: 216538,
         *       displayStart: 216441,
         *       displayEnd: 216538,
         *       url: "http://x.foo.org/changelog.html?range=216441:216538",
         *     },
         *     ...
         *   ]
         *
         * @param {number} seriesIndex An index in this.json.data.
         * @param {number} dataIndex The index of the point within the series.
         * @return {Array.<Object>} An array of information needed for showing
         *     change log links for different types of revisions.
         */
        getRevisions: function(seriesIndex, dataIndex) {
          var annotationSeries = this.json.annotations[seriesIndex];
          var annotation = annotationSeries[dataIndex];
          var previousAnnotation = annotationSeries[dataIndex - 1];
          var defaultRevisionRangeInfo = null;
          var revisionRangeInfoObjects = [];
          for (var revisionTypeKey in annotation) {
            if (revisionTypeKey.indexOf('r_') != 0) {
              continue;  // Not a revision.
            }
            if (!this.revisionInfo[revisionTypeKey]) {
              console.warn(
                  'No entry', revisionTypeKey, 'in', this.revisionInfo);
              continue;
            }
            var end = annotation[revisionTypeKey];
            var start = -1;
            if (dataIndex > 0 && previousAnnotation &&
                previousAnnotation[revisionTypeKey]) {
              start = previousAnnotation[revisionTypeKey];
            }
            var revisionRangeInfo = this.getRevisionRangeInfo(
                revisionTypeKey, start, end);
            if (revisionTypeKey == annotation['a_default_rev']) {
              // The default revision type will be inserted afterwards.
              defaultRevisionRangeInfo = revisionRangeInfo;
            } else {
              revisionRangeInfoObjects.push(revisionRangeInfo);
            }
          }
          // Revisions are sorted by name, with the default first.
          revisionRangeInfoObjects.sort(function(a, b) {
            var aName = a['name'].toLowerCase();
            var bName = b['name'].toLowerCase();
            return aName.localeCompare(bName);
          });
          if (defaultRevisionRangeInfo) {
            revisionRangeInfoObjects.unshift(defaultRevisionRangeInfo);
          }
          return revisionRangeInfoObjects;
        },

        /**
         * Returns an object with revision-related information for one type
         * of revision, for two revision numbers.
         *
         * @param {string} revisionTypeKey A key in this.revisionInfo.
         *     This will be a string starting with "r_".
         * @param {(number|string|boolean)} start Optional start revision.
         *     False may be given if the start and end revision are the same.
         * @param {(number|string)} end End revision or only revision.
         * @return {Object} The information necessary for showing a link for
         *     a change log for a particular revision range.
         */
        getRevisionRangeInfo: function(revisionTypeKey, start, end) {
          var revisionInfo = this.revisionInfo[revisionTypeKey];
          if (!revisionInfo) {
            console.warn('No entry', revisionTypeKey, 'in', this.revisionInfo);
          }
          var revisionTypeKey = revisionInfo['name'];
          var urlTemplate = revisionInfo['url'];

          if (!isNaN(start) && !isNaN(end) && Number(start) > Number(end)) {
            console.warn('Start and end revisions flipped:', start, end);
            var temp = start;
            start = end;
            end = temp;
          }

          // For a regression range, start is the "last known good" revision.
          // We want the "first possible bad" revision.
          if (!isNaN(start) && (start != end)) {
            start = Number(start) + 1;
          }

          // If the substring R1_trim is found in the URL template, we assume
          // that it's the URL template for Chrome OS versions.
          var url = '';
          if (urlTemplate.indexOf('{{R1_trim}}') != -1) {
            url = this.fillInChromeOSChangeLogURL(urlTemplate, start, end);
          } else {
            url = urlTemplate.replace('{{R1}}', start).replace('{{R2}}', end);
          }

          if (start == end || !start) {
            start = false;
          }

          return {
            'name': revisionTypeKey,
            'url': url,
            'start': start,
            'end': end,
            'displayStart': getDisplayRevision(start),
            'displayEnd': getDisplayRevision(end)
          };
        },

        /**
         * Fills in a Chrome OS or Chrome version change log URL.
         * The chromeOS diff tool expects version numbers to be composed of
         * only the right-most 3 components of the number (i.e., we need to
         * drop the  left-most component when constructing the URL below).
         * The format of the specified version number should be "X.Y.Z",
         * not "W.X.Y.Z".
         * @param {string} urlTemplate A string with the template fields
         *     R1_trim and R2_trim.
         * @param {string} start Start version string.
         * @param {string} end End version string.
         */
        fillInChromeOSChangeLogURL: function(urlTemplate, start, end) {
          var urlEndVersion = end.substring(end.indexOf('.') + 1);
          var urlStartVersion = '';
          if (start) {
            urlStartVersion = start.substring(start.indexOf('.') + 1);
          } else {
            urlStartVersion = urlEndVersion;
          }
          var url = urlTemplate.replace('{{R1_trim}}', urlStartVersion);
          url = url.replace('{{R2_trim}}', urlEndVersion);
          return url;
        },

        /**
         * Handler for the click event for the 'View original graph' link.
         *
         * This link only appears after zooming in on a smaller Y-axis range
         * (by clicking and dragging and then clicking). When the 'view
         * original graph' link has been clicked, the original Y-axis range
         * should be restored.
         */
        onViewOriginal: function() {
          this.chartOptions.yaxis.min = null;
          this.chartOptions.yaxis.max = null;
          this.$.original.hidden = true;
          this.updateChart();
        },

        /**
         * Handler for resize event.
         * @param {Event} event Event object.
         */
        onResize: function(event) {
          // Try not to resize graphs until the user has stopped resizing
          clearTimeout(this.resizeTimer);
          this.resizeTimer = setTimeout(this.resizeGraph.bind(this), 100);
        },

        /**
         * Resizes the chart if it's present.
         */
        resizeGraph: function() {
          if (!this.chart || this.$.plot.offsetWidth == 0) {
            return;
          }
          // The chart is resized when it's updated.
          this.updateChart();
         },

        /**
         * On collapseLegend change, updates graph and chart-revision sizes.
         */
        collapseLegendChanged: function() {
          this.onResize();
          this.$.slider.onResize();
        },

        seriesMouseover: function(event) {
          var index = event.detail.index;
          if (this.indicesToGraph.indexOf(index) != -1) {
            this.highlightSeries([index]);
          }
        },

        seriesMouseout: function(event) {
          this.undoSeriesHighlighting();
        },

        /**
         * Highlights each series in |targetIndices|.
         * Highlighting makes a series line width and shadow thicker and lowers
         * the opacity of unhighlighted series.
         *
         * @param {Array.<number>} targetIndices List of series indices to
         *     highlight.
         */
        highlightSeries: function(targetIndices) {
          var flotData = this.chart.getData();
          if (!flotData) {
            return;
          }

          for (var i = 0; i < flotData.length; i++) {
            var series = flotData[i];
            if (targetIndices.indexOf(this.getSeriesFillIndex(series)) != -1) {
              continue;
            }
            if (targetIndices.indexOf(series.index) != -1) {
              this.updateSeriesHighlighting(series, 2.5, 1, 0.2, 4);
            } else {
               this.updateSeriesHighlighting(series, 2, 0.25, 0, 0);
            }
          }

          this.chart.setData(flotData);
          this.chart.draw();
        },

        undoSeriesHighlighting: function() {
          if (!this.chart) {
            return;
          }
          var flotData = this.chart.getData();
          if (!flotData) {
            return;
          }
          for (var i = 0; i < flotData.length; i++) {
            this.updateSeriesHighlighting(
                flotData[i],
                this.DEFAULT_SERIES_PROPERTIES.lineWidth,
                this.DEFAULT_SERIES_PROPERTIES.opacity,
                this.DEFAULT_SERIES_PROPERTIES.fill,
                this.DEFAULT_SERIES_PROPERTIES.shadowSize);
          }
          this.chart.setData(flotData);
          this.chart.draw();
        },

        /**
         * Gets series's target index if series is a filled line.
         * Filled lines are series that shade the upper and lower bounds
         * (e.g. error bar regions).
         *
         * @param {Object} series The data series
         * @return {?number} The index of the series that filled line
         * correspond to, null if series is not a filled line.
         */
        getSeriesFillIndex: function(series) {
          if (!series.fillBetween) {
            return null;
          }
          // fillBetween is a string 'line_X' (labeled by graph_json.py),
          // where X is a series index that filled line correspond to.
          var index = series.fillBetween.replace(/[^0-9]/g, '');
          return parseInt(index);
        },

        updateSeriesHighlighting: function(series, lineWidth, opacity,
                                           fill, shadowSize) {
          if (series.fillBetween) {
            series.lines.fill = fill;
          } else {
            series.shadowSize = shadowSize;
            series.lines.lineWidth = lineWidth;
          }
          var rgb = series.color.split(/[\(\)]/g)[1];
          rgb = rgb.split(',');
          rgb[3] = opacity;
          series.color = 'rgba(' + rgb.join(',') + ')';
        },

        /**
         * Allows onDrop to be triggered.
         */
        allowDrop: function(event) {
          if (this.droppable) {
            event.preventDefault();
          }
        },

        /**
         * Handler for on-drop event, fired when a series group is dropped
         * onto this chart-container.
         */
        onDrop: function(event) {
          event.preventDefault();
          var dataTransfer = event.dataTransfer;
          if (dataTransfer.getData('type') != 'seriesdnd') {
            return;
          }
          var data = JSON.parse(dataTransfer.getData('data'));
          if (data) {
            this.addSeriesGroup(data, true);
          }
          this.fireChartStateChangedEvent(this.seriesGroupList);
        },

        legendSeriesDragStart: function(event) {
          this.droppable = false;
        },

        legendSeriesDragEnd: function(event) {
          this.droppable = true;
        },

        /**
         * Gets series's target index if series is a filled line.
         * Filled lines are series that shade the upper and lower bounds
         * (e.g. error bar regions).
         *
         * @param {?Object} state Chart state to send to URI controller which
         *    is used to generate state ID.  If none is specified, only
         *    'this.graphParams' is sent.
         */
        fireChartStateChangedEvent: function(state) {
          this.fire('chartstatechanged', {
            target: this,
            stateName: 'chartstatechanged',
            params: this.graphParams,
            state: state
          });
        },

        onUriChanged: function(event) {
          var detail = event.detail;
          if (detail.stateName != 'chartstatechanged') {
            return;
          }

          var isSameTarget = (detail.id == this.getAttribute('uniqueid') ||
              detail.id == this.$.legend.getAttribute('uniqueid'));
          var shouldReload = false;
          if (isSameTarget) {
            this.set('seriesGroupList', detail.state);
            shouldReload = true;
          }

          if (!graphParamEquals(this.graphParams, detail.params)) {
            this.graphParams = detail.params;
            shouldReload = true;
          }
          if (shouldReload) {
            this.reloadChart();
          }
        },

        /**
         * Gets the current state of the chart.
         * This is called by 'report-page.html' to create page state.
         *
         * @return {Array} List of pair of test path and selected series.
         */
        getState: function() {
          var state = [];
          this.seriesGroupList.forEach(function(seriesGroup) {
            var selected = [];
            var unselected = [];
            var tests = seriesGroup.tests;
            for (var i = 0; i < tests.length; i++) {
              if (tests[i].selected) {
                selected.push(tests[i].name);
              } else {
                unselected.push(tests[i].name);
              }
            }

            if (selected.length == 0 && unselected.length == 0) {
              selected = ['none'];
            } else if (seriesGroup.selection) {
              selected = [seriesGroup.selection];
            }
            selected = arrayUnique(selected);
            state.push([seriesGroup.path, selected]);
          });
          return state;
        },

        listeners: {
          drop: 'onDrop',
          dragover: 'allowDrop'
        }
      });
    })();
  </script>
</dom-module>
