<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/base/ui.html">
<link rel="import" href="/core/tracks/chart_transform.html">
<link rel="import" href="/core/tracks/heading_track.html">

<style>
.chart-track {
  height: 30px;
  position: relative;
}
</style>

<script>
'use strict';

tr.exportTo('tr.c.tracks', function() {

  /**
   * A track that displays a chart.
   *
   * @constructor
   * @extends {HeadingTrack}
   */
  var ChartTrack =
      tr.b.ui.define('chart-track', tr.c.tracks.HeadingTrack);

  ChartTrack.prototype = {
    __proto__: tr.c.tracks.HeadingTrack.prototype,

    decorate: function(viewport) {
      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
      this.classList.add('chart-track');
      this.series_ = undefined;

      // GUID -> {axis: ChartAxis, series: [ChartSeries]}.
      this.axisGuidToAxisData_ = undefined;

      // The maximum top and bottom padding of all series.
      this.topPadding_ = undefined;
      this.bottomPadding_ = undefined;
    },

    get series() {
      return this.series_;
    },

    /**
     * Set the list of chart series to be displayed on this track. The list
     * is assumed to be sorted in increasing z-order (i.e. the last series in
     * the list will be drawn at the top).
     */
    set series(series) {
      this.series_ = series;
      this.calculateAxisDataAndPadding_();
      this.invalidateDrawingContainer();
    },

    get height() {
      return window.getComputedStyle(this).height;
    },

    set height(height) {
      this.style.height = height;
      this.invalidateDrawingContainer();
    },

    get hasVisibleContent() {
      return !!this.series && this.series.length > 0;
    },

    calculateAxisDataAndPadding_: function() {
      if (!this.series_) {
        this.axisGuidToAxisData_ = undefined;
        this.topPadding_ = undefined;
        this.bottomPadding_ = undefined;
        return;
      }

      var axisGuidToAxisData = {};
      var topPadding = 0;
      var bottomPadding = 0;

      this.series_.forEach(function(series) {
        var axis = series.axis;
        var axisGuid = axis.guid;
        if (!(axisGuid in axisGuidToAxisData)) {
          axisGuidToAxisData[axisGuid] = {
            axis: axis,
            series: []
          };
        }
        axisGuidToAxisData[axisGuid].series.push(series);
        topPadding = Math.max(topPadding, series.topPadding);
        bottomPadding = Math.max(bottomPadding, series.bottomPadding);
      }, this);

      this.axisGuidToAxisData_ = axisGuidToAxisData;
      this.topPadding_ = topPadding;
      this.bottomPadding_ = bottomPadding;
    },

    draw: function(type, viewLWorld, viewRWorld) {
      switch (type) {
        case tr.c.tracks.DrawType.GENERAL_EVENT:
          this.drawChart_(viewLWorld, viewRWorld);
          break;
      }
    },

    drawChart_: function(viewLWorld, viewRWorld) {
      if (!this.series_)
        return;

      var ctx = this.context();

      // Get track drawing parameters.
      var displayTransform = this.viewport.currentDisplayTransform;
      var pixelRatio = window.devicePixelRatio || 1;
      var bounds = this.getBoundingClientRect();
      var highDetails = this.viewport.highDetails;

      // Pre-multiply all device-independent pixel parameters with the pixel
      // ratio to avoid unnecessary recomputation in the performance-critical
      // drawing code.
      var width = bounds.width * pixelRatio;
      var height = bounds.height * pixelRatio;
      var topPadding = this.topPadding_ * pixelRatio;
      var bottomPadding = this.bottomPadding_ * pixelRatio;

      // Set up clipping.
      ctx.save();
      ctx.beginPath();
      ctx.rect(0, 0, width, height);
      ctx.clip();

      // Draw all series in the increasing z-order.
      this.series_.forEach(function(series) {
        var chartTransform = new tr.c.tracks.ChartTransform(
            displayTransform, series.axis, width, height, topPadding,
            bottomPadding, pixelRatio);
        series.draw(ctx, chartTransform, highDetails);
      }, this);

      // Stop clipping.
      ctx.restore();
    },

    addEventsToTrackMap: function(eventToTrackMap) {
      // TODO(petrcermak): Consider adding the series to the track map instead
      // of the track (a potential performance optimization).
      this.series_.forEach(function(series) {
        series.points.forEach(function(point) {
          point.addToTrackMap(eventToTrackMap, this);
        }, this);
      }, this);
    },

    addIntersectingEventsInRangeToSelectionInWorldSpace: function(
        loWX, hiWX, viewPixWidthWorld, selection) {
      this.series_.forEach(function(series) {
        series.addIntersectingEventsInRangeToSelectionInWorldSpace(
            loWX, hiWX, viewPixWidthWorld, selection);
      }, this);
    },

    addEventNearToProvidedEventToSelection: function(event, offset, selection) {
      var foundItem = false;
      this.series_.forEach(function(series) {
        foundItem = foundItem || series.addEventNearToProvidedEventToSelection(
            event, offset, selection);
      }, this);
      return foundItem;
    },

    addAllEventsMatchingFilterToSelection: function(filter, selection) {
      // Do nothing.
    },

    addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                         selection) {
      this.series_.forEach(function(series) {
        series.addClosestEventToSelection(
            worldX, worldMaxDist, loY, hiY, selection);
      }, this);
    },

    /**
     * Automatically set the bounds of all axes on this track from the range of
     * values of all series (in this track) associated with each of them.
     *
     * See the description of ChartAxis.autoSetFromRange for the optional
     * configuration argument flags.
     */
    autoSetAllAxes: function(opt_config) {
      tr.b.iterItems(this.axisGuidToAxisData_, function(axisGuid, axisData) {
        var axis = axisData.axis;
        var series = axisData.series;
        axis.autoSetFromSeries(series, opt_config);
      }, this);
    },

    /**
     * Automatically set the bounds of the provided axis from the range of
     * values of all series (in this track) associated with it.
     *
     * See the description of ChartAxis.autoSetFromRange for the optional
     * configuration argument flags.
     */
    autoSetAxis: function(axis, opt_config) {
      var series = this.axisGuidToAxisData_[axis.guid].series;
      axis.autoSetFromSeries(series, opt_config);
    }
  };

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